From 17b8b551ac892bfa8d20d85c5eabbe466a0d87c9 Mon Sep 17 00:00:00 2001
From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com>
Date: Tue, 10 Sep 2019 21:56:07 -0400
Subject: [PATCH 01/28] build: handle arm64 node headers (#20194)
* build: handle arm64 node headers
(cherry picked from commit ff1f224d96fbbd0d745483d48a7ee55dc80f8add)
* node.lib for arm64 needs to go to specific dir
---
script/upload-node-headers.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/script/upload-node-headers.py b/script/upload-node-headers.py
index df8de4a65baf3..066a5370d4173 100755
--- a/script/upload-node-headers.py
+++ b/script/upload-node-headers.py
@@ -53,6 +53,10 @@ def upload_node(bucket, access_key, secret_key, version):
node_lib = os.path.join(DIST_DIR, 'node.lib')
iojs_lib = os.path.join(DIST_DIR, 'win-x86', 'iojs.lib')
v4_node_lib = os.path.join(DIST_DIR, 'win-x86', 'node.lib')
+ elif get_target_arch() == 'arm64':
+ node_lib = os.path.join(DIST_DIR, 'arm64', 'node.lib')
+ iojs_lib = os.path.join(DIST_DIR, 'win-arm64', 'iojs.lib')
+ v4_node_lib = os.path.join(DIST_DIR, 'win-arm64', 'node.lib')
else:
node_lib = os.path.join(DIST_DIR, 'x64', 'node.lib')
iojs_lib = os.path.join(DIST_DIR, 'win-x64', 'iojs.lib')
From 407747b48c47cdeed156a73dde1c47609470c95a Mon Sep 17 00:00:00 2001
From: Electron Bot
Date: Wed, 11 Sep 2019 10:30:11 -0700
Subject: [PATCH 02/28] Bump v6.0.9
---
ELECTRON_VERSION | 2 +-
atom/browser/resources/mac/Info.plist | 4 ++--
atom/browser/resources/win/atom.rc | 8 ++++----
atom/common/atom_version.h | 2 +-
package.json | 2 +-
5 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/ELECTRON_VERSION b/ELECTRON_VERSION
index a0c2cf5cd77f4..fb06ed73fadc6 100644
--- a/ELECTRON_VERSION
+++ b/ELECTRON_VERSION
@@ -1 +1 @@
-6.0.8
\ No newline at end of file
+6.0.9
\ No newline at end of file
diff --git a/atom/browser/resources/mac/Info.plist b/atom/browser/resources/mac/Info.plist
index a04396920eb2b..dc27db7aa5f4c 100644
--- a/atom/browser/resources/mac/Info.plist
+++ b/atom/browser/resources/mac/Info.plist
@@ -17,9 +17,9 @@
CFBundleIconFile
electron.icns
CFBundleVersion
- 6.0.8
+ 6.0.9
CFBundleShortVersionString
- 6.0.8
+ 6.0.9
LSApplicationCategoryType
public.app-category.developer-tools
LSMinimumSystemVersion
diff --git a/atom/browser/resources/win/atom.rc b/atom/browser/resources/win/atom.rc
index dc08516c19edb..480a97c39f1bd 100644
--- a/atom/browser/resources/win/atom.rc
+++ b/atom/browser/resources/win/atom.rc
@@ -50,8 +50,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 6,0,8,0
- PRODUCTVERSION 6,0,8,0
+ FILEVERSION 6,0,9,0
+ PRODUCTVERSION 6,0,9,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -68,12 +68,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "GitHub, Inc."
VALUE "FileDescription", "Electron"
- VALUE "FileVersion", "6.0.8"
+ VALUE "FileVersion", "6.0.9"
VALUE "InternalName", "electron.exe"
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
VALUE "OriginalFilename", "electron.exe"
VALUE "ProductName", "Electron"
- VALUE "ProductVersion", "6.0.8"
+ VALUE "ProductVersion", "6.0.9"
VALUE "SquirrelAwareVersion", "1"
END
END
diff --git a/atom/common/atom_version.h b/atom/common/atom_version.h
index 89b82d52a1553..e26c0a34eb2ff 100644
--- a/atom/common/atom_version.h
+++ b/atom/common/atom_version.h
@@ -7,7 +7,7 @@
#define ATOM_MAJOR_VERSION 6
#define ATOM_MINOR_VERSION 0
-#define ATOM_PATCH_VERSION 8
+#define ATOM_PATCH_VERSION 9
// clang-format off
// #define ATOM_PRE_RELEASE_VERSION
// clang-format on
diff --git a/package.json b/package.json
index e928214d0649e..46b1d19feec1d 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "electron",
- "version": "6.0.8",
+ "version": "6.0.9",
"repository": "https://github.com/electron/electron",
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
"devDependencies": {
From e3be3239624cfb51d1066893f07f3e8e6bc08df3 Mon Sep 17 00:00:00 2001
From: Samuel Attard
Date: Tue, 17 Sep 2019 07:49:08 -0700
Subject: [PATCH 03/28] docs: remove dash that broke the return type parser
(#20246)
---
docs/api/dialog.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/api/dialog.md b/docs/api/dialog.md
index e01fc8a3fdbfc..849e27f7283ff 100644
--- a/docs/api/dialog.md
+++ b/docs/api/dialog.md
@@ -117,7 +117,7 @@ dialog.showOpenDialogSync(mainWindow, {
Returns `Promise
'))
+
+const hasFormat = clipboard.has('selection
')
+console.log(hasFormat)
+// 'true' or 'false
```
### `clipboard.read(format)` _Experimental_
@@ -157,14 +214,33 @@ Returns `String` - Reads `format` type from the clipboard.
Returns `Buffer` - Reads `format` type from the clipboard.
+```js
+const { clipboard } = require('electron')
+
+const buffer = Buffer.from('this is binary', 'utf8')
+clipboard.writeBuffer('public.utf8-plain-text', buffer)
+
+const ret = clipboard.readBuffer('public.utf8-plain-text')
+
+console.log(buffer.equals(out))
+// true
+```
+
### `clipboard.writeBuffer(format, buffer[, type])` _Experimental_
* `format` String
* `buffer` Buffer
-* `type` String (optional) - Can be `selection` or `clipboard`. `selection` is only available on Linux.
+* `type` String (optional) - Can be `selection` or `clipboard`; default is 'clipboard'. `selection` is only available on Linux.
Writes the `buffer` into the clipboard as `format`.
+```js
+const { clipboard } = require('electron')
+
+const buffer = Buffer.from('writeBuffer', 'utf8')
+clipboard.writeBuffer('public.utf8-plain-text', buffer)
+```
+
### `clipboard.write(data[, type])`
* `data` Object
@@ -172,11 +248,30 @@ Writes the `buffer` into the clipboard as `format`.
* `html` String (optional)
* `image` [NativeImage](native-image.md) (optional)
* `rtf` String (optional)
- * `bookmark` String (optional) - The title of the url at `text`.
-* `type` String (optional) - Can be `selection` or `clipboard`. `selection` is only available on Linux.
+ * `bookmark` String (optional) - The title of the URL at `text`.
+* `type` String (optional) - Can be `selection` or `clipboard`; default is 'clipboard'. `selection` is only available on Linux.
-```javascript
+Writes `data` to the clipboard.
+
+```js
const { clipboard } = require('electron')
-clipboard.write({ text: 'test', html: 'test' })
+
+clipboard.write({
+ text: 'test',
+ html: 'Hi',
+ rtf: '{\\rtf1\\utf8 text}',
+ bookmark: 'a title'
+})
+
+console.log(clipboard.readText())
+// 'test'
+
+console.log(clipboard.readHTML())
+// Hi
+
+console.log(clipboard.readRTF())
+// '{\\rtf1\\utf8 text}'
+
+console.log(clipboard.readBookmark())
+// { title: 'a title', url: 'test' }
```
-Writes `data` to the clipboard.
From 15c89c8262e42e0f1f5ab36f91676ca3f3b24967 Mon Sep 17 00:00:00 2001
From: Shelley Vohr
Date: Thu, 19 Sep 2019 11:29:35 -0700
Subject: [PATCH 09/28] fix: crash when exiting simple fullscreen on macOS
(#20144) (#20282)
---
atom/browser/native_window_mac.h | 2 +-
atom/browser/ui/cocoa/atom_ns_window.mm | 10 ++++++++--
spec/api-browser-window-spec.js | 11 +++++++++++
3 files changed, 20 insertions(+), 3 deletions(-)
diff --git a/atom/browser/native_window_mac.h b/atom/browser/native_window_mac.h
index 7fcb51713161f..4ed66ecffd35c 100644
--- a/atom/browser/native_window_mac.h
+++ b/atom/browser/native_window_mac.h
@@ -157,7 +157,7 @@ class NativeWindowMac : public NativeWindow {
AtomTouchBar* touch_bar() const { return touch_bar_.get(); }
bool zoom_to_page_width() const { return zoom_to_page_width_; }
bool fullscreen_window_title() const { return fullscreen_window_title_; }
- bool simple_fullscreen() const { return always_simple_fullscreen_; }
+ bool always_simple_fullscreen() const { return always_simple_fullscreen_; }
protected:
// views::WidgetDelegate:
diff --git a/atom/browser/ui/cocoa/atom_ns_window.mm b/atom/browser/ui/cocoa/atom_ns_window.mm
index 9531ab7803f30..4ccd8a15beff1 100644
--- a/atom/browser/ui/cocoa/atom_ns_window.mm
+++ b/atom/browser/ui/cocoa/atom_ns_window.mm
@@ -174,8 +174,14 @@ - (void)performClose:(id)sender {
}
- (void)toggleFullScreenMode:(id)sender {
- if (shell_->simple_fullscreen())
- shell_->SetSimpleFullScreen(!shell_->IsSimpleFullScreen());
+ bool is_simple_fs = shell_->IsSimpleFullScreen();
+ bool always_simple_fs = shell_->always_simple_fullscreen();
+
+ // If we're in simple fullscreen mode and trying to exit it
+ // we need to ensure we exit it properly to prevent a crash
+ // with NSWindowStyleMaskTitled mode
+ if (is_simple_fs || always_simple_fs)
+ shell_->SetSimpleFullScreen(!is_simple_fs);
else
[super toggleFullScreen:sender];
}
diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js
index 53b9e1de64b00..b99bcbfb7687e 100644
--- a/spec/api-browser-window-spec.js
+++ b/spec/api-browser-window-spec.js
@@ -3090,6 +3090,17 @@ describe('BrowserWindow module', () => {
w.setFullScreen(true)
})
+ it('does not crash when exiting simpleFullScreen', (done) => {
+ w.destroy()
+ w = new BrowserWindow()
+ w.setSimpleFullScreen(true)
+
+ setTimeout(() => {
+ w.setFullScreen(!w.isFullScreen())
+ done()
+ }, 1000)
+ })
+
it('should not be changed by setKiosk method', (done) => {
w.destroy()
w = new BrowserWindow()
From ce31dc359181f5a2a610bd4ad821a61aef15f905 Mon Sep 17 00:00:00 2001
From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com>
Date: Fri, 20 Sep 2019 10:20:19 -0400
Subject: [PATCH 10/28] ci: actually kill leftover processes on WOA testing
(#20292)
* ci: only kill WOA processes if they are running
(cherry picked from commit 844752cd97c4b010f0467bbfdfe4940934945523)
* ci: actually kill leftover processes on WOA testing
(cherry picked from commit a76d2d8e53458447579b865febbfaef5b2921f94)
---
azure-pipelines-woa.yml | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/azure-pipelines-woa.yml b/azure-pipelines-woa.yml
index f347dc121bd9d..352123cd04130 100644
--- a/azure-pipelines-woa.yml
+++ b/azure-pipelines-woa.yml
@@ -77,8 +77,8 @@ steps:
python electron\script\verify-ffmpeg.py --build-dir out\Default --source-root %cd% --ffmpeg-path out\ffmpeg
displayName: 'Verify ffmpeg'
-- script: |
- taskkill /F /IM electron.exe
- taskkill /F /IM MicrosoftEdge.exe
+- powershell: |
+ Get-Process | Where Name –Like "electron*" | Stop-Process
+ Get-Process | Where Name –Like "MicrosoftEdge*" | Stop-Process
displayName: 'Kill processes left running from last test run'
condition: always()
\ No newline at end of file
From 0450ee952456b204481b086234d0a7195b1cfe93 Mon Sep 17 00:00:00 2001
From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com>
Date: Fri, 20 Sep 2019 07:44:21 -0700
Subject: [PATCH 11/28] fix: correct 'Entire screen' to ' Entire Screen'
(#20301)
---
electron_strings.grdp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/electron_strings.grdp b/electron_strings.grdp
index 78324e76f5ae8..f827eed718b08 100644
--- a/electron_strings.grdp
+++ b/electron_strings.grdp
@@ -13,7 +13,7 @@
- Entire screen
+ Entire Screen
{SCREEN_INDEX, plural, =1{Screen #} other{Screen #}}
From 886e636b1357d3fe5cb4eaf51889ac89b9e7179a Mon Sep 17 00:00:00 2001
From: Birunthan Mohanathas
Date: Mon, 30 Sep 2019 10:46:41 -0700
Subject: [PATCH 12/28] fix: Make the `--disable-color-correct-rendering`
switch work again (backport) (#20358)
---
.../disable_color_correct_rendering.patch | 53 +++++++++++++++++++
1 file changed, 53 insertions(+)
diff --git a/patches/common/chromium/disable_color_correct_rendering.patch b/patches/common/chromium/disable_color_correct_rendering.patch
index 40ab3205de110..4a024fdc19039 100644
--- a/patches/common/chromium/disable_color_correct_rendering.patch
+++ b/patches/common/chromium/disable_color_correct_rendering.patch
@@ -18,6 +18,23 @@ This can be removed once web content (including WebGL) learn how
to deal with color spaces. That is being tracked at
https://crbug.com/634542 and https://crbug.com/711107.
+diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
+index e2921219d253dbb198bd089811cc102aeec594cc..62290a30dee8d51df6e1f771894832b4105c2dd3 100644
+--- a/cc/trees/layer_tree_host_impl.cc
++++ b/cc/trees/layer_tree_host_impl.cc
+@@ -1625,6 +1625,12 @@ const gfx::ColorSpace& LayerTreeHostImpl::GetRasterColorSpace() const {
+
+ const gfx::ColorSpace& LayerTreeHostImpl::GetRasterColorSpaceAndId(
+ int* id) const {
++ if (!settings_.enable_color_correct_rendering) {
++ static gfx::ColorSpace invalid_color_space;
++ *id = -1;
++ return invalid_color_space;
++ }
++
+ const gfx::ColorSpace* result = nullptr;
+ // The pending tree will have the most recently updated color space, so
+ // prefer that.
diff --git a/cc/trees/layer_tree_settings.h b/cc/trees/layer_tree_settings.h
index 092fb1b7ea3626b7649472c35ec20bf1a6aaf4cd..fed8dd322faba387ebd0508228f847766a76011e 100644
--- a/cc/trees/layer_tree_settings.h
@@ -248,6 +265,42 @@ index a450561913e274b36ece94c22bae7b14930db36e..3b9a0a5cef0ec2fc02d4e2d1b0e4e1da
// Checkerimaging is not supported for synchronous single-threaded mode, which
// is what the renderer uses if its not threaded.
settings.enable_checker_imaging =
+diff --git a/third_party/blink/renderer/platform/graphics/canvas_color_params.cc b/third_party/blink/renderer/platform/graphics/canvas_color_params.cc
+index 9e5b58dc78b05491d1154b25b5b9c8c55b883b07..8524fd9f090fbb5cb0e37b1a6205d77917e9f221 100644
+--- a/third_party/blink/renderer/platform/graphics/canvas_color_params.cc
++++ b/third_party/blink/renderer/platform/graphics/canvas_color_params.cc
+@@ -11,6 +11,7 @@
+ #include "third_party/khronos/GLES3/gl3.h"
+ #include "third_party/skia/include/core/SkSurfaceProps.h"
+ #include "ui/gfx/color_space.h"
++#include "ui/gfx/switches.h"
+
+ namespace blink {
+
+@@ -81,6 +82,11 @@ uint8_t CanvasColorParams::BytesPerPixel() const {
+ }
+
+ gfx::ColorSpace CanvasColorParams::GetSamplerGfxColorSpace() const {
++ auto* cmd_line = base::CommandLine::ForCurrentProcess();
++ if (cmd_line->HasSwitch(switches::kDisableColorCorrectRendering)) {
++ return gfx::ColorSpace();
++ }
++
+ gfx::ColorSpace::PrimaryID primary_id = GetPrimaryID(color_space_);
+
+ // TODO(ccameron): This needs to take into account whether or not this texture
+@@ -94,6 +100,11 @@ gfx::ColorSpace CanvasColorParams::GetSamplerGfxColorSpace() const {
+ }
+
+ gfx::ColorSpace CanvasColorParams::GetStorageGfxColorSpace() const {
++ auto* cmd_line = base::CommandLine::ForCurrentProcess();
++ if (cmd_line->HasSwitch(switches::kDisableColorCorrectRendering)) {
++ return gfx::ColorSpace();
++ }
++
+ gfx::ColorSpace::PrimaryID primary_id = GetPrimaryID(color_space_);
+
+ gfx::ColorSpace::TransferID transfer_id =
diff --git a/ui/gfx/mac/io_surface.cc b/ui/gfx/mac/io_surface.cc
index 88ec94963569588ed2882193a28197879dcb1090..eae37577bc9b1872c0162f55de218553eed61587 100644
--- a/ui/gfx/mac/io_surface.cc
From e472efbea20097de9f78a1e68b16030087c28323 Mon Sep 17 00:00:00 2001
From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com>
Date: Tue, 1 Oct 2019 15:06:23 -0400
Subject: [PATCH 13/28] fix: correctly crash when there is no crashReporter
(#20396)
* fix: correctly crash when there is no crashReporter
* test: correctly crash when there is crashReporter
---
atom/common/crash_reporter/crash_reporter_win.cc | 12 ++++++++++--
spec/api-crash-reporter-spec.js | 10 ++++++++++
spec/fixtures/crash-app/main.js | 5 +++++
spec/fixtures/crash-app/package.json | 4 ++++
4 files changed, 29 insertions(+), 2 deletions(-)
create mode 100644 spec/fixtures/crash-app/main.js
create mode 100644 spec/fixtures/crash-app/package.json
diff --git a/atom/common/crash_reporter/crash_reporter_win.cc b/atom/common/crash_reporter/crash_reporter_win.cc
index 6d48b9533c2ef..34d7999d8d23b 100644
--- a/atom/common/crash_reporter/crash_reporter_win.cc
+++ b/atom/common/crash_reporter/crash_reporter_win.cc
@@ -28,9 +28,17 @@ namespace {
#if defined(_WIN64)
int CrashForException(EXCEPTION_POINTERS* info) {
auto* reporter = crash_reporter::CrashReporterWin::GetInstance();
- if (reporter->IsInitialized())
+ if (reporter->IsInitialized()) {
reporter->GetCrashpadClient().DumpAndCrash(info);
- return EXCEPTION_CONTINUE_SEARCH;
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+
+ // When there is exception and we do not have crashReporter set up, we just
+ // let the execution continue and crash, which is the default behavior.
+ //
+ // We must not return EXCEPTION_CONTINUE_SEARCH here, as it would end up with
+ // busy loop when there is no exception handler in the program.
+ return EXCEPTION_CONTINUE_EXECUTION;
}
#endif
diff --git a/spec/api-crash-reporter-spec.js b/spec/api-crash-reporter-spec.js
index bbff0a25cd79e..2a2046ef56640 100644
--- a/spec/api-crash-reporter-spec.js
+++ b/spec/api-crash-reporter-spec.js
@@ -373,6 +373,16 @@ describe('crashReporter module', () => {
assert(!('hello' in crashReporter.getParameters()))
})
})
+
+ describe('when not started', () => {
+ it('does not prevent process from crashing', (done) => {
+ const appPath = path.join(fixtures, 'api', 'cookie-app')
+ const appProcess = childProcess.spawn(process.execPath, [appPath])
+ appProcess.once('close', () => {
+ done()
+ })
+ })
+ })
})
const waitForCrashReport = () => {
diff --git a/spec/fixtures/crash-app/main.js b/spec/fixtures/crash-app/main.js
new file mode 100644
index 0000000000000..e279216218822
--- /dev/null
+++ b/spec/fixtures/crash-app/main.js
@@ -0,0 +1,5 @@
+const { app } = require('electron')
+
+app.on('ready', () => {
+ process.crash()
+})
diff --git a/spec/fixtures/crash-app/package.json b/spec/fixtures/crash-app/package.json
new file mode 100644
index 0000000000000..e03fc08f1f79f
--- /dev/null
+++ b/spec/fixtures/crash-app/package.json
@@ -0,0 +1,4 @@
+{
+ "name": "electron-crash-app",
+ "main": "main.js"
+}
From 4e417e21b8700772627753916032648c524f27e2 Mon Sep 17 00:00:00 2001
From: Electron Bot
Date: Tue, 1 Oct 2019 12:08:35 -0700
Subject: [PATCH 14/28] Bump v6.0.11
---
ELECTRON_VERSION | 2 +-
atom/browser/resources/mac/Info.plist | 4 ++--
atom/browser/resources/win/atom.rc | 8 ++++----
atom/common/atom_version.h | 2 +-
package.json | 2 +-
5 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/ELECTRON_VERSION b/ELECTRON_VERSION
index c5a1e4c4361df..cb372c07bfa82 100644
--- a/ELECTRON_VERSION
+++ b/ELECTRON_VERSION
@@ -1 +1 @@
-6.0.10
\ No newline at end of file
+6.0.11
\ No newline at end of file
diff --git a/atom/browser/resources/mac/Info.plist b/atom/browser/resources/mac/Info.plist
index 47f87cb46f686..d3efa6a713058 100644
--- a/atom/browser/resources/mac/Info.plist
+++ b/atom/browser/resources/mac/Info.plist
@@ -17,9 +17,9 @@
CFBundleIconFile
electron.icns
CFBundleVersion
- 6.0.10
+ 6.0.11
CFBundleShortVersionString
- 6.0.10
+ 6.0.11
LSApplicationCategoryType
public.app-category.developer-tools
LSMinimumSystemVersion
diff --git a/atom/browser/resources/win/atom.rc b/atom/browser/resources/win/atom.rc
index 6f5ebfccfafd7..f378c8dc44a2b 100644
--- a/atom/browser/resources/win/atom.rc
+++ b/atom/browser/resources/win/atom.rc
@@ -50,8 +50,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 6,0,10,0
- PRODUCTVERSION 6,0,10,0
+ FILEVERSION 6,0,11,0
+ PRODUCTVERSION 6,0,11,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -68,12 +68,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "GitHub, Inc."
VALUE "FileDescription", "Electron"
- VALUE "FileVersion", "6.0.10"
+ VALUE "FileVersion", "6.0.11"
VALUE "InternalName", "electron.exe"
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
VALUE "OriginalFilename", "electron.exe"
VALUE "ProductName", "Electron"
- VALUE "ProductVersion", "6.0.10"
+ VALUE "ProductVersion", "6.0.11"
VALUE "SquirrelAwareVersion", "1"
END
END
diff --git a/atom/common/atom_version.h b/atom/common/atom_version.h
index 182a5a53cd67d..2929e61ed841d 100644
--- a/atom/common/atom_version.h
+++ b/atom/common/atom_version.h
@@ -7,7 +7,7 @@
#define ATOM_MAJOR_VERSION 6
#define ATOM_MINOR_VERSION 0
-#define ATOM_PATCH_VERSION 10
+#define ATOM_PATCH_VERSION 11
// clang-format off
// #define ATOM_PRE_RELEASE_VERSION
// clang-format on
diff --git a/package.json b/package.json
index 0d2e4e4b405b9..f332706dc9e8b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "electron",
- "version": "6.0.10",
+ "version": "6.0.11",
"repository": "https://github.com/electron/electron",
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
"devDependencies": {
From 99a0581d0d0e6735abc6ab5dd4b4af97b61fa7d8 Mon Sep 17 00:00:00 2001
From: Milan Burda
Date: Wed, 2 Oct 2019 11:03:18 +0200
Subject: [PATCH 15/28] fix: allow paths to asar archives to contain the .asar
extension in directories (#20342) (#20402)
---
atom/common/api/atom_api_asar.cc | 16 +
atom/common/asar/asar_util.cc | 20 +-
atom/common/asar/asar_util.h | 3 +-
lib/common/asar.js | 19 +-
spec/api-protocol-spec.js | 4 +-
spec/asar-spec.js | 311 +++++++++---------
spec/fixtures/module/no-asar.js | 2 +-
spec/fixtures/no-proprietary-codecs.js | 2 +-
spec/fixtures/{asar => test.asar}/a.asar | Bin
spec/fixtures/{asar => test.asar}/echo.asar | Bin
spec/fixtures/{asar => test.asar}/empty.asar | Bin
spec/fixtures/{asar => test.asar}/file | 0
spec/fixtures/{asar => test.asar}/logo.asar | Bin
spec/fixtures/{asar => test.asar}/script.asar | Bin
spec/fixtures/{asar => test.asar}/unpack.asar | Bin
.../unpack.asar.unpacked/a.txt | 0
.../unpack.asar.unpacked/atom.png | Bin
spec/fixtures/{asar => test.asar}/video.asar | Bin
spec/fixtures/{asar => test.asar}/web.asar | Bin
19 files changed, 196 insertions(+), 181 deletions(-)
rename spec/fixtures/{asar => test.asar}/a.asar (100%)
rename spec/fixtures/{asar => test.asar}/echo.asar (100%)
rename spec/fixtures/{asar => test.asar}/empty.asar (100%)
rename spec/fixtures/{asar => test.asar}/file (100%)
rename spec/fixtures/{asar => test.asar}/logo.asar (100%)
rename spec/fixtures/{asar => test.asar}/script.asar (100%)
rename spec/fixtures/{asar => test.asar}/unpack.asar (100%)
rename spec/fixtures/{asar => test.asar}/unpack.asar.unpacked/a.txt (100%)
rename spec/fixtures/{asar => test.asar}/unpack.asar.unpacked/atom.png (100%)
rename spec/fixtures/{asar => test.asar}/video.asar (100%)
rename spec/fixtures/{asar => test.asar}/web.asar (100%)
diff --git a/atom/common/api/atom_api_asar.cc b/atom/common/api/atom_api_asar.cc
index 00fad1275f297..0551bc8834a1b 100644
--- a/atom/common/api/atom_api_asar.cc
+++ b/atom/common/api/atom_api_asar.cc
@@ -7,6 +7,7 @@
#include
#include "atom/common/asar/archive.h"
+#include "atom/common/asar/asar_util.h"
#include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/file_path_converter.h"
#include "atom/common/node_includes.h"
@@ -127,12 +128,27 @@ void InitAsarSupport(v8::Isolate* isolate, v8::Local require) {
&asar_init_params, &asar_init_args, nullptr);
}
+v8::Local SplitPath(v8::Isolate* isolate,
+ const base::FilePath& path) {
+ mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
+ base::FilePath asar_path, file_path;
+ if (asar::GetAsarArchivePath(path, &asar_path, &file_path, true)) {
+ dict.Set("isAsar", true);
+ dict.Set("asarPath", asar_path);
+ dict.Set("filePath", file_path);
+ } else {
+ dict.Set("isAsar", false);
+ }
+ return dict.GetHandle();
+}
+
void Initialize(v8::Local exports,
v8::Local unused,
v8::Local context,
void* priv) {
mate::Dictionary dict(context->GetIsolate(), exports);
dict.SetMethod("createArchive", &Archive::Create);
+ dict.SetMethod("splitPath", &SplitPath);
dict.SetMethod("initAsarSupport", &InitAsarSupport);
}
diff --git a/atom/common/asar/asar_util.cc b/atom/common/asar/asar_util.cc
index b564a75dc7223..7934c3183a2e9 100644
--- a/atom/common/asar/asar_util.cc
+++ b/atom/common/asar/asar_util.cc
@@ -13,6 +13,7 @@
#include "base/lazy_instance.h"
#include "base/stl_util.h"
#include "base/threading/thread_local.h"
+#include "base/threading/thread_restrictions.h"
namespace asar {
@@ -25,6 +26,17 @@ base::LazyInstance>::Leaky
const base::FilePath::CharType kAsarExtension[] = FILE_PATH_LITERAL(".asar");
+std::map g_is_directory_cache;
+
+bool IsDirectoryCached(const base::FilePath& path) {
+ auto it = g_is_directory_cache.find(path);
+ if (it != g_is_directory_cache.end()) {
+ return it->second;
+ }
+ base::ThreadRestrictions::ScopedAllowIO allow_io;
+ return g_is_directory_cache[path] = base::DirectoryExists(path);
+}
+
} // namespace
std::shared_ptr GetOrCreateAsarArchive(const base::FilePath& path) {
@@ -47,11 +59,12 @@ void ClearArchives() {
bool GetAsarArchivePath(const base::FilePath& full_path,
base::FilePath* asar_path,
- base::FilePath* relative_path) {
+ base::FilePath* relative_path,
+ bool allow_root) {
base::FilePath iter = full_path;
while (true) {
base::FilePath dirname = iter.DirName();
- if (iter.MatchesExtension(kAsarExtension))
+ if (iter.MatchesExtension(kAsarExtension) && !IsDirectoryCached(iter))
break;
else if (iter == dirname)
return false;
@@ -59,7 +72,8 @@ bool GetAsarArchivePath(const base::FilePath& full_path,
}
base::FilePath tail;
- if (!iter.AppendRelativePath(full_path, &tail))
+ if (!((allow_root && iter == full_path) ||
+ iter.AppendRelativePath(full_path, &tail)))
return false;
*asar_path = iter;
diff --git a/atom/common/asar/asar_util.h b/atom/common/asar/asar_util.h
index 90ffb9b46a300..f934845e514d0 100644
--- a/atom/common/asar/asar_util.h
+++ b/atom/common/asar/asar_util.h
@@ -25,7 +25,8 @@ void ClearArchives();
// Separates the path to Archive out.
bool GetAsarArchivePath(const base::FilePath& full_path,
base::FilePath* asar_path,
- base::FilePath* relative_path);
+ base::FilePath* relative_path,
+ bool allow_root = false);
// Same with base::ReadFileToString but supports asar Archive.
bool ReadFileToString(const base::FilePath& path, std::string* contents);
diff --git a/lib/common/asar.js b/lib/common/asar.js
index f0977753d0704..caf18c2c4c9c7 100644
--- a/lib/common/asar.js
+++ b/lib/common/asar.js
@@ -40,8 +40,6 @@
return newArchive
}
- const ASAR_EXTENSION = '.asar'
-
// Separate asar package's path from full path.
const splitPath = archivePathOrBuffer => {
// Shortcut for disabled asar.
@@ -54,22 +52,7 @@
}
if (typeof archivePath !== 'string') return { isAsar: false }
- if (archivePath.endsWith(ASAR_EXTENSION)) {
- return { isAsar: true, asarPath: archivePath, filePath: '' }
- }
-
- archivePath = path.normalize(archivePath)
- const index = archivePath.lastIndexOf(`${ASAR_EXTENSION}${path.sep}`)
- if (index === -1) return { isAsar: false }
-
- // E.g. for "//some/path/to/archive.asar/then/internal.file"...
- return {
- isAsar: true,
- // "//some/path/to/archive.asar"
- asarPath: archivePath.substr(0, index + ASAR_EXTENSION.length),
- // "then/internal.file" (with a path separator excluded)
- filePath: archivePath.substr(index + ASAR_EXTENSION.length + 1)
- }
+ return asar.splitPath(path.normalize(archivePath))
}
// Convert asar archive's Stats object to fs's Stats object.
diff --git a/spec/api-protocol-spec.js b/spec/api-protocol-spec.js
index 8b53567894b41..dec87a03c3c91 100644
--- a/spec/api-protocol-spec.js
+++ b/spec/api-protocol-spec.js
@@ -280,7 +280,7 @@ describe('protocol module', () => {
})
describe('protocol.registerFileProtocol', () => {
- const filePath = path.join(__dirname, 'fixtures', 'asar', 'a.asar', 'file1')
+ const filePath = path.join(__dirname, 'fixtures', 'test.asar', 'a.asar', 'file1')
const fileContent = require('fs').readFileSync(filePath)
const normalPath = path.join(__dirname, 'fixtures', 'pages', 'a.html')
const normalContent = require('fs').readFileSync(normalPath)
@@ -394,7 +394,7 @@ describe('protocol module', () => {
})
it('fails when sending unexist-file', (done) => {
- const fakeFilePath = path.join(__dirname, 'fixtures', 'asar', 'a.asar', 'not-exist')
+ const fakeFilePath = path.join(__dirname, 'fixtures', 'test.asar', 'a.asar', 'not-exist')
const handler = (request, callback) => callback(fakeFilePath)
protocol.registerFileProtocol(protocolName, handler, (error) => {
if (error) return done(error)
diff --git a/spec/asar-spec.js b/spec/asar-spec.js
index a8a7b4aa07246..37e13a93d1ba4 100644
--- a/spec/asar-spec.js
+++ b/spec/asar-spec.js
@@ -28,10 +28,11 @@ async function expectToThrowErrorWithCode (func, code) {
describe('asar package', function () {
const fixtures = path.join(__dirname, 'fixtures')
+ const asarDir = path.join(fixtures, 'test.asar')
describe('node api', function () {
it('supports paths specified as a Buffer', function () {
- const file = Buffer.from(path.join(fixtures, 'asar', 'a.asar', 'file1'))
+ const file = Buffer.from(path.join(asarDir, 'a.asar', 'file1'))
assert.strictEqual(fs.existsSync(file), true)
})
@@ -45,35 +46,35 @@ describe('asar package', function () {
})
it('reads a normal file', function () {
- const file1 = path.join(fixtures, 'asar', 'a.asar', 'file1')
+ const file1 = path.join(asarDir, 'a.asar', 'file1')
assert.strictEqual(fs.readFileSync(file1).toString().trim(), 'file1')
- const file2 = path.join(fixtures, 'asar', 'a.asar', 'file2')
+ const file2 = path.join(asarDir, 'a.asar', 'file2')
assert.strictEqual(fs.readFileSync(file2).toString().trim(), 'file2')
- const file3 = path.join(fixtures, 'asar', 'a.asar', 'file3')
+ const file3 = path.join(asarDir, 'a.asar', 'file3')
assert.strictEqual(fs.readFileSync(file3).toString().trim(), 'file3')
})
it('reads from a empty file', function () {
- const file = path.join(fixtures, 'asar', 'empty.asar', 'file1')
+ const file = path.join(asarDir, 'empty.asar', 'file1')
const buffer = fs.readFileSync(file)
assert.strictEqual(buffer.length, 0)
assert.strictEqual(buffer.toString(), '')
})
it('reads a linked file', function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'link1')
+ const p = path.join(asarDir, 'a.asar', 'link1')
assert.strictEqual(fs.readFileSync(p).toString().trim(), 'file1')
})
it('reads a file from linked directory', function () {
- const p1 = path.join(fixtures, 'asar', 'a.asar', 'link2', 'file1')
+ const p1 = path.join(asarDir, 'a.asar', 'link2', 'file1')
assert.strictEqual(fs.readFileSync(p1).toString().trim(), 'file1')
- const p2 = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2', 'file1')
+ const p2 = path.join(asarDir, 'a.asar', 'link2', 'link2', 'file1')
assert.strictEqual(fs.readFileSync(p2).toString().trim(), 'file1')
})
it('throws ENOENT error when can not find file', function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist')
+ const p = path.join(asarDir, 'a.asar', 'not-exist')
const throws = function () {
fs.readFileSync(p)
}
@@ -81,7 +82,7 @@ describe('asar package', function () {
})
it('passes ENOENT error to callback when can not find file', function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist')
+ const p = path.join(asarDir, 'a.asar', 'not-exist')
let async = false
fs.readFile(p, function (e) {
assert(async)
@@ -91,14 +92,14 @@ describe('asar package', function () {
})
it('reads a normal file with unpacked files', function () {
- const p = path.join(fixtures, 'asar', 'unpack.asar', 'a.txt')
+ const p = path.join(asarDir, 'unpack.asar', 'a.txt')
assert.strictEqual(fs.readFileSync(p).toString().trim(), 'a')
})
})
describe('fs.readFile', function () {
it('reads a normal file', function (done) {
- const p = path.join(fixtures, 'asar', 'a.asar', 'file1')
+ const p = path.join(asarDir, 'a.asar', 'file1')
fs.readFile(p, function (err, content) {
assert.strictEqual(err, null)
assert.strictEqual(String(content).trim(), 'file1')
@@ -107,7 +108,7 @@ describe('asar package', function () {
})
it('reads from a empty file', function (done) {
- const p = path.join(fixtures, 'asar', 'empty.asar', 'file1')
+ const p = path.join(asarDir, 'empty.asar', 'file1')
fs.readFile(p, function (err, content) {
assert.strictEqual(err, null)
assert.strictEqual(String(content), '')
@@ -116,7 +117,7 @@ describe('asar package', function () {
})
it('reads from a empty file with encoding', function (done) {
- const p = path.join(fixtures, 'asar', 'empty.asar', 'file1')
+ const p = path.join(asarDir, 'empty.asar', 'file1')
fs.readFile(p, 'utf8', function (err, content) {
assert.strictEqual(err, null)
assert.strictEqual(content, '')
@@ -125,7 +126,7 @@ describe('asar package', function () {
})
it('reads a linked file', function (done) {
- const p = path.join(fixtures, 'asar', 'a.asar', 'link1')
+ const p = path.join(asarDir, 'a.asar', 'link1')
fs.readFile(p, function (err, content) {
assert.strictEqual(err, null)
assert.strictEqual(String(content).trim(), 'file1')
@@ -134,7 +135,7 @@ describe('asar package', function () {
})
it('reads a file from linked directory', function (done) {
- const p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2', 'file1')
+ const p = path.join(asarDir, 'a.asar', 'link2', 'link2', 'file1')
fs.readFile(p, function (err, content) {
assert.strictEqual(err, null)
assert.strictEqual(String(content).trim(), 'file1')
@@ -143,7 +144,7 @@ describe('asar package', function () {
})
it('throws ENOENT error when can not find file', function (done) {
- const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist')
+ const p = path.join(asarDir, 'a.asar', 'not-exist')
fs.readFile(p, function (err) {
assert.strictEqual(err.code, 'ENOENT')
done()
@@ -153,44 +154,44 @@ describe('asar package', function () {
describe('fs.promises.readFile', function () {
it('reads a normal file', async function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'file1')
+ const p = path.join(asarDir, 'a.asar', 'file1')
const content = await fs.promises.readFile(p)
assert.strictEqual(String(content).trim(), 'file1')
})
it('reads from a empty file', async function () {
- const p = path.join(fixtures, 'asar', 'empty.asar', 'file1')
+ const p = path.join(asarDir, 'empty.asar', 'file1')
const content = await fs.promises.readFile(p)
assert.strictEqual(String(content), '')
})
it('reads from a empty file with encoding', async function () {
- const p = path.join(fixtures, 'asar', 'empty.asar', 'file1')
+ const p = path.join(asarDir, 'empty.asar', 'file1')
const content = await fs.promises.readFile(p, 'utf8')
assert.strictEqual(content, '')
})
it('reads a linked file', async function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'link1')
+ const p = path.join(asarDir, 'a.asar', 'link1')
const content = await fs.promises.readFile(p)
assert.strictEqual(String(content).trim(), 'file1')
})
it('reads a file from linked directory', async function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2', 'file1')
+ const p = path.join(asarDir, 'a.asar', 'link2', 'link2', 'file1')
const content = await fs.promises.readFile(p)
assert.strictEqual(String(content).trim(), 'file1')
})
it('throws ENOENT error when can not find file', async function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist')
+ const p = path.join(asarDir, 'a.asar', 'not-exist')
await expectToThrowErrorWithCode(() => fs.promises.readFile(p), 'ENOENT')
})
})
describe('fs.copyFile', function () {
it('copies a normal file', function (done) {
- const p = path.join(fixtures, 'asar', 'a.asar', 'file1')
+ const p = path.join(asarDir, 'a.asar', 'file1')
const dest = temp.path()
fs.copyFile(p, dest, function (err) {
assert.strictEqual(err, null)
@@ -200,7 +201,7 @@ describe('asar package', function () {
})
it('copies a unpacked file', function (done) {
- const p = path.join(fixtures, 'asar', 'unpack.asar', 'a.txt')
+ const p = path.join(asarDir, 'unpack.asar', 'a.txt')
const dest = temp.path()
fs.copyFile(p, dest, function (err) {
assert.strictEqual(err, null)
@@ -212,14 +213,14 @@ describe('asar package', function () {
describe('fs.promises.copyFile', function () {
it('copies a normal file', async function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'file1')
+ const p = path.join(asarDir, 'a.asar', 'file1')
const dest = temp.path()
await fs.promises.copyFile(p, dest)
assert(fs.readFileSync(p).equals(fs.readFileSync(dest)))
})
it('copies a unpacked file', async function () {
- const p = path.join(fixtures, 'asar', 'unpack.asar', 'a.txt')
+ const p = path.join(asarDir, 'unpack.asar', 'a.txt')
const dest = temp.path()
await fs.promises.copyFile(p, dest)
assert(fs.readFileSync(p).equals(fs.readFileSync(dest)))
@@ -228,14 +229,14 @@ describe('asar package', function () {
describe('fs.copyFileSync', function () {
it('copies a normal file', function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'file1')
+ const p = path.join(asarDir, 'a.asar', 'file1')
const dest = temp.path()
fs.copyFileSync(p, dest)
assert(fs.readFileSync(p).equals(fs.readFileSync(dest)))
})
it('copies a unpacked file', function () {
- const p = path.join(fixtures, 'asar', 'unpack.asar', 'a.txt')
+ const p = path.join(asarDir, 'unpack.asar', 'a.txt')
const dest = temp.path()
fs.copyFileSync(p, dest)
assert(fs.readFileSync(p).equals(fs.readFileSync(dest)))
@@ -244,13 +245,13 @@ describe('asar package', function () {
describe('fs.lstatSync', function () {
it('handles path with trailing slash correctly', function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2', 'file1')
+ const p = path.join(asarDir, 'a.asar', 'link2', 'link2', 'file1')
fs.lstatSync(p)
fs.lstatSync(p + '/')
})
it('returns information of root', function () {
- const p = path.join(fixtures, 'asar', 'a.asar')
+ const p = path.join(asarDir, 'a.asar')
const stats = fs.lstatSync(p)
assert.strictEqual(stats.isFile(), false)
assert.strictEqual(stats.isDirectory(), true)
@@ -259,7 +260,7 @@ describe('asar package', function () {
})
it('returns information of root with stats as bigint', function () {
- const p = path.join(fixtures, 'asar', 'a.asar')
+ const p = path.join(asarDir, 'a.asar')
const stats = fs.lstatSync(p, { bigint: false })
assert.strictEqual(stats.isFile(), false)
assert.strictEqual(stats.isDirectory(), true)
@@ -271,7 +272,7 @@ describe('asar package', function () {
const ref2 = ['file1', 'file2', 'file3', path.join('dir1', 'file1'), path.join('link2', 'file1')]
for (let j = 0, len = ref2.length; j < len; j++) {
const file = ref2[j]
- const p = path.join(fixtures, 'asar', 'a.asar', file)
+ const p = path.join(asarDir, 'a.asar', file)
const stats = fs.lstatSync(p)
assert.strictEqual(stats.isFile(), true)
assert.strictEqual(stats.isDirectory(), false)
@@ -284,7 +285,7 @@ describe('asar package', function () {
const ref2 = ['dir1', 'dir2', 'dir3']
for (let j = 0, len = ref2.length; j < len; j++) {
const file = ref2[j]
- const p = path.join(fixtures, 'asar', 'a.asar', file)
+ const p = path.join(asarDir, 'a.asar', file)
const stats = fs.lstatSync(p)
assert.strictEqual(stats.isFile(), false)
assert.strictEqual(stats.isDirectory(), true)
@@ -297,7 +298,7 @@ describe('asar package', function () {
const ref2 = ['link1', path.join('dir1', 'link1'), path.join('link2', 'link2')]
for (let j = 0, len = ref2.length; j < len; j++) {
const file = ref2[j]
- const p = path.join(fixtures, 'asar', 'a.asar', file)
+ const p = path.join(asarDir, 'a.asar', file)
const stats = fs.lstatSync(p)
assert.strictEqual(stats.isFile(), false)
assert.strictEqual(stats.isDirectory(), false)
@@ -310,7 +311,7 @@ describe('asar package', function () {
const ref2 = ['link2', path.join('dir1', 'link2'), path.join('link2', 'link2')]
for (let j = 0, len = ref2.length; j < len; j++) {
const file = ref2[j]
- const p = path.join(fixtures, 'asar', 'a.asar', file)
+ const p = path.join(asarDir, 'a.asar', file)
const stats = fs.lstatSync(p)
assert.strictEqual(stats.isFile(), false)
assert.strictEqual(stats.isDirectory(), false)
@@ -323,7 +324,7 @@ describe('asar package', function () {
const ref2 = ['file4', 'file5', path.join('dir1', 'file4')]
for (let j = 0, len = ref2.length; j < len; j++) {
const file = ref2[j]
- const p = path.join(fixtures, 'asar', 'a.asar', file)
+ const p = path.join(asarDir, 'a.asar', file)
const throws = function () {
fs.lstatSync(p)
}
@@ -334,12 +335,12 @@ describe('asar package', function () {
describe('fs.lstat', function () {
it('handles path with trailing slash correctly', function (done) {
- const p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2', 'file1')
+ const p = path.join(asarDir, 'a.asar', 'link2', 'link2', 'file1')
fs.lstat(p + '/', done)
})
it('returns information of root', function (done) {
- const p = path.join(fixtures, 'asar', 'a.asar')
+ const p = path.join(asarDir, 'a.asar')
fs.lstat(p, function (err, stats) {
assert.strictEqual(err, null)
assert.strictEqual(stats.isFile(), false)
@@ -351,7 +352,7 @@ describe('asar package', function () {
})
it('returns information of root with stats as bigint', function (done) {
- const p = path.join(fixtures, 'asar', 'a.asar')
+ const p = path.join(asarDir, 'a.asar')
fs.lstat(p, { bigint: false }, function (err, stats) {
assert.strictEqual(err, null)
assert.strictEqual(stats.isFile(), false)
@@ -363,7 +364,7 @@ describe('asar package', function () {
})
it('returns information of a normal file', function (done) {
- const p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'file1')
+ const p = path.join(asarDir, 'a.asar', 'link2', 'file1')
fs.lstat(p, function (err, stats) {
assert.strictEqual(err, null)
assert.strictEqual(stats.isFile(), true)
@@ -375,7 +376,7 @@ describe('asar package', function () {
})
it('returns information of a normal directory', function (done) {
- const p = path.join(fixtures, 'asar', 'a.asar', 'dir1')
+ const p = path.join(asarDir, 'a.asar', 'dir1')
fs.lstat(p, function (err, stats) {
assert.strictEqual(err, null)
assert.strictEqual(stats.isFile(), false)
@@ -387,7 +388,7 @@ describe('asar package', function () {
})
it('returns information of a linked file', function (done) {
- const p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link1')
+ const p = path.join(asarDir, 'a.asar', 'link2', 'link1')
fs.lstat(p, function (err, stats) {
assert.strictEqual(err, null)
assert.strictEqual(stats.isFile(), false)
@@ -399,7 +400,7 @@ describe('asar package', function () {
})
it('returns information of a linked directory', function (done) {
- const p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2')
+ const p = path.join(asarDir, 'a.asar', 'link2', 'link2')
fs.lstat(p, function (err, stats) {
assert.strictEqual(err, null)
assert.strictEqual(stats.isFile(), false)
@@ -411,7 +412,7 @@ describe('asar package', function () {
})
it('throws ENOENT error when can not find file', function (done) {
- const p = path.join(fixtures, 'asar', 'a.asar', 'file4')
+ const p = path.join(asarDir, 'a.asar', 'file4')
fs.lstat(p, function (err) {
assert.strictEqual(err.code, 'ENOENT')
done()
@@ -421,12 +422,12 @@ describe('asar package', function () {
describe('fs.promises.lstat', function () {
it('handles path with trailing slash correctly', async function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2', 'file1')
+ const p = path.join(asarDir, 'a.asar', 'link2', 'link2', 'file1')
await fs.promises.lstat(p + '/')
})
it('returns information of root', async function () {
- const p = path.join(fixtures, 'asar', 'a.asar')
+ const p = path.join(asarDir, 'a.asar')
const stats = await fs.promises.lstat(p)
assert.strictEqual(stats.isFile(), false)
assert.strictEqual(stats.isDirectory(), true)
@@ -435,7 +436,7 @@ describe('asar package', function () {
})
it('returns information of root with stats as bigint', async function () {
- const p = path.join(fixtures, 'asar', 'a.asar')
+ const p = path.join(asarDir, 'a.asar')
const stats = await fs.promises.lstat(p, { bigint: false })
assert.strictEqual(stats.isFile(), false)
assert.strictEqual(stats.isDirectory(), true)
@@ -444,7 +445,7 @@ describe('asar package', function () {
})
it('returns information of a normal file', async function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'file1')
+ const p = path.join(asarDir, 'a.asar', 'link2', 'file1')
const stats = await fs.promises.lstat(p)
assert.strictEqual(stats.isFile(), true)
assert.strictEqual(stats.isDirectory(), false)
@@ -453,7 +454,7 @@ describe('asar package', function () {
})
it('returns information of a normal directory', async function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'dir1')
+ const p = path.join(asarDir, 'a.asar', 'dir1')
const stats = await fs.promises.lstat(p)
assert.strictEqual(stats.isFile(), false)
assert.strictEqual(stats.isDirectory(), true)
@@ -462,7 +463,7 @@ describe('asar package', function () {
})
it('returns information of a linked file', async function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link1')
+ const p = path.join(asarDir, 'a.asar', 'link2', 'link1')
const stats = await fs.promises.lstat(p)
assert.strictEqual(stats.isFile(), false)
assert.strictEqual(stats.isDirectory(), false)
@@ -471,7 +472,7 @@ describe('asar package', function () {
})
it('returns information of a linked directory', async function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2')
+ const p = path.join(asarDir, 'a.asar', 'link2', 'link2')
const stats = await fs.promises.lstat(p)
assert.strictEqual(stats.isFile(), false)
assert.strictEqual(stats.isDirectory(), false)
@@ -480,56 +481,56 @@ describe('asar package', function () {
})
it('throws ENOENT error when can not find file', async function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'file4')
+ const p = path.join(asarDir, 'a.asar', 'file4')
await expectToThrowErrorWithCode(() => fs.promises.lstat(p), 'ENOENT')
})
})
describe('fs.realpathSync', () => {
it('returns real path root', () => {
- const parent = fs.realpathSync(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync(asarDir)
const p = 'a.asar'
const r = fs.realpathSync(path.join(parent, p))
assert.strictEqual(r, path.join(parent, p))
})
it('returns real path of a normal file', () => {
- const parent = fs.realpathSync(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync(asarDir)
const p = path.join('a.asar', 'file1')
const r = fs.realpathSync(path.join(parent, p))
assert.strictEqual(r, path.join(parent, p))
})
it('returns real path of a normal directory', () => {
- const parent = fs.realpathSync(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync(asarDir)
const p = path.join('a.asar', 'dir1')
const r = fs.realpathSync(path.join(parent, p))
assert.strictEqual(r, path.join(parent, p))
})
it('returns real path of a linked file', () => {
- const parent = fs.realpathSync(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync(asarDir)
const p = path.join('a.asar', 'link2', 'link1')
const r = fs.realpathSync(path.join(parent, p))
assert.strictEqual(r, path.join(parent, 'a.asar', 'file1'))
})
it('returns real path of a linked directory', () => {
- const parent = fs.realpathSync(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync(asarDir)
const p = path.join('a.asar', 'link2', 'link2')
const r = fs.realpathSync(path.join(parent, p))
assert.strictEqual(r, path.join(parent, 'a.asar', 'dir1'))
})
it('returns real path of an unpacked file', () => {
- const parent = fs.realpathSync(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync(asarDir)
const p = path.join('unpack.asar', 'a.txt')
const r = fs.realpathSync(path.join(parent, p))
assert.strictEqual(r, path.join(parent, p))
})
it('throws ENOENT error when can not find file', () => {
- const parent = fs.realpathSync(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync(asarDir)
const p = path.join('a.asar', 'not-exist')
const throws = () => fs.realpathSync(path.join(parent, p))
assert.throws(throws, /ENOENT/)
@@ -538,49 +539,49 @@ describe('asar package', function () {
describe('fs.realpathSync.native', () => {
it('returns real path root', () => {
- const parent = fs.realpathSync.native(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync.native(asarDir)
const p = 'a.asar'
const r = fs.realpathSync.native(path.join(parent, p))
assert.strictEqual(r, path.join(parent, p))
})
it('returns real path of a normal file', () => {
- const parent = fs.realpathSync.native(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync.native(asarDir)
const p = path.join('a.asar', 'file1')
const r = fs.realpathSync.native(path.join(parent, p))
assert.strictEqual(r, path.join(parent, p))
})
it('returns real path of a normal directory', () => {
- const parent = fs.realpathSync.native(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync.native(asarDir)
const p = path.join('a.asar', 'dir1')
const r = fs.realpathSync.native(path.join(parent, p))
assert.strictEqual(r, path.join(parent, p))
})
it('returns real path of a linked file', () => {
- const parent = fs.realpathSync.native(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync.native(asarDir)
const p = path.join('a.asar', 'link2', 'link1')
const r = fs.realpathSync.native(path.join(parent, p))
assert.strictEqual(r, path.join(parent, 'a.asar', 'file1'))
})
it('returns real path of a linked directory', () => {
- const parent = fs.realpathSync.native(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync.native(asarDir)
const p = path.join('a.asar', 'link2', 'link2')
const r = fs.realpathSync.native(path.join(parent, p))
assert.strictEqual(r, path.join(parent, 'a.asar', 'dir1'))
})
it('returns real path of an unpacked file', () => {
- const parent = fs.realpathSync.native(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync.native(asarDir)
const p = path.join('unpack.asar', 'a.txt')
const r = fs.realpathSync.native(path.join(parent, p))
assert.strictEqual(r, path.join(parent, p))
})
it('throws ENOENT error when can not find file', () => {
- const parent = fs.realpathSync.native(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync.native(asarDir)
const p = path.join('a.asar', 'not-exist')
const throws = () => fs.realpathSync.native(path.join(parent, p))
assert.throws(throws, /ENOENT/)
@@ -589,7 +590,7 @@ describe('asar package', function () {
describe('fs.realpath', () => {
it('returns real path root', done => {
- const parent = fs.realpathSync(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync(asarDir)
const p = 'a.asar'
fs.realpath(path.join(parent, p), (err, r) => {
assert.strictEqual(err, null)
@@ -599,7 +600,7 @@ describe('asar package', function () {
})
it('returns real path of a normal file', done => {
- const parent = fs.realpathSync(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync(asarDir)
const p = path.join('a.asar', 'file1')
fs.realpath(path.join(parent, p), (err, r) => {
assert.strictEqual(err, null)
@@ -609,7 +610,7 @@ describe('asar package', function () {
})
it('returns real path of a normal directory', done => {
- const parent = fs.realpathSync(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync(asarDir)
const p = path.join('a.asar', 'dir1')
fs.realpath(path.join(parent, p), (err, r) => {
assert.strictEqual(err, null)
@@ -619,7 +620,7 @@ describe('asar package', function () {
})
it('returns real path of a linked file', done => {
- const parent = fs.realpathSync(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync(asarDir)
const p = path.join('a.asar', 'link2', 'link1')
fs.realpath(path.join(parent, p), (err, r) => {
assert.strictEqual(err, null)
@@ -629,7 +630,7 @@ describe('asar package', function () {
})
it('returns real path of a linked directory', done => {
- const parent = fs.realpathSync(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync(asarDir)
const p = path.join('a.asar', 'link2', 'link2')
fs.realpath(path.join(parent, p), (err, r) => {
assert.strictEqual(err, null)
@@ -639,7 +640,7 @@ describe('asar package', function () {
})
it('returns real path of an unpacked file', done => {
- const parent = fs.realpathSync(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync(asarDir)
const p = path.join('unpack.asar', 'a.txt')
fs.realpath(path.join(parent, p), (err, r) => {
assert.strictEqual(err, null)
@@ -649,7 +650,7 @@ describe('asar package', function () {
})
it('throws ENOENT error when can not find file', done => {
- const parent = fs.realpathSync(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync(asarDir)
const p = path.join('a.asar', 'not-exist')
fs.realpath(path.join(parent, p), err => {
assert.strictEqual(err.code, 'ENOENT')
@@ -660,49 +661,49 @@ describe('asar package', function () {
describe('fs.promises.realpath', () => {
it('returns real path root', async () => {
- const parent = fs.realpathSync(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync(asarDir)
const p = 'a.asar'
const r = await fs.promises.realpath(path.join(parent, p))
assert.strictEqual(r, path.join(parent, p))
})
it('returns real path of a normal file', async () => {
- const parent = fs.realpathSync(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync(asarDir)
const p = path.join('a.asar', 'file1')
const r = await fs.promises.realpath(path.join(parent, p))
assert.strictEqual(r, path.join(parent, p))
})
it('returns real path of a normal directory', async () => {
- const parent = fs.realpathSync(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync(asarDir)
const p = path.join('a.asar', 'dir1')
const r = await fs.promises.realpath(path.join(parent, p))
assert.strictEqual(r, path.join(parent, p))
})
it('returns real path of a linked file', async () => {
- const parent = fs.realpathSync(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync(asarDir)
const p = path.join('a.asar', 'link2', 'link1')
const r = await fs.promises.realpath(path.join(parent, p))
assert.strictEqual(r, path.join(parent, 'a.asar', 'file1'))
})
it('returns real path of a linked directory', async () => {
- const parent = fs.realpathSync(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync(asarDir)
const p = path.join('a.asar', 'link2', 'link2')
const r = await fs.promises.realpath(path.join(parent, p))
assert.strictEqual(r, path.join(parent, 'a.asar', 'dir1'))
})
it('returns real path of an unpacked file', async () => {
- const parent = fs.realpathSync(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync(asarDir)
const p = path.join('unpack.asar', 'a.txt')
const r = await fs.promises.realpath(path.join(parent, p))
assert.strictEqual(r, path.join(parent, p))
})
it('throws ENOENT error when can not find file', async () => {
- const parent = fs.realpathSync(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync(asarDir)
const p = path.join('a.asar', 'not-exist')
await expectToThrowErrorWithCode(() => fs.promises.realpath(path.join(parent, p)), 'ENOENT')
})
@@ -710,7 +711,7 @@ describe('asar package', function () {
describe('fs.realpath.native', () => {
it('returns real path root', done => {
- const parent = fs.realpathSync.native(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync.native(asarDir)
const p = 'a.asar'
fs.realpath.native(path.join(parent, p), (err, r) => {
assert.strictEqual(err, null)
@@ -720,7 +721,7 @@ describe('asar package', function () {
})
it('returns real path of a normal file', done => {
- const parent = fs.realpathSync.native(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync.native(asarDir)
const p = path.join('a.asar', 'file1')
fs.realpath.native(path.join(parent, p), (err, r) => {
assert.strictEqual(err, null)
@@ -730,7 +731,7 @@ describe('asar package', function () {
})
it('returns real path of a normal directory', done => {
- const parent = fs.realpathSync.native(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync.native(asarDir)
const p = path.join('a.asar', 'dir1')
fs.realpath.native(path.join(parent, p), (err, r) => {
assert.strictEqual(err, null)
@@ -740,7 +741,7 @@ describe('asar package', function () {
})
it('returns real path of a linked file', done => {
- const parent = fs.realpathSync.native(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync.native(asarDir)
const p = path.join('a.asar', 'link2', 'link1')
fs.realpath.native(path.join(parent, p), (err, r) => {
assert.strictEqual(err, null)
@@ -750,7 +751,7 @@ describe('asar package', function () {
})
it('returns real path of a linked directory', done => {
- const parent = fs.realpathSync.native(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync.native(asarDir)
const p = path.join('a.asar', 'link2', 'link2')
fs.realpath.native(path.join(parent, p), (err, r) => {
assert.strictEqual(err, null)
@@ -760,7 +761,7 @@ describe('asar package', function () {
})
it('returns real path of an unpacked file', done => {
- const parent = fs.realpathSync.native(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync.native(asarDir)
const p = path.join('unpack.asar', 'a.txt')
fs.realpath.native(path.join(parent, p), (err, r) => {
assert.strictEqual(err, null)
@@ -770,7 +771,7 @@ describe('asar package', function () {
})
it('throws ENOENT error when can not find file', done => {
- const parent = fs.realpathSync.native(path.join(fixtures, 'asar'))
+ const parent = fs.realpathSync.native(asarDir)
const p = path.join('a.asar', 'not-exist')
fs.realpath.native(path.join(parent, p), err => {
assert.strictEqual(err.code, 'ENOENT')
@@ -781,25 +782,25 @@ describe('asar package', function () {
describe('fs.readdirSync', function () {
it('reads dirs from root', function () {
- const p = path.join(fixtures, 'asar', 'a.asar')
+ const p = path.join(asarDir, 'a.asar')
const dirs = fs.readdirSync(p)
assert.deepStrictEqual(dirs, ['dir1', 'dir2', 'dir3', 'file1', 'file2', 'file3', 'link1', 'link2', 'ping.js'])
})
it('reads dirs from a normal dir', function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'dir1')
+ const p = path.join(asarDir, 'a.asar', 'dir1')
const dirs = fs.readdirSync(p)
assert.deepStrictEqual(dirs, ['file1', 'file2', 'file3', 'link1', 'link2'])
})
it('reads dirs from a linked dir', function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2')
+ const p = path.join(asarDir, 'a.asar', 'link2', 'link2')
const dirs = fs.readdirSync(p)
assert.deepStrictEqual(dirs, ['file1', 'file2', 'file3', 'link1', 'link2'])
})
it('throws ENOENT error when can not find file', function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist')
+ const p = path.join(asarDir, 'a.asar', 'not-exist')
const throws = function () {
fs.readdirSync(p)
}
@@ -809,7 +810,7 @@ describe('asar package', function () {
describe('fs.readdir', function () {
it('reads dirs from root', function (done) {
- const p = path.join(fixtures, 'asar', 'a.asar')
+ const p = path.join(asarDir, 'a.asar')
fs.readdir(p, function (err, dirs) {
assert.strictEqual(err, null)
assert.deepStrictEqual(dirs, ['dir1', 'dir2', 'dir3', 'file1', 'file2', 'file3', 'link1', 'link2', 'ping.js'])
@@ -818,7 +819,7 @@ describe('asar package', function () {
})
it('reads dirs from a normal dir', function (done) {
- const p = path.join(fixtures, 'asar', 'a.asar', 'dir1')
+ const p = path.join(asarDir, 'a.asar', 'dir1')
fs.readdir(p, function (err, dirs) {
assert.strictEqual(err, null)
assert.deepStrictEqual(dirs, ['file1', 'file2', 'file3', 'link1', 'link2'])
@@ -826,7 +827,7 @@ describe('asar package', function () {
})
})
it('reads dirs from a linked dir', function (done) {
- const p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2')
+ const p = path.join(asarDir, 'a.asar', 'link2', 'link2')
fs.readdir(p, function (err, dirs) {
assert.strictEqual(err, null)
assert.deepStrictEqual(dirs, ['file1', 'file2', 'file3', 'link1', 'link2'])
@@ -835,7 +836,7 @@ describe('asar package', function () {
})
it('throws ENOENT error when can not find file', function (done) {
- const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist')
+ const p = path.join(asarDir, 'a.asar', 'not-exist')
fs.readdir(p, function (err) {
assert.strictEqual(err.code, 'ENOENT')
done()
@@ -845,25 +846,25 @@ describe('asar package', function () {
describe('fs.promises.readdir', function () {
it('reads dirs from root', async function () {
- const p = path.join(fixtures, 'asar', 'a.asar')
+ const p = path.join(asarDir, 'a.asar')
const dirs = await fs.promises.readdir(p)
assert.deepStrictEqual(dirs, ['dir1', 'dir2', 'dir3', 'file1', 'file2', 'file3', 'link1', 'link2', 'ping.js'])
})
it('reads dirs from a normal dir', async function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'dir1')
+ const p = path.join(asarDir, 'a.asar', 'dir1')
const dirs = await fs.promises.readdir(p)
assert.deepStrictEqual(dirs, ['file1', 'file2', 'file3', 'link1', 'link2'])
})
it('reads dirs from a linked dir', async function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2')
+ const p = path.join(asarDir, 'a.asar', 'link2', 'link2')
const dirs = await fs.promises.readdir(p)
assert.deepStrictEqual(dirs, ['file1', 'file2', 'file3', 'link1', 'link2'])
})
it('throws ENOENT error when can not find file', async function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist')
+ const p = path.join(asarDir, 'a.asar', 'not-exist')
await expectToThrowErrorWithCode(() => fs.promises.readdir(p), 'ENOENT')
})
})
@@ -873,7 +874,7 @@ describe('asar package', function () {
const ref2 = ['file1', 'link1', path.join('link2', 'file1')]
for (let j = 0, len = ref2.length; j < len; j++) {
const file = ref2[j]
- const p = path.join(fixtures, 'asar', 'a.asar', file)
+ const p = path.join(asarDir, 'a.asar', file)
const fd = fs.openSync(p, 'r')
const buffer = Buffer.alloc(6)
fs.readSync(fd, buffer, 0, 6, 0)
@@ -883,7 +884,7 @@ describe('asar package', function () {
})
it('throws ENOENT error when can not find file', function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist')
+ const p = path.join(asarDir, 'a.asar', 'not-exist')
const throws = function () {
fs.openSync(p)
}
@@ -893,7 +894,7 @@ describe('asar package', function () {
describe('fs.open', function () {
it('opens a normal file', function (done) {
- const p = path.join(fixtures, 'asar', 'a.asar', 'file1')
+ const p = path.join(asarDir, 'a.asar', 'file1')
fs.open(p, 'r', function (err, fd) {
assert.strictEqual(err, null)
const buffer = Buffer.alloc(6)
@@ -906,7 +907,7 @@ describe('asar package', function () {
})
it('throws ENOENT error when can not find file', function (done) {
- const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist')
+ const p = path.join(asarDir, 'a.asar', 'not-exist')
fs.open(p, 'r', function (err) {
assert.strictEqual(err.code, 'ENOENT')
done()
@@ -916,7 +917,7 @@ describe('asar package', function () {
describe('fs.promises.open', function () {
it('opens a normal file', async function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'file1')
+ const p = path.join(asarDir, 'a.asar', 'file1')
const fh = await fs.promises.open(p, 'r')
const buffer = Buffer.alloc(6)
await fh.read(buffer, 0, 6, 0)
@@ -925,14 +926,14 @@ describe('asar package', function () {
})
it('throws ENOENT error when can not find file', async function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist')
+ const p = path.join(asarDir, 'a.asar', 'not-exist')
await expectToThrowErrorWithCode(() => fs.promises.open(p, 'r'), 'ENOENT')
})
})
describe('fs.mkdir', function () {
it('throws error when calling inside asar archive', function (done) {
- const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist')
+ const p = path.join(asarDir, 'a.asar', 'not-exist')
fs.mkdir(p, function (err) {
assert.strictEqual(err.code, 'ENOTDIR')
done()
@@ -942,14 +943,14 @@ describe('asar package', function () {
describe('fs.promises.mkdir', function () {
it('throws error when calling inside asar archive', async function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist')
+ const p = path.join(asarDir, 'a.asar', 'not-exist')
await expectToThrowErrorWithCode(() => fs.promises.mkdir(p), 'ENOTDIR')
})
})
describe('fs.mkdirSync', function () {
it('throws error when calling inside asar archive', function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist')
+ const p = path.join(asarDir, 'a.asar', 'not-exist')
assert.throws(function () {
fs.mkdirSync(p)
}, new RegExp('ENOTDIR'))
@@ -958,7 +959,7 @@ describe('asar package', function () {
describe('fs.exists', function () {
it('handles an existing file', function (done) {
- const p = path.join(fixtures, 'asar', 'a.asar', 'file1')
+ const p = path.join(asarDir, 'a.asar', 'file1')
// eslint-disable-next-line
fs.exists(p, function (exists) {
assert.strictEqual(exists, true)
@@ -967,7 +968,7 @@ describe('asar package', function () {
})
it('handles a non-existent file', function (done) {
- const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist')
+ const p = path.join(asarDir, 'a.asar', 'not-exist')
// eslint-disable-next-line
fs.exists(p, function (exists) {
assert.strictEqual(exists, false)
@@ -976,7 +977,7 @@ describe('asar package', function () {
})
it('promisified version handles an existing file', (done) => {
- const p = path.join(fixtures, 'asar', 'a.asar', 'file1')
+ const p = path.join(asarDir, 'a.asar', 'file1')
// eslint-disable-next-line
util.promisify(fs.exists)(p).then(exists => {
assert.strictEqual(exists, true)
@@ -985,7 +986,7 @@ describe('asar package', function () {
})
it('promisified version handles a non-existent file', function (done) {
- const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist')
+ const p = path.join(asarDir, 'a.asar', 'not-exist')
// eslint-disable-next-line
util.promisify(fs.exists)(p).then(exists => {
assert.strictEqual(exists, false)
@@ -996,14 +997,14 @@ describe('asar package', function () {
describe('fs.existsSync', function () {
it('handles an existing file', function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'file1')
+ const p = path.join(asarDir, 'a.asar', 'file1')
assert.doesNotThrow(function () {
assert.strictEqual(fs.existsSync(p), true)
})
})
it('handles a non-existent file', function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist')
+ const p = path.join(asarDir, 'a.asar', 'not-exist')
assert.doesNotThrow(function () {
assert.strictEqual(fs.existsSync(p), false)
})
@@ -1012,7 +1013,7 @@ describe('asar package', function () {
describe('fs.access', function () {
it('accesses a normal file', function (done) {
- const p = path.join(fixtures, 'asar', 'a.asar', 'file1')
+ const p = path.join(asarDir, 'a.asar', 'file1')
fs.access(p, function (err) {
assert(err == null)
done()
@@ -1020,7 +1021,7 @@ describe('asar package', function () {
})
it('throws an error when called with write mode', function (done) {
- const p = path.join(fixtures, 'asar', 'a.asar', 'file1')
+ const p = path.join(asarDir, 'a.asar', 'file1')
fs.access(p, fs.constants.R_OK | fs.constants.W_OK, function (err) {
assert.strictEqual(err.code, 'EACCES')
done()
@@ -1028,7 +1029,7 @@ describe('asar package', function () {
})
it('throws an error when called on non-existent file', function (done) {
- const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist')
+ const p = path.join(asarDir, 'a.asar', 'not-exist')
fs.access(p, function (err) {
assert.strictEqual(err.code, 'ENOENT')
done()
@@ -1036,7 +1037,7 @@ describe('asar package', function () {
})
it('allows write mode for unpacked files', function (done) {
- const p = path.join(fixtures, 'asar', 'unpack.asar', 'a.txt')
+ const p = path.join(asarDir, 'unpack.asar', 'a.txt')
fs.access(p, fs.constants.R_OK | fs.constants.W_OK, function (err) {
assert(err == null)
done()
@@ -1046,50 +1047,50 @@ describe('asar package', function () {
describe('fs.promises.access', function () {
it('accesses a normal file', async function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'file1')
+ const p = path.join(asarDir, 'a.asar', 'file1')
await fs.promises.access(p)
})
it('throws an error when called with write mode', async function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'file1')
+ const p = path.join(asarDir, 'a.asar', 'file1')
await expectToThrowErrorWithCode(() => fs.promises.access(p, fs.constants.R_OK | fs.constants.W_OK), 'EACCES')
})
it('throws an error when called on non-existent file', async function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist')
+ const p = path.join(asarDir, 'a.asar', 'not-exist')
await expectToThrowErrorWithCode(() => fs.promises.access(p), 'ENOENT')
})
it('allows write mode for unpacked files', async function () {
- const p = path.join(fixtures, 'asar', 'unpack.asar', 'a.txt')
+ const p = path.join(asarDir, 'unpack.asar', 'a.txt')
await fs.promises.access(p, fs.constants.R_OK | fs.constants.W_OK)
})
})
describe('fs.accessSync', function () {
it('accesses a normal file', function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'file1')
+ const p = path.join(asarDir, 'a.asar', 'file1')
assert.doesNotThrow(function () {
fs.accessSync(p)
})
})
it('throws an error when called with write mode', function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'file1')
+ const p = path.join(asarDir, 'a.asar', 'file1')
assert.throws(function () {
fs.accessSync(p, fs.constants.R_OK | fs.constants.W_OK)
}, /EACCES/)
})
it('throws an error when called on non-existent file', function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist')
+ const p = path.join(asarDir, 'a.asar', 'not-exist')
assert.throws(function () {
fs.accessSync(p)
}, /ENOENT/)
})
it('allows write mode for unpacked files', function () {
- const p = path.join(fixtures, 'asar', 'unpack.asar', 'a.txt')
+ const p = path.join(asarDir, 'unpack.asar', 'a.txt')
assert.doesNotThrow(function () {
fs.accessSync(p, fs.constants.R_OK | fs.constants.W_OK)
})
@@ -1104,7 +1105,7 @@ describe('asar package', function () {
})
it('opens a normal js file', function (done) {
- const child = ChildProcess.fork(path.join(fixtures, 'asar', 'a.asar', 'ping.js'))
+ const child = ChildProcess.fork(path.join(asarDir, 'a.asar', 'ping.js'))
child.on('message', function (msg) {
assert.strictEqual(msg, 'message')
done()
@@ -1113,7 +1114,7 @@ describe('asar package', function () {
})
it('supports asar in the forked js', function (done) {
- const file = path.join(fixtures, 'asar', 'a.asar', 'file1')
+ const file = path.join(asarDir, 'a.asar', 'file1')
const child = ChildProcess.fork(path.join(fixtures, 'module', 'asar.js'))
child.on('message', function (content) {
assert.strictEqual(content, fs.readFileSync(file).toString())
@@ -1124,7 +1125,7 @@ describe('asar package', function () {
})
describe('child_process.exec', function () {
- const echo = path.join(fixtures, 'asar', 'echo.asar', 'echo')
+ const echo = path.join(asarDir, 'echo.asar', 'echo')
it('should not try to extract the command if there is a reference to a file inside an .asar', function (done) {
ChildProcess.exec('echo ' + echo + ' foo bar', function (error, stdout) {
@@ -1142,7 +1143,7 @@ describe('asar package', function () {
})
describe('child_process.execSync', function () {
- const echo = path.join(fixtures, 'asar', 'echo.asar', 'echo')
+ const echo = path.join(asarDir, 'echo.asar', 'echo')
it('should not try to extract the command if there is a reference to a file inside an .asar', function (done) {
const stdout = ChildProcess.execSync('echo ' + echo + ' foo bar')
@@ -1154,7 +1155,7 @@ describe('asar package', function () {
describe('child_process.execFile', function () {
const execFile = ChildProcess.execFile
const execFileSync = ChildProcess.execFileSync
- const echo = path.join(fixtures, 'asar', 'echo.asar', 'echo')
+ const echo = path.join(asarDir, 'echo.asar', 'echo')
before(function () {
if (process.platform !== 'darwin') {
@@ -1198,16 +1199,16 @@ describe('asar package', function () {
const internalModuleReadJSON = process.binding('fs').internalModuleReadJSON
it('read a normal file', function () {
- const file1 = path.join(fixtures, 'asar', 'a.asar', 'file1')
+ const file1 = path.join(asarDir, 'a.asar', 'file1')
assert.strictEqual(internalModuleReadJSON(file1).toString().trim(), 'file1')
- const file2 = path.join(fixtures, 'asar', 'a.asar', 'file2')
+ const file2 = path.join(asarDir, 'a.asar', 'file2')
assert.strictEqual(internalModuleReadJSON(file2).toString().trim(), 'file2')
- const file3 = path.join(fixtures, 'asar', 'a.asar', 'file3')
+ const file3 = path.join(asarDir, 'a.asar', 'file3')
assert.strictEqual(internalModuleReadJSON(file3).toString().trim(), 'file3')
})
it('reads a normal file with unpacked files', function () {
- const p = path.join(fixtures, 'asar', 'unpack.asar', 'a.txt')
+ const p = path.join(asarDir, 'unpack.asar', 'a.txt')
assert.strictEqual(internalModuleReadJSON(p).toString().trim(), 'a')
})
})
@@ -1244,8 +1245,8 @@ describe('asar package', function () {
})
it('disables asar support in sync API', function () {
- const file = path.join(fixtures, 'asar', 'a.asar', 'file1')
- const dir = path.join(fixtures, 'asar', 'a.asar', 'dir1')
+ const file = path.join(asarDir, 'a.asar', 'file1')
+ const dir = path.join(asarDir, 'a.asar', 'dir1')
assert.throws(function () {
fs.readFileSync(file)
}, new RegExp(errorName))
@@ -1261,8 +1262,8 @@ describe('asar package', function () {
})
it('disables asar support in async API', function (done) {
- const file = path.join(fixtures, 'asar', 'a.asar', 'file1')
- const dir = path.join(fixtures, 'asar', 'a.asar', 'dir1')
+ const file = path.join(asarDir, 'a.asar', 'file1')
+ const dir = path.join(asarDir, 'a.asar', 'dir1')
fs.readFile(file, function (error) {
assert.strictEqual(error.code, errorName)
fs.lstat(file, function (error) {
@@ -1280,7 +1281,7 @@ describe('asar package', function () {
it('treats *.asar as normal file', function () {
const originalFs = require('original-fs')
- const asar = path.join(fixtures, 'asar', 'a.asar')
+ const asar = path.join(asarDir, 'a.asar')
const content1 = fs.readFileSync(asar)
const content2 = originalFs.readFileSync(asar)
assert.strictEqual(content1.compare(content2), 0)
@@ -1348,7 +1349,7 @@ describe('asar package', function () {
})
it('can request a file in package', function (done) {
- const p = path.resolve(fixtures, 'asar', 'a.asar', 'file1')
+ const p = path.resolve(asarDir, 'a.asar', 'file1')
$.get('file://' + p, function (data) {
assert.strictEqual(data.trim(), 'file1')
done()
@@ -1356,7 +1357,7 @@ describe('asar package', function () {
})
it('can request a file in package with unpacked files', function (done) {
- const p = path.resolve(fixtures, 'asar', 'unpack.asar', 'a.txt')
+ const p = path.resolve(asarDir, 'unpack.asar', 'a.txt')
$.get('file://' + p, function (data) {
assert.strictEqual(data.trim(), 'a')
done()
@@ -1364,7 +1365,7 @@ describe('asar package', function () {
})
it('can request a linked file in package', function (done) {
- const p = path.resolve(fixtures, 'asar', 'a.asar', 'link2', 'link1')
+ const p = path.resolve(asarDir, 'a.asar', 'link2', 'link1')
$.get('file://' + p, function (data) {
assert.strictEqual(data.trim(), 'file1')
done()
@@ -1372,7 +1373,7 @@ describe('asar package', function () {
})
it('can request a file in filesystem', function (done) {
- const p = path.resolve(fixtures, 'asar', 'file')
+ const p = path.resolve(asarDir, 'file')
$.get('file://' + p, function (data) {
assert.strictEqual(data.trim(), 'file')
done()
@@ -1380,7 +1381,7 @@ describe('asar package', function () {
})
it('gets 404 when file is not found', function (done) {
- const p = path.resolve(fixtures, 'asar', 'a.asar', 'no-exist')
+ const p = path.resolve(asarDir, 'a.asar', 'no-exist')
$.ajax({
url: 'file://' + p,
error: function (err) {
@@ -1403,7 +1404,7 @@ describe('asar package', function () {
nodeIntegration: true
}
})
- const p = path.resolve(fixtures, 'asar', 'web.asar', 'index.html')
+ const p = path.resolve(asarDir, 'web.asar', 'index.html')
ipcMain.once('dirname', function (event, dirname) {
assert.strictEqual(dirname, path.dirname(p))
done()
@@ -1424,7 +1425,7 @@ describe('asar package', function () {
nodeIntegration: true
}
})
- const p = path.resolve(fixtures, 'asar', 'script.asar', 'index.html')
+ const p = path.resolve(asarDir, 'script.asar', 'index.html')
w.loadFile(p)
ipcMain.once('ping', function (event, message) {
assert.strictEqual(message, 'pong')
@@ -1447,7 +1448,7 @@ describe('asar package', function () {
nodeIntegration: true
}
})
- const p = path.resolve(fixtures, 'asar', 'video.asar', 'index.html')
+ const p = path.resolve(asarDir, 'video.asar', 'index.html')
w.loadFile(p)
ipcMain.on('asar-video', function (event, message, error) {
if (message === 'ended') {
@@ -1464,7 +1465,7 @@ describe('asar package', function () {
const originalFs = require('original-fs')
it('treats .asar as file', function () {
- const file = path.join(fixtures, 'asar', 'a.asar')
+ const file = path.join(asarDir, 'a.asar')
const stats = originalFs.statSync(file)
assert(stats.isFile())
})
@@ -1484,7 +1485,7 @@ describe('asar package', function () {
})
it('can be used with streams', () => {
- originalFs.createReadStream(path.join(fixtures, 'asar', 'a.asar'))
+ originalFs.createReadStream(path.join(asarDir, 'a.asar'))
})
it('has the same APIs as fs', function () {
@@ -1497,7 +1498,7 @@ describe('asar package', function () {
const gfs = require('graceful-fs')
it('recognize asar archvies', function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'link1')
+ const p = path.join(asarDir, 'a.asar', 'link1')
assert.strictEqual(gfs.readFileSync(p).toString().trim(), 'file1')
})
it('does not touch global fs object', function () {
@@ -1509,7 +1510,7 @@ describe('asar package', function () {
const mkdirp = require('mkdirp')
it('throws error when calling inside asar archive', function () {
- const p = path.join(fixtures, 'asar', 'a.asar', 'not-exist')
+ const p = path.join(asarDir, 'a.asar', 'not-exist')
assert.throws(function () {
mkdirp.sync(p)
}, new RegExp('ENOTDIR'))
@@ -1518,7 +1519,7 @@ describe('asar package', function () {
describe('native-image', function () {
it('reads image from asar archive', function () {
- const p = path.join(fixtures, 'asar', 'logo.asar', 'logo.png')
+ const p = path.join(asarDir, 'logo.asar', 'logo.png')
const logo = nativeImage.createFromPath(p)
assert.deepStrictEqual(logo.getSize(), {
width: 55,
@@ -1527,7 +1528,7 @@ describe('asar package', function () {
})
it('reads image from asar archive with unpacked files', function () {
- const p = path.join(fixtures, 'asar', 'unpack.asar', 'atom.png')
+ const p = path.join(asarDir, 'unpack.asar', 'atom.png')
const logo = nativeImage.createFromPath(p)
assert.deepStrictEqual(logo.getSize(), {
width: 1024,
diff --git a/spec/fixtures/module/no-asar.js b/spec/fixtures/module/no-asar.js
index e574e3c6511b8..400a8525ffa47 100644
--- a/spec/fixtures/module/no-asar.js
+++ b/spec/fixtures/module/no-asar.js
@@ -1,7 +1,7 @@
const fs = require('fs')
const path = require('path')
-const stats = fs.statSync(path.join(__dirname, '..', 'asar', 'a.asar'))
+const stats = fs.statSync(path.join(__dirname, '..', 'test.asar', 'a.asar'))
const details = {
isFile: stats.isFile(),
diff --git a/spec/fixtures/no-proprietary-codecs.js b/spec/fixtures/no-proprietary-codecs.js
index d29342d0ea2ca..741927b44f27b 100644
--- a/spec/fixtures/no-proprietary-codecs.js
+++ b/spec/fixtures/no-proprietary-codecs.js
@@ -25,7 +25,7 @@ app.once('ready', () => {
app.exit(1)
})
- window.loadFile(path.resolve(__dirname, 'asar', 'video.asar', 'index.html'))
+ window.loadFile(path.resolve(__dirname, 'test.asar', 'video.asar', 'index.html'))
ipcMain.on('asar-video', (event, message, error) => {
if (message === 'ended') {
diff --git a/spec/fixtures/asar/a.asar b/spec/fixtures/test.asar/a.asar
similarity index 100%
rename from spec/fixtures/asar/a.asar
rename to spec/fixtures/test.asar/a.asar
diff --git a/spec/fixtures/asar/echo.asar b/spec/fixtures/test.asar/echo.asar
similarity index 100%
rename from spec/fixtures/asar/echo.asar
rename to spec/fixtures/test.asar/echo.asar
diff --git a/spec/fixtures/asar/empty.asar b/spec/fixtures/test.asar/empty.asar
similarity index 100%
rename from spec/fixtures/asar/empty.asar
rename to spec/fixtures/test.asar/empty.asar
diff --git a/spec/fixtures/asar/file b/spec/fixtures/test.asar/file
similarity index 100%
rename from spec/fixtures/asar/file
rename to spec/fixtures/test.asar/file
diff --git a/spec/fixtures/asar/logo.asar b/spec/fixtures/test.asar/logo.asar
similarity index 100%
rename from spec/fixtures/asar/logo.asar
rename to spec/fixtures/test.asar/logo.asar
diff --git a/spec/fixtures/asar/script.asar b/spec/fixtures/test.asar/script.asar
similarity index 100%
rename from spec/fixtures/asar/script.asar
rename to spec/fixtures/test.asar/script.asar
diff --git a/spec/fixtures/asar/unpack.asar b/spec/fixtures/test.asar/unpack.asar
similarity index 100%
rename from spec/fixtures/asar/unpack.asar
rename to spec/fixtures/test.asar/unpack.asar
diff --git a/spec/fixtures/asar/unpack.asar.unpacked/a.txt b/spec/fixtures/test.asar/unpack.asar.unpacked/a.txt
similarity index 100%
rename from spec/fixtures/asar/unpack.asar.unpacked/a.txt
rename to spec/fixtures/test.asar/unpack.asar.unpacked/a.txt
diff --git a/spec/fixtures/asar/unpack.asar.unpacked/atom.png b/spec/fixtures/test.asar/unpack.asar.unpacked/atom.png
similarity index 100%
rename from spec/fixtures/asar/unpack.asar.unpacked/atom.png
rename to spec/fixtures/test.asar/unpack.asar.unpacked/atom.png
diff --git a/spec/fixtures/asar/video.asar b/spec/fixtures/test.asar/video.asar
similarity index 100%
rename from spec/fixtures/asar/video.asar
rename to spec/fixtures/test.asar/video.asar
diff --git a/spec/fixtures/asar/web.asar b/spec/fixtures/test.asar/web.asar
similarity index 100%
rename from spec/fixtures/asar/web.asar
rename to spec/fixtures/test.asar/web.asar
From 3176e323e41f097fedc2bb7110a10bf48482dbe8 Mon Sep 17 00:00:00 2001
From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com>
Date: Thu, 3 Oct 2019 08:59:09 +0200
Subject: [PATCH 16/28] fix: recentDocuments menu role on macOS (#20409)
---
atom/browser/ui/cocoa/atom_menu_controller.mm | 26 ++++++++++++++-----
1 file changed, 20 insertions(+), 6 deletions(-)
diff --git a/atom/browser/ui/cocoa/atom_menu_controller.mm b/atom/browser/ui/cocoa/atom_menu_controller.mm
index 9d66880c1cab6..32af8b3880266 100644
--- a/atom/browser/ui/cocoa/atom_menu_controller.mm
+++ b/atom/browser/ui/cocoa/atom_menu_controller.mm
@@ -126,11 +126,13 @@ - (void)populateWithModel:(atom::AtomMenuModel*)model {
if (!menu_)
return;
+ // Locate & retain the recent documents menu item
if (!recentDocumentsMenuItem_) {
- // Locate & retain the recent documents menu item
- recentDocumentsMenuItem_.reset(
- [[[[[NSApp mainMenu] itemWithTitle:@"Electron"] submenu]
- itemWithTitle:@"Open Recent"] retain]);
+ base::string16 title = base::ASCIIToUTF16("Open Recent");
+ NSString* openTitle = l10n_util::FixUpWindowsStyleLabel(title);
+
+ recentDocumentsMenuItem_.reset([[[[[NSApp mainMenu]
+ itemWithTitle:@"Electron"] submenu] itemWithTitle:openTitle] retain]);
}
model_ = model;
@@ -193,8 +195,17 @@ - (void)moveMenuItems:(NSMenu*)source to:(NSMenu*)destination {
// Replaces the item's submenu instance with the singleton recent documents
// menu. Previously replaced menu items will be recovered.
- (void)replaceSubmenuShowingRecentDocuments:(NSMenuItem*)item {
- NSMenu* recentDocumentsMenu =
- [[[recentDocumentsMenuItem_ submenu] retain] autorelease];
+ NSMenu* recentDocumentsMenu = [recentDocumentsMenuItem_ submenu];
+ if (!recentDocumentsMenu) {
+ base::string16 title = base::ASCIIToUTF16("Clear Menu");
+ NSString* clearTitle = l10n_util::FixUpWindowsStyleLabel(title);
+ recentDocumentsMenu = [[[NSMenu alloc] initWithTitle:@""] autorelease];
+ [recentDocumentsMenu
+ addItem:[[[NSMenuItem alloc]
+ initWithTitle:clearTitle
+ action:@selector(clearRecentDocuments:)
+ keyEquivalent:@""] autorelease]];
+ }
// Remove menu items in recent documents back to swap menu
[self moveMenuItems:recentDocumentsMenu to:recentDocumentsMenuSwap_];
@@ -211,6 +222,9 @@ - (void)replaceSubmenuShowingRecentDocuments:(NSMenuItem*)item {
// Replace submenu
[item setSubmenu:recentDocumentsMenu];
+ DCHECK_EQ([item action], @selector(submenuAction:));
+ DCHECK_EQ([item target], recentDocumentsMenu);
+
// Remember the new menu item that carries the recent documents menu
recentDocumentsMenuItem_.reset([item retain]);
}
From 15e611a0ff49c896cea56dc7872b27d27a5bb7c0 Mon Sep 17 00:00:00 2001
From: Shelley Vohr
Date: Mon, 7 Oct 2019 17:15:48 +0200
Subject: [PATCH 17/28] docs: clarify dock.bounce usage (#20458)
---
docs/api/app.md | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/docs/api/app.md b/docs/api/app.md
index e1785cf144e79..8cfa6ddefeab0 100644
--- a/docs/api/app.md
+++ b/docs/api/app.md
@@ -1285,6 +1285,8 @@ you exactly what went wrong
* `type` String (optional) - Can be `critical` or `informational`. The default is
`informational`
+Returns `Integer` an ID representing the request.
+
When `critical` is passed, the dock icon will bounce until either the
application becomes active or the request is canceled.
@@ -1292,7 +1294,7 @@ When `informational` is passed, the dock icon will bounce for one second.
However, the request remains active until either the application becomes active
or the request is canceled.
-Returns `Integer` an ID representing the request.
+**Nota Bene:** This method can only be used while the app is not focused; when the app is focused it will return -1.
### `app.dock.cancelBounce(id)` _macOS_
From 28eb7b05321436b666cc2588a6f386e9d2246b5d Mon Sep 17 00:00:00 2001
From: Joshua Westerheide
Date: Mon, 7 Oct 2019 19:04:00 +0200
Subject: [PATCH 18/28] feat: add env variable to skip binary download on npm
install (backport) (#20438)
* feat: add env variable to skip binary download on npm install
* docs: add "Skip binary download" section to install tutorial
---
docs/tutorial/installation.md | 11 +++++++++++
npm/install.js | 4 ++++
2 files changed, 15 insertions(+)
diff --git a/docs/tutorial/installation.md b/docs/tutorial/installation.md
index 5eeb89911b727..3aaba70d369a1 100644
--- a/docs/tutorial/installation.md
+++ b/docs/tutorial/installation.md
@@ -97,6 +97,17 @@ a text file. A typical cache might look like this:
├── SHASUMS256.txt-1.8.2-beta.3
```
+## Skip binary download
+When installing the `electron` NPM package, it automatically downloads the electron binary.
+
+This can sometimes be unnecessary, e.g. in a CI environment, when testing another component.
+
+To prevent the binary from being downloaded when you install all npm dependencies you can set the environment variable `ELECTRON_SKIP_BINARY_DOWNLOAD`.
+E.g.:
+```sh
+ELECTRON_SKIP_BINARY_DOWNLOAD=1 npm install
+```
+
## Troubleshooting
When running `npm install electron`, some users occasionally encounter
diff --git a/npm/install.js b/npm/install.js
index 3f59ce15d22bc..05bdab0bdab0b 100755
--- a/npm/install.js
+++ b/npm/install.js
@@ -15,6 +15,10 @@ try {
// do nothing
}
+if (process.env.ELECTRON_SKIP_BINARY_DOWNLOAD) {
+ process.exit(0)
+}
+
var platformPath = getPlatformPath()
var electronPath = process.env.ELECTRON_OVERRIDE_DIST_PATH || path.join(__dirname, 'dist', platformPath)
From e501930d38ac8ff7c19417005b06e9a2e9fd1303 Mon Sep 17 00:00:00 2001
From: Robo
Date: Mon, 7 Oct 2019 13:05:14 -0700
Subject: [PATCH 19/28] fix: fs.watch() behavior change in node >= 10.16.0
(#20429)
This reverts the patch from https://github.com/electron/node/pull/100
which never got merged due to reasons outlined in https://github.com/libuv/libuv/pull/2313
* Adds new patches that backports https://github.com/libuv/libuv/pull/2459
and https://github.com/libuv/libuv/pull/2460
Based on https://github.com/nodejs/node/issues/29460
---
patches/node/.patches | 3 +-
.../fsevents-regression-in-watching.patch | 158 +++++++++++++
...s-stop-using-fsevents-to-watch-files.patch | 120 ++++++++++
.../fsevents_fix_file_event_reporting.patch | 213 ------------------
4 files changed, 280 insertions(+), 214 deletions(-)
create mode 100644 patches/node/fsevents-regression-in-watching.patch
create mode 100644 patches/node/fsevents-stop-using-fsevents-to-watch-files.patch
delete mode 100644 patches/node/fsevents_fix_file_event_reporting.patch
diff --git a/patches/node/.patches b/patches/node/.patches
index 4b1b10e03f924..ab79ba34c02ef 100644
--- a/patches/node/.patches
+++ b/patches/node/.patches
@@ -32,7 +32,6 @@ feat_add_original-fs_module.patch
build_allow_embedders_to_override_the_node_module_version_define.patch
refactor_allow_embedder_overriding_of_internal_fs_calls.patch
chore_add_ability_to_prevent_warn_non_context-aware_native_modules.patch
-fsevents_fix_file_event_reporting.patch
src_only_run_preloadmodules_if_the_preload_array_is_not_empty.patch
src_read_break_node_first_line_from_the_inspect_options.patch
chore_allow_the_node_entrypoint_to_be_a_builtin_module.patch
@@ -55,3 +54,5 @@ chore_read_nobrowserglobals_from_global_not_process.patch
chore_use_v8_inspector_js_protocol_to_find_pdl_file.patch
chore_split_createenvironment_into_createenvironment_and.patch
fix_set_uptime_offset_in_correct_init_method.patch
+fsevents-stop-using-fsevents-to-watch-files.patch
+fsevents-regression-in-watching.patch
diff --git a/patches/node/fsevents-regression-in-watching.patch b/patches/node/fsevents-regression-in-watching.patch
new file mode 100644
index 0000000000000..e808aba80e358
--- /dev/null
+++ b/patches/node/fsevents-regression-in-watching.patch
@@ -0,0 +1,158 @@
+From ae12376dbb56fa080b699f00840c7b9c5230a85f Mon Sep 17 00:00:00 2001
+From: Jameson Nash
+Date: Sat, 7 Sep 2019 20:45:39 -0400
+Subject: [PATCH] fsevents: regression in watching /
+
+This case got lost by accident in
+https://github.com/libuv/libuv/pull/2082,
+preventing the realpath `/` from ever matching.
+
+Fixes: https://github.com/nodejs/node/issues/28917
+PR-URL: https://github.com/libuv/libuv/pull/2460
+Reviewed-By: Ben Noordhuis
+Reviewed-By: Saúl Ibarra Corretgé
+
+diff --git a/deps/uv/src/unix/fsevents.c b/deps/uv/src/unix/fsevents.c
+index ddacda31..deeaa63d 100644
+--- a/deps/uv/src/unix/fsevents.c
++++ b/deps/uv/src/unix/fsevents.c
+@@ -263,10 +263,12 @@ static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef,
+ if (len < handle->realpath_len)
+ continue;
+
++ /* Make sure that realpath actually named a directory,
++ * (unless watching root, which alone keeps a trailing slash on the realpath)
++ * or that we matched the whole string */
+ if (handle->realpath_len != len &&
++ handle->realpath_len > 1 &&
+ path[handle->realpath_len] != '/')
+- /* Make sure that realpath actually named a directory,
+- * or that we matched the whole string */
+ continue;
+
+ if (memcmp(path, handle->realpath, handle->realpath_len) != 0)
+diff --git a/deps/uv/test/test-fs-event.c b/deps/uv/test/test-fs-event.c
+index 4b8bb1ef..7725c3af 100644
+--- a/deps/uv/test/test-fs-event.c
++++ b/deps/uv/test/test-fs-event.c
+@@ -47,6 +47,7 @@ static const char file_prefix[] = "fsevent-";
+ static const int fs_event_file_count = 16;
+ #if defined(__APPLE__) || defined(_WIN32)
+ static const char file_prefix_in_subdir[] = "subdir";
++static int fs_multievent_cb_called;
+ #endif
+ static uv_timer_t timer;
+ static int timer_cb_called;
+@@ -280,7 +281,7 @@ static void fs_event_cb_dir_multi_file_in_subdir(uv_fs_event_t* handle,
+ if (filename && strcmp(filename, file_prefix_in_subdir) == 0)
+ return;
+ #endif
+- fs_event_cb_called++;
++ fs_multievent_cb_called++;
+ ASSERT(handle == &fs_event);
+ ASSERT(status == 0);
+ ASSERT(events == UV_CHANGE || events == UV_RENAME);
+@@ -298,7 +299,7 @@ static void fs_event_cb_dir_multi_file_in_subdir(uv_fs_event_t* handle,
+ if (fs_event_created + fs_event_removed == fs_event_file_count) {
+ /* Once we've processed all create events, delete all files */
+ ASSERT(0 == uv_timer_start(&timer, fs_event_unlink_files_in_subdir, 1, 0));
+- } else if (fs_event_cb_called == 2 * fs_event_file_count) {
++ } else if (fs_multievent_cb_called == 2 * fs_event_file_count) {
+ /* Once we've processed all create and delete events, stop watching */
+ uv_close((uv_handle_t*) &timer, close_cb);
+ uv_close((uv_handle_t*) handle, close_cb);
+@@ -393,6 +394,21 @@ static void timer_cb_watch_twice(uv_timer_t* handle) {
+ uv_close((uv_handle_t*) handle, NULL);
+ }
+
++static void fs_event_cb_close(uv_fs_event_t* handle,
++ const char* filename,
++ int events,
++ int status) {
++ ASSERT(status == 0);
++
++ ASSERT(fs_event_cb_called < 3);
++ ++fs_event_cb_called;
++
++ if (fs_event_cb_called == 3) {
++ uv_close((uv_handle_t*) handle, close_cb);
++ }
++}
++
++
+ TEST_IMPL(fs_event_watch_dir) {
+ #if defined(NO_FS_EVENTS)
+ RETURN_SKIP(NO_FS_EVENTS);
+@@ -434,10 +450,12 @@ TEST_IMPL(fs_event_watch_dir) {
+ return 0;
+ }
+
++
+ TEST_IMPL(fs_event_watch_dir_recursive) {
+ #if defined(__APPLE__) || defined(_WIN32)
+ uv_loop_t* loop;
+ int r;
++ uv_fs_event_t fs_event_root;
+
+ /* Setup */
+ loop = uv_default_loop();
+@@ -451,17 +469,37 @@ TEST_IMPL(fs_event_watch_dir_recursive) {
+
+ r = uv_fs_event_init(loop, &fs_event);
+ ASSERT(r == 0);
+- r = uv_fs_event_start(&fs_event, fs_event_cb_dir_multi_file_in_subdir, "watch_dir", UV_FS_EVENT_RECURSIVE);
++ r = uv_fs_event_start(&fs_event,
++ fs_event_cb_dir_multi_file_in_subdir,
++ "watch_dir",
++ UV_FS_EVENT_RECURSIVE);
+ ASSERT(r == 0);
+ r = uv_timer_init(loop, &timer);
+ ASSERT(r == 0);
+ r = uv_timer_start(&timer, fs_event_create_files_in_subdir, 100, 0);
+ ASSERT(r == 0);
+
++#ifndef _WIN32
++ /* Also try to watch the root directory.
++ * This will be noisier, so we're just checking for any couple events to happen. */
++ r = uv_fs_event_init(loop, &fs_event_root);
++ ASSERT(r == 0);
++ r = uv_fs_event_start(&fs_event_root,
++ fs_event_cb_close,
++ "/",
++ UV_FS_EVENT_RECURSIVE);
++ ASSERT(r == 0);
++#else
++ fs_event_cb_called += 3;
++ close_cb_called += 1;
++ (void)fs_event_root;
++#endif
++
+ uv_run(loop, UV_RUN_DEFAULT);
+
+- ASSERT(fs_event_cb_called == fs_event_created + fs_event_removed);
+- ASSERT(close_cb_called == 2);
++ ASSERT(fs_multievent_cb_called == fs_event_created + fs_event_removed);
++ ASSERT(fs_event_cb_called == 3);
++ ASSERT(close_cb_called == 3);
+
+ /* Cleanup */
+ fs_event_unlink_files_in_subdir(NULL);
+@@ -870,18 +908,6 @@ TEST_IMPL(fs_event_close_with_pending_event) {
+ return 0;
+ }
+
+-static void fs_event_cb_close(uv_fs_event_t* handle, const char* filename,
+- int events, int status) {
+- ASSERT(status == 0);
+-
+- ASSERT(fs_event_cb_called < 3);
+- ++fs_event_cb_called;
+-
+- if (fs_event_cb_called == 3) {
+- uv_close((uv_handle_t*) handle, close_cb);
+- }
+-}
+-
+ TEST_IMPL(fs_event_close_in_callback) {
+ #if defined(NO_FS_EVENTS)
+ RETURN_SKIP(NO_FS_EVENTS);
diff --git a/patches/node/fsevents-stop-using-fsevents-to-watch-files.patch b/patches/node/fsevents-stop-using-fsevents-to-watch-files.patch
new file mode 100644
index 0000000000000..b502c5540d58f
--- /dev/null
+++ b/patches/node/fsevents-stop-using-fsevents-to-watch-files.patch
@@ -0,0 +1,120 @@
+From 97b85e8b75b8f3df774b6e008dbaa143daa412b7 Mon Sep 17 00:00:00 2001
+From: Jameson Nash
+Date: Sat, 7 Sep 2019 14:55:40 -0400
+Subject: [PATCH] fsevents: stop using fsevents to watch files
+
+Goes back to just using it to watch folders,
+but keeps the other logic changes around.
+
+Refs: https://github.com/libuv/libuv/pull/387
+Refs: https://github.com/libuv/libuv/pull/2082
+Refs: https://github.com/libuv/libuv/pull/1572
+Refs: https://github.com/nodejs/node/issues/29460
+Fixes: https://github.com/libuv/libuv/issues/2488
+Closes: https://github.com/libuv/libuv/pull/2452
+PR-URL: https://github.com/libuv/libuv/pull/2459
+Reviewed-By: Ben Noordhuis
+Reviewed-By: Saúl Ibarra Corretgé
+
+diff --git a/deps/uv/src/unix/kqueue.c b/deps/uv/src/unix/kqueue.c
+index c04e7a48..ad09f403 100644
+--- a/deps/uv/src/unix/kqueue.c
++++ b/deps/uv/src/unix/kqueue.c
+@@ -454,10 +454,26 @@ int uv_fs_event_start(uv_fs_event_t* handle,
+ const char* path,
+ unsigned int flags) {
+ int fd;
++#if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
++ struct stat statbuf;
++#endif
+
+ if (uv__is_active(handle))
+ return UV_EINVAL;
+
++ handle->cb = cb;
++ handle->path = uv__strdup(path);
++ if (handle->path == NULL)
++ return UV_ENOMEM;
++
++ /* TODO open asynchronously - but how do we report back errors? */
++ fd = open(handle->path, O_RDONLY);
++ if (fd == -1) {
++ uv__free(handle->path);
++ handle->path = NULL;
++ return UV__ERR(errno);
++ }
++
+ #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
+ /* Nullify field to perform checks later */
+ handle->cf_cb = NULL;
+@@ -465,14 +481,17 @@ int uv_fs_event_start(uv_fs_event_t* handle,
+ handle->realpath_len = 0;
+ handle->cf_flags = flags;
+
++ if (fstat(fd, &statbuf))
++ goto fallback;
++ /* FSEvents works only with directories */
++ if (!(statbuf.st_mode & S_IFDIR))
++ goto fallback;
++
+ if (!uv__has_forked_with_cfrunloop) {
+ int r;
+- /* The fallback fd is not used */
++ /* The fallback fd is no longer needed */
++ uv__close_nocheckstdio(fd);
+ handle->event_watcher.fd = -1;
+- handle->path = uv__strdup(path);
+- if (handle->path == NULL)
+- return UV_ENOMEM;
+- handle->cb = cb;
+ r = uv__fsevents_init(handle);
+ if (r == 0) {
+ uv__handle_start(handle);
+@@ -482,20 +501,9 @@ int uv_fs_event_start(uv_fs_event_t* handle,
+ }
+ return r;
+ }
++fallback:
+ #endif /* #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
+
+- /* TODO open asynchronously - but how do we report back errors? */
+- fd = open(path, O_RDONLY);
+- if (fd == -1)
+- return UV__ERR(errno);
+-
+- handle->path = uv__strdup(path);
+- if (handle->path == NULL) {
+- uv__close_nocheckstdio(fd);
+- return UV_ENOMEM;
+- }
+-
+- handle->cb = cb;
+ uv__handle_start(handle);
+ uv__io_init(&handle->event_watcher, uv__fs_event, fd);
+ uv__io_start(handle->loop, &handle->event_watcher, POLLIN);
+@@ -514,7 +522,7 @@ int uv_fs_event_stop(uv_fs_event_t* handle) {
+ uv__handle_stop(handle);
+
+ #if defined(__APPLE__) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
+- if (!uv__has_forked_with_cfrunloop)
++ if (!uv__has_forked_with_cfrunloop && handle->cf_cb != NULL)
+ r = uv__fsevents_close(handle);
+ #endif
+
+diff --git a/deps/uv/test/test-fs-event.c b/deps/uv/test/test-fs-event.c
+index ea34bd63..4b8bb1ef 100644
+--- a/deps/uv/test/test-fs-event.c
++++ b/deps/uv/test/test-fs-event.c
+@@ -656,6 +656,12 @@ TEST_IMPL(fs_event_watch_file_current_dir) {
+ /* Setup */
+ remove("watch_file");
+ create_file("watch_file");
++#if defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_12)
++ /* Empirically, kevent seems to (sometimes) report the preceeding
++ * create_file events prior to macOS 10.11.6 in the subsequent fs_event_start
++ * So let the system settle before running the test. */
++ uv_sleep(1100);
++#endif
+
+ r = uv_fs_event_init(loop, &fs_event);
+ ASSERT(r == 0);
diff --git a/patches/node/fsevents_fix_file_event_reporting.patch b/patches/node/fsevents_fix_file_event_reporting.patch
deleted file mode 100644
index bc89830651349..0000000000000
--- a/patches/node/fsevents_fix_file_event_reporting.patch
+++ /dev/null
@@ -1,213 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Ben Noordhuis
-Date: Mon, 27 May 2019 14:31:53 +0200
-Subject: fsevents: fix file event reporting
-
-Commit 2d2af38 ("fsevents: really watch files with fsevents on macos
-10.7+") from last November introduced a regression where events that
-were previously reported as UV_RENAME were now reported as UV_CHANGE.
-This commit rectifies that.
-
-Fixes: https://github.com/nodejs/node/issues/27869
-
-diff --git a/deps/uv/src/unix/fsevents.c b/deps/uv/src/unix/fsevents.c
-index ddacda31fef87eee131fc2ee2ff46cc88be429d9..911023a6562319af5e9e3412ddbfd2ca14f77b05 100644
---- a/deps/uv/src/unix/fsevents.c
-+++ b/deps/uv/src/unix/fsevents.c
-@@ -49,19 +49,9 @@ void uv__fsevents_loop_delete(uv_loop_t* loop) {
- #include
- #include
-
--/* These are macros to avoid "initializer element is not constant" errors
-+/* Macro to avoid "initializer element is not constant" errors
- * with old versions of gcc.
- */
--#define kFSEventsModified (kFSEventStreamEventFlagItemFinderInfoMod | \
-- kFSEventStreamEventFlagItemModified | \
-- kFSEventStreamEventFlagItemInodeMetaMod | \
-- kFSEventStreamEventFlagItemChangeOwner | \
-- kFSEventStreamEventFlagItemXattrMod)
--
--#define kFSEventsRenamed (kFSEventStreamEventFlagItemCreated | \
-- kFSEventStreamEventFlagItemRemoved | \
-- kFSEventStreamEventFlagItemRenamed)
--
- #define kFSEventsSystem (kFSEventStreamEventFlagUserDropped | \
- kFSEventStreamEventFlagKernelDropped | \
- kFSEventStreamEventFlagEventIdsWrapped | \
-@@ -289,8 +279,6 @@ static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef,
- path--;
- len++;
- }
-- /* Created and Removed seem to be always set, but don't make sense */
-- flags &= ~kFSEventsRenamed;
- } else {
- /* Skip forward slash */
- path++;
-@@ -311,12 +299,12 @@ static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef,
-
- memset(event, 0, sizeof(*event));
- memcpy(event->path, path, len + 1);
-- event->events = UV_RENAME;
-+ event->events = UV_CHANGE;
-
-- if (0 == (flags & kFSEventsRenamed)) {
-- if (0 != (flags & kFSEventsModified) ||
-- 0 == (flags & kFSEventStreamEventFlagItemIsDir))
-- event->events = UV_CHANGE;
-+ if ((flags & kFSEventStreamEventFlagItemIsDir) ||
-+ (flags & kFSEventStreamEventFlagItemRemoved) ||
-+ (flags & kFSEventStreamEventFlagItemRenamed)) {
-+ event->events = UV_RENAME;
- }
-
- QUEUE_INSERT_TAIL(&head, &event->member);
-diff --git a/deps/uv/test/test-fs-event.c b/deps/uv/test/test-fs-event.c
-index ea34bd63a70625c3e2c60d5a1bbb087c5f0bbb2e..38d722a27ef1a78717726272d54578c734280242 100644
---- a/deps/uv/test/test-fs-event.c
-+++ b/deps/uv/test/test-fs-event.c
-@@ -62,6 +62,15 @@ static char fs_event_filename[1024];
- static int timer_cb_touch_called;
- static int timer_cb_exact_called;
-
-+static void expect_filename(const char* path, const char* expected) {
-+#if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
-+ ASSERT(0 == strcmp(path, expected));
-+#else
-+ if (path != NULL)
-+ ASSERT(0 == strcmp(path, expected));
-+#endif
-+}
-+
- static void fs_event_fail(uv_fs_event_t* handle,
- const char* filename,
- int events,
-@@ -130,11 +139,7 @@ static void fs_event_cb_dir(uv_fs_event_t* handle, const char* filename,
- ASSERT(handle == &fs_event);
- ASSERT(status == 0);
- ASSERT(events == UV_CHANGE);
-- #if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
-- ASSERT(strcmp(filename, "file1") == 0);
-- #else
-- ASSERT(filename == NULL || strcmp(filename, "file1") == 0);
-- #endif
-+ expect_filename(filename, "file1");
- ASSERT(0 == uv_fs_event_stop(handle));
- uv_close((uv_handle_t*)handle, close_cb);
- }
-@@ -312,11 +317,7 @@ static void fs_event_cb_file(uv_fs_event_t* handle, const char* filename,
- ASSERT(handle == &fs_event);
- ASSERT(status == 0);
- ASSERT(events == UV_CHANGE);
-- #if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
-- ASSERT(strcmp(filename, "file2") == 0);
-- #else
-- ASSERT(filename == NULL || strcmp(filename, "file2") == 0);
-- #endif
-+ expect_filename(filename, "file2");
- ASSERT(0 == uv_fs_event_stop(handle));
- uv_close((uv_handle_t*)handle, close_cb);
- }
-@@ -339,11 +340,7 @@ static void fs_event_cb_file_current_dir(uv_fs_event_t* handle,
- ASSERT(handle == &fs_event);
- ASSERT(status == 0);
- ASSERT(events == UV_CHANGE);
-- #if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
-- ASSERT(strcmp(filename, "watch_file") == 0);
-- #else
-- ASSERT(filename == NULL || strcmp(filename, "watch_file") == 0);
-- #endif
-+ expect_filename(filename, "watch_file");
-
- /* Regression test for SunOS: touch should generate just one event. */
- {
-@@ -619,6 +616,69 @@ TEST_IMPL(fs_event_watch_file_exact_path) {
- return 0;
- }
-
-+static void file_remove_cb(uv_fs_event_t* handle,
-+ const char* path,
-+ int events,
-+ int status) {
-+ fs_event_cb_called++;
-+
-+ expect_filename(path, "file1");
-+ /* TODO(bnoordhuis) Harmonize the behavior across platforms. Right now
-+ * this test merely ensures the status quo doesn't regress.
-+ */
-+#if defined(_AIX) || defined(__linux__)
-+ ASSERT(UV_CHANGE == events);
-+#else
-+ ASSERT(UV_RENAME == events);
-+#endif
-+ ASSERT(0 == status);
-+
-+ uv_close((uv_handle_t*) handle, NULL);
-+}
-+
-+static void file_remove_next(uv_timer_t* handle) {
-+ uv_close((uv_handle_t*) handle, NULL);
-+ remove("watch_dir/file1");
-+}
-+
-+static void file_remove_start(uv_timer_t* handle) {
-+ uv_fs_event_t* watcher;
-+ uv_loop_t* loop;
-+
-+ loop = handle->loop;
-+ watcher = handle->data;
-+
-+ ASSERT(0 == uv_fs_event_init(loop, watcher));
-+ ASSERT(0 == uv_fs_event_start(watcher, file_remove_cb, "watch_dir/file1", 0));
-+ ASSERT(0 == uv_timer_start(handle, file_remove_next, 50, 0));
-+}
-+
-+TEST_IMPL(fs_event_watch_file_remove) {
-+ uv_fs_event_t watcher;
-+ uv_timer_t timer;
-+ uv_loop_t* loop;
-+
-+#if defined(__MVS__)
-+ RETURN_SKIP("test does not work on this OS");
-+#endif
-+
-+ remove("watch_dir/file1");
-+ remove("watch_dir/");
-+ create_dir("watch_dir");
-+ create_file("watch_dir/file1");
-+
-+ loop = uv_default_loop();
-+ timer.data = &watcher;
-+
-+ ASSERT(0 == uv_timer_init(loop, &timer));
-+ ASSERT(0 == uv_timer_start(&timer, file_remove_start, 500, 0));
-+ ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
-+ ASSERT(1 == fs_event_cb_called);
-+
-+ MAKE_VALGRIND_HAPPY();
-+ return 0;
-+}
-+
- TEST_IMPL(fs_event_watch_file_twice) {
- #if defined(NO_FS_EVENTS)
- RETURN_SKIP(NO_FS_EVENTS);
-diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h
-index 8886b07c8a74736208d5614257f832f59d79633a..3e758a1d2cbe104a691d362411770006d1494bae 100644
---- a/deps/uv/test/test-list.h
-+++ b/deps/uv/test/test-list.h
-@@ -333,6 +333,7 @@ TEST_DECLARE (fs_event_watch_dir_short_path)
- #endif
- TEST_DECLARE (fs_event_watch_file)
- TEST_DECLARE (fs_event_watch_file_exact_path)
-+TEST_DECLARE (fs_event_watch_file_remove)
- TEST_DECLARE (fs_event_watch_file_twice)
- TEST_DECLARE (fs_event_watch_file_current_dir)
- #ifdef _WIN32
-@@ -920,6 +921,7 @@ TASK_LIST_START
- #endif
- TEST_ENTRY (fs_event_watch_file)
- TEST_ENTRY (fs_event_watch_file_exact_path)
-+ TEST_ENTRY (fs_event_watch_file_remove)
- TEST_ENTRY (fs_event_watch_file_twice)
- TEST_ENTRY (fs_event_watch_file_current_dir)
- #ifdef _WIN32
From 03d16f37d2dc9e570adecbc87872e78fe4855378 Mon Sep 17 00:00:00 2001
From: Shelley Vohr
Date: Tue, 8 Oct 2019 17:59:28 +0200
Subject: [PATCH 20/28] fix: enable worker threads in ELECTRON_RUN_AS_NODE
(#20457)
---
patches/node/.patches | 1 +
patches/node/fix_enable_worker_threads.patch | 29 ++++++++++++++++++++
2 files changed, 30 insertions(+)
create mode 100644 patches/node/fix_enable_worker_threads.patch
diff --git a/patches/node/.patches b/patches/node/.patches
index ab79ba34c02ef..bf7dc4efef84a 100644
--- a/patches/node/.patches
+++ b/patches/node/.patches
@@ -54,5 +54,6 @@ chore_read_nobrowserglobals_from_global_not_process.patch
chore_use_v8_inspector_js_protocol_to_find_pdl_file.patch
chore_split_createenvironment_into_createenvironment_and.patch
fix_set_uptime_offset_in_correct_init_method.patch
+fix_enable_worker_threads.patch
fsevents-stop-using-fsevents-to-watch-files.patch
fsevents-regression-in-watching.patch
diff --git a/patches/node/fix_enable_worker_threads.patch b/patches/node/fix_enable_worker_threads.patch
new file mode 100644
index 0000000000000..586cd0b46a95c
--- /dev/null
+++ b/patches/node/fix_enable_worker_threads.patch
@@ -0,0 +1,29 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Shelley Vohr
+Date: Thu, 3 Oct 2019 19:03:30 +0200
+Subject: fix: enable worker_threads
+
+Electron sets NODE_USE_V8_PLATFORM to false, because Electron
+initializes the v8 platform itself and Node.js worker thread
+initialization relies on the platform it uses having been set inside
+code guarded by NODE_USE_V8_PLATFORM.
+
+This commit fixes this problem by changing node_worker to use the three-arg
+implementation of `NewIsolate` to prevent it trying to use a possibly-null ptr.
+
+diff --git a/src/node_worker.cc b/src/node_worker.cc
+index 8f97f5c351..2bfbb28e61 100644
+--- a/src/node_worker.cc
++++ b/src/node_worker.cc
+@@ -112,7 +112,10 @@ class WorkerThreadData {
+ array_buffer_allocator_(ArrayBufferAllocator::Create()) {
+ CHECK_EQ(uv_loop_init(&loop_), 0);
+
+- Isolate* isolate = NewIsolate(array_buffer_allocator_.get(), &loop_);
++ Isolate* isolate = NewIsolate(
++ array_buffer_allocator_.get(),
++ &loop_,
++ w->platform_);
+ CHECK_NOT_NULL(isolate);
+
+ {
From 31ba6c203e754f5bb8a12c223186d9e98caf96fd Mon Sep 17 00:00:00 2001
From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com>
Date: Tue, 8 Oct 2019 15:33:32 -0400
Subject: [PATCH 21/28] fix: properly free IsolateData in node_main (#20475)
---
atom/app/node_main.cc | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/atom/app/node_main.cc b/atom/app/node_main.cc
index 482b375c106e4..332687302e3e5 100644
--- a/atom/app/node_main.cc
+++ b/atom/app/node_main.cc
@@ -68,9 +68,14 @@ int NodeMain(int argc, char* argv[]) {
// Initialize gin::IsolateHolder.
JavascriptEnvironment gin_env(loop);
- node::Environment* env = node::CreateEnvironment(
- node::CreateIsolateData(gin_env.isolate(), loop, gin_env.platform()),
- gin_env.context(), argc, argv, exec_argc, exec_argv, false);
+ node::IsolateData* isolate_data =
+ node::CreateIsolateData(gin_env.isolate(), loop, gin_env.platform());
+ CHECK_NE(nullptr, isolate_data);
+
+ node::Environment* env =
+ node::CreateEnvironment(isolate_data, gin_env.context(), argc, argv,
+ exec_argc, exec_argv, false);
+ CHECK_NE(nullptr, env);
// Enable support for v8 inspector.
NodeDebugger node_debugger(env);
@@ -118,6 +123,7 @@ int NodeMain(int argc, char* argv[]) {
v8::Isolate* isolate = env->isolate();
node::FreeEnvironment(env);
+ node::FreeIsolateData(isolate_data);
gin_env.platform()->DrainTasks(isolate);
gin_env.platform()->CancelPendingDelayedTasks(isolate);
From 1e50380fab37f407c4d357e1e30ecbc3d5a703b8 Mon Sep 17 00:00:00 2001
From: Electron Bot
Date: Tue, 8 Oct 2019 12:43:31 -0700
Subject: [PATCH 22/28] Bump v6.0.12
---
ELECTRON_VERSION | 2 +-
atom/browser/resources/mac/Info.plist | 4 ++--
atom/browser/resources/win/atom.rc | 8 ++++----
atom/common/atom_version.h | 2 +-
package.json | 2 +-
5 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/ELECTRON_VERSION b/ELECTRON_VERSION
index cb372c07bfa82..d089f6d74812e 100644
--- a/ELECTRON_VERSION
+++ b/ELECTRON_VERSION
@@ -1 +1 @@
-6.0.11
\ No newline at end of file
+6.0.12
\ No newline at end of file
diff --git a/atom/browser/resources/mac/Info.plist b/atom/browser/resources/mac/Info.plist
index d3efa6a713058..59b1a119fa920 100644
--- a/atom/browser/resources/mac/Info.plist
+++ b/atom/browser/resources/mac/Info.plist
@@ -17,9 +17,9 @@
CFBundleIconFile
electron.icns
CFBundleVersion
- 6.0.11
+ 6.0.12
CFBundleShortVersionString
- 6.0.11
+ 6.0.12
LSApplicationCategoryType
public.app-category.developer-tools
LSMinimumSystemVersion
diff --git a/atom/browser/resources/win/atom.rc b/atom/browser/resources/win/atom.rc
index f378c8dc44a2b..ab44121518d97 100644
--- a/atom/browser/resources/win/atom.rc
+++ b/atom/browser/resources/win/atom.rc
@@ -50,8 +50,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 6,0,11,0
- PRODUCTVERSION 6,0,11,0
+ FILEVERSION 6,0,12,0
+ PRODUCTVERSION 6,0,12,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -68,12 +68,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "GitHub, Inc."
VALUE "FileDescription", "Electron"
- VALUE "FileVersion", "6.0.11"
+ VALUE "FileVersion", "6.0.12"
VALUE "InternalName", "electron.exe"
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
VALUE "OriginalFilename", "electron.exe"
VALUE "ProductName", "Electron"
- VALUE "ProductVersion", "6.0.11"
+ VALUE "ProductVersion", "6.0.12"
VALUE "SquirrelAwareVersion", "1"
END
END
diff --git a/atom/common/atom_version.h b/atom/common/atom_version.h
index 2929e61ed841d..589e7066cd61d 100644
--- a/atom/common/atom_version.h
+++ b/atom/common/atom_version.h
@@ -7,7 +7,7 @@
#define ATOM_MAJOR_VERSION 6
#define ATOM_MINOR_VERSION 0
-#define ATOM_PATCH_VERSION 11
+#define ATOM_PATCH_VERSION 12
// clang-format off
// #define ATOM_PRE_RELEASE_VERSION
// clang-format on
diff --git a/package.json b/package.json
index f332706dc9e8b..2bdfcf9902a2b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "electron",
- "version": "6.0.11",
+ "version": "6.0.12",
"repository": "https://github.com/electron/electron",
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
"devDependencies": {
From fd0b57f219b1275b7133074387625d15094fd3c6 Mon Sep 17 00:00:00 2001
From: Robo
Date: Wed, 9 Oct 2019 13:41:06 -0700
Subject: [PATCH 23/28] fix: backport chromium patches to fix touchpad
scrolling on windows (#20488)
Backports https://chromium-review.googlesource.com/c/chromium/src/+/1689922
and https://chromium-review.googlesource.com/c/chromium/src/+/1753661
---
patches/common/chromium/.patches | 2 +
...andler_when_directmanipulationhelper.patch | 118 +++
...helper_when_every_lrwhh_updateparent.patch | 975 ++++++++++++++++++
3 files changed, 1095 insertions(+)
create mode 100644 patches/common/chromium/notify_directmanipulationeventhandler_when_directmanipulationhelper.patch
create mode 100644 patches/common/chromium/recreate_directmanipulationhelper_when_every_lrwhh_updateparent.patch
diff --git a/patches/common/chromium/.patches b/patches/common/chromium/.patches
index 06f8cbd21a607..2b0f234f8655b 100644
--- a/patches/common/chromium/.patches
+++ b/patches/common/chromium/.patches
@@ -84,3 +84,5 @@ fix_use_weakptr_to_detect_deletion.patch
fix_disabling_compositor_recycling.patch
allow_new_privileges_in_unsandboxed_child_processes.patch
fix_add_more_checks_in_mojocdmservice.patch
+recreate_directmanipulationhelper_when_every_lrwhh_updateparent.patch
+notify_directmanipulationeventhandler_when_directmanipulationhelper.patch
diff --git a/patches/common/chromium/notify_directmanipulationeventhandler_when_directmanipulationhelper.patch b/patches/common/chromium/notify_directmanipulationeventhandler_when_directmanipulationhelper.patch
new file mode 100644
index 0000000000000..dec26bfb080f4
--- /dev/null
+++ b/patches/common/chromium/notify_directmanipulationeventhandler_when_directmanipulationhelper.patch
@@ -0,0 +1,118 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Siye Liu
+Date: Thu, 15 Aug 2019 02:30:05 +0000
+Subject: Notify DirectManipulationEventHandler when DirectManipulationHelper
+ is destructed.
+
+The crash report shows that DirectManipulation may call
+|DirectManipulationEventHandler::OnInteraction| after
+DirectManipulationHelper is destroyed. Since |OnInteraction| is relying
+on DirectManipulationHelper to add/remove animation observer, we should
+set the pointer to DirectManipulationHelper to nullptr after it is
+destroyed.
+
+In this CL, we set the pointer to DirectManipulationHelper in separate
+function |SetDirectManipulationHelper| instead of passing the pointer
+during ctor of DirectManipulationEventHandler.
+
+Bug: 993260
+Change-Id: Id781af047e72268532d861920a077a0c6b1650bb
+Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1753661
+Reviewed-by: Scott Violet
+Commit-Queue: Siye Liu
+Cr-Commit-Position: refs/heads/master@{#687125}
+
+diff --git a/content/browser/renderer_host/direct_manipulation_event_handler_win.cc b/content/browser/renderer_host/direct_manipulation_event_handler_win.cc
+index 33ce63d8d0f59573cb4764f146b4f88008cca4a8..bae879411fb253a810034eb2cb531a54530a4183 100644
+--- a/content/browser/renderer_host/direct_manipulation_event_handler_win.cc
++++ b/content/browser/renderer_host/direct_manipulation_event_handler_win.cc
+@@ -28,9 +28,8 @@ bool FloatEquals(float f1, float f2) {
+ } // namespace
+
+ DirectManipulationEventHandler::DirectManipulationEventHandler(
+- DirectManipulationHelper* helper,
+ ui::WindowEventTarget* event_target)
+- : helper_(helper), event_target_(event_target) {}
++ : event_target_(event_target) {}
+
+ bool DirectManipulationEventHandler::SetViewportSizeInPixels(
+ const gfx::Size& viewport_size_in_pixels) {
+@@ -45,6 +44,11 @@ void DirectManipulationEventHandler::SetDeviceScaleFactor(
+ device_scale_factor_ = device_scale_factor;
+ }
+
++void DirectManipulationEventHandler::SetDirectManipulationHelper(
++ DirectManipulationHelper* helper) {
++ helper_ = helper;
++}
++
+ DirectManipulationEventHandler::~DirectManipulationEventHandler() {}
+
+ void DirectManipulationEventHandler::TransitionToState(
+@@ -303,6 +307,9 @@ HRESULT DirectManipulationEventHandler::OnContentUpdated(
+ HRESULT DirectManipulationEventHandler::OnInteraction(
+ IDirectManipulationViewport2* viewport,
+ DIRECTMANIPULATION_INTERACTION_TYPE interaction) {
++ if (!helper_)
++ return S_OK;
++
+ if (interaction == DIRECTMANIPULATION_INTERACTION_BEGIN) {
+ DebugLogging("OnInteraction BEGIN.", S_OK);
+ helper_->AddAnimationObserver();
+diff --git a/content/browser/renderer_host/direct_manipulation_event_handler_win.h b/content/browser/renderer_host/direct_manipulation_event_handler_win.h
+index f1902085032ffc95edb2d8dcd5224f1c5ecda3d2..e654c5f1a45da9e054d2c367df6f5115fa25862c 100644
+--- a/content/browser/renderer_host/direct_manipulation_event_handler_win.h
++++ b/content/browser/renderer_host/direct_manipulation_event_handler_win.h
+@@ -38,14 +38,15 @@ class DirectManipulationEventHandler
+ IDirectManipulationViewportEventHandler,
+ IDirectManipulationInteractionEventHandler>> {
+ public:
+- DirectManipulationEventHandler(DirectManipulationHelper* helper,
+- ui::WindowEventTarget* event_target);
++ DirectManipulationEventHandler(ui::WindowEventTarget* event_target);
+
+ // Return true if viewport_size_in_pixels_ changed.
+ bool SetViewportSizeInPixels(const gfx::Size& viewport_size_in_pixels);
+
+ void SetDeviceScaleFactor(float device_scale_factor);
+
++ void SetDirectManipulationHelper(DirectManipulationHelper* helper);
++
+ private:
+ friend class DirectManipulationBrowserTest;
+ friend DirectManipulationUnitTest;
+diff --git a/content/browser/renderer_host/direct_manipulation_helper_win.cc b/content/browser/renderer_host/direct_manipulation_helper_win.cc
+index 9401e7f8fb1fafd0532bb1e86035701c1df2ffda..6ce09b9f7b80e94c2adb582954c90afc95fc20e4 100644
+--- a/content/browser/renderer_host/direct_manipulation_helper_win.cc
++++ b/content/browser/renderer_host/direct_manipulation_helper_win.cc
+@@ -78,8 +78,9 @@ DirectManipulationHelper::CreateInstanceForTesting(
+ base::WrapUnique(new DirectManipulationHelper(0, nullptr));
+
+ instance->event_handler_ =
+- Microsoft::WRL::Make(instance.get(),
+- event_target);
++ Microsoft::WRL::Make(event_target);
++
++ instance->event_handler_->SetDirectManipulationHelper(instance.get());
+
+ instance->viewport_ = viewport;
+
+@@ -159,7 +160,9 @@ bool DirectManipulationHelper::Initialize(ui::WindowEventTarget* event_target) {
+ }
+
+ event_handler_ =
+- Microsoft::WRL::Make(this, event_target);
++ Microsoft::WRL::Make(event_target);
++
++ event_handler_->SetDirectManipulationHelper(this);
+
+ // We got Direct Manipulation transform from
+ // IDirectManipulationViewportEventHandler.
+@@ -265,6 +268,7 @@ void DirectManipulationHelper::Destroy() {
+ if (has_animation_observer_)
+ RemoveAnimationObserver();
+ compositor_ = nullptr;
++ event_handler_->SetDirectManipulationHelper(nullptr);
+
+ HRESULT hr;
+ if (viewport_) {
diff --git a/patches/common/chromium/recreate_directmanipulationhelper_when_every_lrwhh_updateparent.patch b/patches/common/chromium/recreate_directmanipulationhelper_when_every_lrwhh_updateparent.patch
new file mode 100644
index 0000000000000..c1688b62918f1
--- /dev/null
+++ b/patches/common/chromium/recreate_directmanipulationhelper_when_every_lrwhh_updateparent.patch
@@ -0,0 +1,975 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Siye Liu
+Date: Mon, 12 Aug 2019 19:26:49 +0000
+Subject: Recreate DirectManipulationHelper when every LRWHH UpdateParent
+
+This is a reland of 7da070704275ac67c95a89dd373a1dc0a1ba1256 and
+d77c5029a13a83e676833aea61966a003564e57a
+
+Compositor and window event target is associated with window's parent.
+We call LRWHH UpdateParent when window's parent update, includes
+window's parent actually update and window initialize. Recreate
+DirectManipulationHelper on every window's parent update helps keep
+DirectManipulationHelper lifecycle tracking simpler. We also make
+CompositorAnimationObserver owned by DirectManipulationHelper.
+
+With this changes, we start the DirectManipulation event polling when
+DirectManipulationHelper created and stop when it destroyed. The issue
+should be fix since event polling start no more depends on
+DM_POINTERHITTEST.
+
+This CL also includes 3 refactoring changes:
+
+1. Move CompositorAnimationObserver into DirectManipulationHelper.
+2. Call ZoomToRect to reset viewport of DirectManipulation when
+ viewport is actually transformed in RUNNING - READAY sequence.
+3. Pass the viewport size to DMEventHandler and use it to reset viewport
+ at gesture end.
+
+The original changes caused a regression that browser UI composition
+keeps ticking begin frames. We register DirectManipulationHelperWin
+as an AnimationObserver of ui::Compositor. UI compositor will ask for
+begin frames as long as it has an AnimationObserver. We should call
+OnCompositorShuttingDown() when the compositor is going Idle. Therefore,
+I added a IDirectManipulationInteractionEventHandler that adds the
+observer when a manipulation begins, and removes it when manipulation
+ends. After my fix, we start the DirectManipulation event polling when
+DirectManipulation interaction begin and stop when DirectManipulation
+interaction end.
+
+Bug: 914914
+Change-Id: I9f59381bdcc6e4ed0970003d87b26ac750bfb42d
+Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1689922
+Reviewed-by: Scott Violet
+Commit-Queue: Siye Liu
+Cr-Commit-Position: refs/heads/master@{#686111}
+
+diff --git a/content/browser/renderer_host/direct_manipulation_event_handler_win.cc b/content/browser/renderer_host/direct_manipulation_event_handler_win.cc
+index eec54fcb0187cfd47286d51226057b2fc4b3204a..33ce63d8d0f59573cb4764f146b4f88008cca4a8 100644
+--- a/content/browser/renderer_host/direct_manipulation_event_handler_win.cc
++++ b/content/browser/renderer_host/direct_manipulation_event_handler_win.cc
+@@ -28,19 +28,16 @@ bool FloatEquals(float f1, float f2) {
+ } // namespace
+
+ DirectManipulationEventHandler::DirectManipulationEventHandler(
+- DirectManipulationHelper* helper)
+- : helper_(helper) {}
+-
+-void DirectManipulationEventHandler::SetWindowEventTarget(
+- ui::WindowEventTarget* event_target) {
+- if (!event_target && LoggingEnabled()) {
+- DebugLogging("Event target is null.", S_OK);
+- if (event_target_)
+- DebugLogging("Previous event target is not null", S_OK);
+- else
+- DebugLogging("Previous event target is null", S_OK);
+- }
+- event_target_ = event_target;
++ DirectManipulationHelper* helper,
++ ui::WindowEventTarget* event_target)
++ : helper_(helper), event_target_(event_target) {}
++
++bool DirectManipulationEventHandler::SetViewportSizeInPixels(
++ const gfx::Size& viewport_size_in_pixels) {
++ if (viewport_size_in_pixels_ == viewport_size_in_pixels)
++ return false;
++ viewport_size_in_pixels_ = viewport_size_in_pixels;
++ return true;
+ }
+
+ void DirectManipulationEventHandler::SetDeviceScaleFactor(
+@@ -175,19 +172,28 @@ HRESULT DirectManipulationEventHandler::OnViewportStatusChanged(
+ if (current != DIRECTMANIPULATION_READY)
+ return S_OK;
+
+- // Reset the viewport when we're idle, so the content transforms always start
+- // at identity.
+- // Every animation will receive 2 ready message, we should stop request
+- // compositor animation at the second ready.
+- first_ready_ = !first_ready_;
+- HRESULT hr = helper_->Reset(first_ready_);
++ // Normally gesture sequence will receive 2 READY message, the first one is
++ // gesture end, the second one is from viewport reset. We don't have content
++ // transform in the second RUNNING -> READY. We should not reset on an empty
++ // RUNNING -> READY sequence.
++ if (last_scale_ != 1.0f || last_x_offset_ != 0 || last_y_offset_ != 0) {
++ HRESULT hr = viewport->ZoomToRect(
++ static_cast(0), static_cast(0),
++ static_cast(viewport_size_in_pixels_.width()),
++ static_cast(viewport_size_in_pixels_.height()), FALSE);
++ if (!SUCCEEDED(hr)) {
++ DebugLogging("Viewport zoom to rect failed.", hr);
++ return hr;
++ }
++ }
++
+ last_scale_ = 1.0f;
+ last_x_offset_ = 0.0f;
+ last_y_offset_ = 0.0f;
+
+ TransitionToState(GestureState::kNone);
+
+- return hr;
++ return S_OK;
+ }
+
+ HRESULT DirectManipulationEventHandler::OnViewportUpdated(
+@@ -294,4 +300,18 @@ HRESULT DirectManipulationEventHandler::OnContentUpdated(
+ return hr;
+ }
+
++HRESULT DirectManipulationEventHandler::OnInteraction(
++ IDirectManipulationViewport2* viewport,
++ DIRECTMANIPULATION_INTERACTION_TYPE interaction) {
++ if (interaction == DIRECTMANIPULATION_INTERACTION_BEGIN) {
++ DebugLogging("OnInteraction BEGIN.", S_OK);
++ helper_->AddAnimationObserver();
++ } else if (interaction == DIRECTMANIPULATION_INTERACTION_END) {
++ DebugLogging("OnInteraction END.", S_OK);
++ helper_->RemoveAnimationObserver();
++ }
++
++ return S_OK;
++}
++
+ } // namespace content
+diff --git a/content/browser/renderer_host/direct_manipulation_event_handler_win.h b/content/browser/renderer_host/direct_manipulation_event_handler_win.h
+index 270e85a09feb0add5b62afe3d9234627070ffe00..f1902085032ffc95edb2d8dcd5224f1c5ecda3d2 100644
+--- a/content/browser/renderer_host/direct_manipulation_event_handler_win.h
++++ b/content/browser/renderer_host/direct_manipulation_event_handler_win.h
+@@ -11,6 +11,7 @@
+ #include
+
+ #include "base/macros.h"
++#include "ui/gfx/geometry/size.h"
+
+ namespace ui {
+
+@@ -21,6 +22,7 @@ class WindowEventTarget;
+ namespace content {
+
+ class DirectManipulationHelper;
++class DirectManipulationBrowserTest;
+ class DirectManipulationUnitTest;
+
+ // DirectManipulationEventHandler receives status update and gesture events from
+@@ -33,17 +35,19 @@ class DirectManipulationEventHandler
+ Microsoft::WRL::RuntimeClassFlags<
+ Microsoft::WRL::RuntimeClassType::ClassicCom>,
+ Microsoft::WRL::FtmBase,
+- IDirectManipulationViewportEventHandler>> {
++ IDirectManipulationViewportEventHandler,
++ IDirectManipulationInteractionEventHandler>> {
+ public:
+- explicit DirectManipulationEventHandler(DirectManipulationHelper* helper);
++ DirectManipulationEventHandler(DirectManipulationHelper* helper,
++ ui::WindowEventTarget* event_target);
+
+- // WindowEventTarget updates for every DM_POINTERHITTEST in case window
+- // hierarchy changed.
+- void SetWindowEventTarget(ui::WindowEventTarget* event_target);
++ // Return true if viewport_size_in_pixels_ changed.
++ bool SetViewportSizeInPixels(const gfx::Size& viewport_size_in_pixels);
+
+ void SetDeviceScaleFactor(float device_scale_factor);
+
+ private:
++ friend class DirectManipulationBrowserTest;
+ friend DirectManipulationUnitTest;
+
+ // DirectManipulationEventHandler();
+@@ -65,18 +69,23 @@ class DirectManipulationEventHandler
+ OnContentUpdated(_In_ IDirectManipulationViewport* viewport,
+ _In_ IDirectManipulationContent* content) override;
+
++ HRESULT STDMETHODCALLTYPE
++ OnInteraction(_In_ IDirectManipulationViewport2* viewport,
++ _In_ DIRECTMANIPULATION_INTERACTION_TYPE interaction) override;
++
+ DirectManipulationHelper* helper_ = nullptr;
+ ui::WindowEventTarget* event_target_ = nullptr;
+ float device_scale_factor_ = 1.0f;
+ float last_scale_ = 1.0f;
+ int last_x_offset_ = 0;
+ int last_y_offset_ = 0;
+- bool first_ready_ = false;
+ bool should_send_scroll_begin_ = false;
+
+ // Current recognized gesture from Direct Manipulation.
+ GestureState gesture_state_ = GestureState::kNone;
+
++ gfx::Size viewport_size_in_pixels_;
++
+ DISALLOW_COPY_AND_ASSIGN(DirectManipulationEventHandler);
+ };
+
+diff --git a/content/browser/renderer_host/direct_manipulation_helper_win.cc b/content/browser/renderer_host/direct_manipulation_helper_win.cc
+index cc62fd688711153e2930fe06550c219e4cc01173..9401e7f8fb1fafd0532bb1e86035701c1df2ffda 100644
+--- a/content/browser/renderer_host/direct_manipulation_helper_win.cc
++++ b/content/browser/renderer_host/direct_manipulation_helper_win.cc
+@@ -14,6 +14,8 @@
+ #include "base/win/windows_version.h"
+ #include "ui/base/ui_base_features.h"
+ #include "ui/base/win/window_event_target.h"
++#include "ui/compositor/compositor.h"
++#include "ui/compositor/compositor_animation_observer.h"
+ #include "ui/display/win/screen_win.h"
+ #include "ui/gfx/geometry/rect.h"
+
+@@ -39,8 +41,9 @@ void DebugLogging(const std::string& s, HRESULT hr) {
+ // static
+ std::unique_ptr
+ DirectManipulationHelper::CreateInstance(HWND window,
++ ui::Compositor* compositor,
+ ui::WindowEventTarget* event_target) {
+- if (!::IsWindow(window))
++ if (!::IsWindow(window) || !compositor || !event_target)
+ return nullptr;
+
+ if (!base::FeatureList::IsEnabled(features::kPrecisionTouchpad))
+@@ -51,8 +54,7 @@ DirectManipulationHelper::CreateInstance(HWND window,
+ return nullptr;
+
+ std::unique_ptr instance =
+- base::WrapUnique(new DirectManipulationHelper());
+- instance->window_ = window;
++ base::WrapUnique(new DirectManipulationHelper(window, compositor));
+
+ if (instance->Initialize(event_target))
+ return instance;
+@@ -73,11 +75,11 @@ DirectManipulationHelper::CreateInstanceForTesting(
+ return nullptr;
+
+ std::unique_ptr instance =
+- base::WrapUnique(new DirectManipulationHelper());
++ base::WrapUnique(new DirectManipulationHelper(0, nullptr));
+
+ instance->event_handler_ =
+- Microsoft::WRL::Make(instance.get());
+- instance->event_handler_->SetWindowEventTarget(event_target);
++ Microsoft::WRL::Make(instance.get(),
++ event_target);
+
+ instance->viewport_ = viewport;
+
+@@ -85,11 +87,25 @@ DirectManipulationHelper::CreateInstanceForTesting(
+ }
+
+ DirectManipulationHelper::~DirectManipulationHelper() {
+- if (viewport_)
+- viewport_->Abandon();
++ Destroy();
+ }
+
+-DirectManipulationHelper::DirectManipulationHelper() {}
++DirectManipulationHelper::DirectManipulationHelper(HWND window,
++ ui::Compositor* compositor)
++ : window_(window), compositor_(compositor) {}
++
++void DirectManipulationHelper::OnAnimationStep(base::TimeTicks timestamp) {
++ // Simulate 1 frame in update_manager_.
++ HRESULT hr = update_manager_->Update(nullptr);
++ if (!SUCCEEDED(hr))
++ DebugLogging("UpdateManager update failed.", hr);
++}
++
++void DirectManipulationHelper::OnCompositingShuttingDown(
++ ui::Compositor* compositor) {
++ DCHECK_EQ(compositor, compositor_);
++ Destroy();
++}
+
+ bool DirectManipulationHelper::Initialize(ui::WindowEventTarget* event_target) {
+ // IDirectManipulationUpdateManager is the first COM object created by the
+@@ -142,8 +158,8 @@ bool DirectManipulationHelper::Initialize(ui::WindowEventTarget* event_target) {
+ return false;
+ }
+
+- event_handler_ = Microsoft::WRL::Make(this);
+- event_handler_->SetWindowEventTarget(event_target);
++ event_handler_ =
++ Microsoft::WRL::Make(this, event_target);
+
+ // We got Direct Manipulation transform from
+ // IDirectManipulationViewportEventHandler.
+@@ -155,8 +171,9 @@ bool DirectManipulationHelper::Initialize(ui::WindowEventTarget* event_target) {
+ }
+
+ // Set default rect for viewport before activate.
+- viewport_size_in_pixels_ = {1000, 1000};
+- RECT rect = gfx::Rect(viewport_size_in_pixels_).ToRECT();
++ gfx::Size viewport_size_in_pixels = {1000, 1000};
++ event_handler_->SetViewportSizeInPixels(viewport_size_in_pixels);
++ RECT rect = gfx::Rect(viewport_size_in_pixels).ToRECT();
+ hr = viewport_->SetViewportRect(&rect);
+ if (!SUCCEEDED(hr)) {
+ DebugLogging("Viewport set rect failed.", hr);
+@@ -185,33 +202,9 @@ bool DirectManipulationHelper::Initialize(ui::WindowEventTarget* event_target) {
+ return true;
+ }
+
+-void DirectManipulationHelper::Activate() {
+- HRESULT hr = viewport_->Stop();
+- if (!SUCCEEDED(hr)) {
+- DebugLogging("Viewport stop failed.", hr);
+- return;
+- }
+-
+- hr = manager_->Activate(window_);
+- if (!SUCCEEDED(hr))
+- DebugLogging("DirectManipulationManager activate failed.", hr);
+-}
+-
+-void DirectManipulationHelper::Deactivate() {
+- HRESULT hr = viewport_->Stop();
+- if (!SUCCEEDED(hr)) {
+- DebugLogging("Viewport stop failed.", hr);
+- return;
+- }
+-
+- hr = manager_->Deactivate(window_);
+- if (!SUCCEEDED(hr))
+- DebugLogging("DirectManipulationManager deactivate failed.", hr);
+-}
+-
+ void DirectManipulationHelper::SetSizeInPixels(
+ const gfx::Size& size_in_pixels) {
+- if (viewport_size_in_pixels_ == size_in_pixels)
++ if (!event_handler_->SetViewportSizeInPixels(size_in_pixels))
+ return;
+
+ HRESULT hr = viewport_->Stop();
+@@ -220,16 +213,13 @@ void DirectManipulationHelper::SetSizeInPixels(
+ return;
+ }
+
+- viewport_size_in_pixels_ = size_in_pixels;
+- RECT rect = gfx::Rect(viewport_size_in_pixels_).ToRECT();
++ RECT rect = gfx::Rect(size_in_pixels).ToRECT();
+ hr = viewport_->SetViewportRect(&rect);
+ if (!SUCCEEDED(hr))
+ DebugLogging("Viewport set rect failed.", hr);
+ }
+
+-bool DirectManipulationHelper::OnPointerHitTest(
+- WPARAM w_param,
+- ui::WindowEventTarget* event_target) {
++void DirectManipulationHelper::OnPointerHitTest(WPARAM w_param) {
+ // Update the device scale factor.
+ event_handler_->SetDeviceScaleFactor(
+ display::win::ScreenWin::GetScaleFactorForHWND(window_));
+@@ -240,53 +230,62 @@ bool DirectManipulationHelper::OnPointerHitTest(
+ // For WM_POINTER, the pointer type will show the event from mouse.
+ // For WM_POINTERACTIVATE, the pointer id will be different with the following
+ // message.
+- event_handler_->SetWindowEventTarget(event_target);
+-
+ using GetPointerTypeFn = BOOL(WINAPI*)(UINT32, POINTER_INPUT_TYPE*);
+ UINT32 pointer_id = GET_POINTERID_WPARAM(w_param);
+ POINTER_INPUT_TYPE pointer_type;
+ static const auto get_pointer_type = reinterpret_cast(
+ base::win::GetUser32FunctionPointer("GetPointerType"));
+ if (get_pointer_type && get_pointer_type(pointer_id, &pointer_type) &&
+- pointer_type == PT_TOUCHPAD && event_target) {
++ pointer_type == PT_TOUCHPAD) {
+ HRESULT hr = viewport_->SetContact(pointer_id);
+- if (!SUCCEEDED(hr)) {
++ if (!SUCCEEDED(hr))
+ DebugLogging("Viewport set contact failed.", hr);
+- return false;
+- }
+-
+- // Request begin frame for fake viewport.
+- need_poll_events_ = true;
+ }
+- return need_poll_events_;
+ }
+
+-HRESULT DirectManipulationHelper::Reset(bool need_poll_events) {
+- // By zooming the primary content to a rect that match the viewport rect, we
+- // reset the content's transform to identity.
+- HRESULT hr = viewport_->ZoomToRect(
+- static_cast(0), static_cast(0),
+- static_cast(viewport_size_in_pixels_.width()),
+- static_cast(viewport_size_in_pixels_.height()), FALSE);
+- if (!SUCCEEDED(hr)) {
+- DebugLogging("Viewport zoom to rect failed.", hr);
+- return hr;
+- }
+-
+- need_poll_events_ = need_poll_events;
+- return S_OK;
++void DirectManipulationHelper::AddAnimationObserver() {
++ DCHECK(compositor_);
++ compositor_->AddAnimationObserver(this);
++ has_animation_observer_ = true;
+ }
+
+-bool DirectManipulationHelper::PollForNextEvent() {
+- // Simulate 1 frame in update_manager_.
+- HRESULT hr = update_manager_->Update(nullptr);
+- if (!SUCCEEDED(hr))
+- DebugLogging("UpdateManager update failed.", hr);
+- return need_poll_events_;
++void DirectManipulationHelper::RemoveAnimationObserver() {
++ DCHECK(compositor_);
++ compositor_->RemoveAnimationObserver(this);
++ has_animation_observer_ = false;
+ }
+
+ void DirectManipulationHelper::SetDeviceScaleFactorForTesting(float factor) {
+ event_handler_->SetDeviceScaleFactor(factor);
+ }
+
++void DirectManipulationHelper::Destroy() {
++ if (!compositor_)
++ return;
++ if (has_animation_observer_)
++ RemoveAnimationObserver();
++ compositor_ = nullptr;
++
++ HRESULT hr;
++ if (viewport_) {
++ hr = viewport_->Stop();
++ if (!SUCCEEDED(hr))
++ DebugLogging("Viewport stop failed.", hr);
++
++ hr = viewport_->RemoveEventHandler(view_port_handler_cookie_);
++ if (!SUCCEEDED(hr))
++ DebugLogging("Viewport remove event handler failed.", hr);
++
++ hr = viewport_->Abandon();
++ if (!SUCCEEDED(hr))
++ DebugLogging("Viewport abandon failed.", hr);
++ }
++
++ if (manager_) {
++ hr = manager_->Deactivate(window_);
++ if (!SUCCEEDED(hr))
++ DebugLogging("DirectManipulationManager deactivate failed.", hr);
++ }
++}
++
+ } // namespace content
+diff --git a/content/browser/renderer_host/direct_manipulation_helper_win.h b/content/browser/renderer_host/direct_manipulation_helper_win.h
+index 76c889b35508ebd92f803a2dd723cfdc11cef1e1..adf19d6849f69b83c51b123c86600a15679da9c6 100644
+--- a/content/browser/renderer_host/direct_manipulation_helper_win.h
++++ b/content/browser/renderer_host/direct_manipulation_helper_win.h
+@@ -16,10 +16,12 @@
+ #include "base/macros.h"
+ #include "content/browser/renderer_host/direct_manipulation_event_handler_win.h"
+ #include "content/common/content_export.h"
++#include "ui/compositor/compositor_animation_observer.h"
+ #include "ui/gfx/geometry/size.h"
+
+ namespace ui {
+
++class Compositor;
+ class WindowEventTarget;
+
+ } // namespace ui
+@@ -44,13 +46,15 @@ bool LoggingEnabled();
+ // when DM_POINTERHITTEST.
+ // 3. OnViewportStatusChanged will be called when the gesture phase change.
+ // OnContentUpdated will be called when the gesture update.
+-class CONTENT_EXPORT DirectManipulationHelper {
++class CONTENT_EXPORT DirectManipulationHelper
++ : public ui::CompositorAnimationObserver {
+ public:
+ // Creates and initializes an instance of this class if Direct Manipulation is
+ // enabled on the platform. Returns nullptr if it disabled or failed on
+ // initialization.
+ static std::unique_ptr CreateInstance(
+ HWND window,
++ ui::Compositor* compositor,
+ ui::WindowEventTarget* event_target);
+
+ // Creates and initializes an instance for testing.
+@@ -58,49 +62,48 @@ class CONTENT_EXPORT DirectManipulationHelper {
+ ui::WindowEventTarget* event_target,
+ Microsoft::WRL::ComPtr viewport);
+
+- ~DirectManipulationHelper();
++ ~DirectManipulationHelper() override;
+
+- // Actives Direct Manipulation, call when window show.
+- void Activate();
+-
+- // Deactivates Direct Manipulation, call when window show.
+- void Deactivate();
++ // CompositorAnimationObserver implements.
++ // DirectManipulation needs to poll for new events every frame while finger
++ // gesturing on touchpad.
++ void OnAnimationStep(base::TimeTicks timestamp) override;
++ void OnCompositingShuttingDown(ui::Compositor* compositor) override;
+
+ // Updates viewport size. Call it when window bounds updated.
+ void SetSizeInPixels(const gfx::Size& size_in_pixels);
+
+- // Reset for gesture end.
+- HRESULT Reset(bool need_animtation);
++ // Pass the pointer hit test to Direct Manipulation.
++ void OnPointerHitTest(WPARAM w_param);
+
+- // Pass the pointer hit test to Direct Manipulation. Return true indicated we
+- // need poll for new events every frame from here.
+- bool OnPointerHitTest(WPARAM w_param, ui::WindowEventTarget* event_target);
++ // Register this as an AnimationObserver of ui::Compositor.
++ void AddAnimationObserver();
+
+- // On each frame poll new Direct Manipulation events. Return true if we still
+- // need poll for new events on next frame, otherwise stop request need begin
+- // frame.
+- bool PollForNextEvent();
++ // Unregister this as an AnimationObserver of ui::Compositor.
++ void RemoveAnimationObserver();
+
+ private:
+ friend class content::DirectManipulationBrowserTest;
+ friend class DirectManipulationUnitTest;
+
+- DirectManipulationHelper();
++ DirectManipulationHelper(HWND window, ui::Compositor* compositor);
+
+ // This function instantiates Direct Manipulation and creates a viewport for
+- // the passed in |window|. Return false if initialize failed.
++ // |window_|. Return false if initialize failed.
+ bool Initialize(ui::WindowEventTarget* event_target);
+
+ void SetDeviceScaleFactorForTesting(float factor);
+
++ void Destroy();
++
+ Microsoft::WRL::ComPtr manager_;
+ Microsoft::WRL::ComPtr update_manager_;
+ Microsoft::WRL::ComPtr viewport_;
+ Microsoft::WRL::ComPtr event_handler_;
+ HWND window_;
++ ui::Compositor* compositor_ = nullptr;
+ DWORD view_port_handler_cookie_;
+- bool need_poll_events_ = false;
+- gfx::Size viewport_size_in_pixels_;
++ bool has_animation_observer_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(DirectManipulationHelper);
+ };
+diff --git a/content/browser/renderer_host/direct_manipulation_win_browsertest.cc b/content/browser/renderer_host/direct_manipulation_win_browsertest.cc
+index 7648cf140d0de6e82ea81c33877495c91e7a57a9..10cf453cda7110b0531854ba63bb908fdd590d50 100644
+--- a/content/browser/renderer_host/direct_manipulation_win_browsertest.cc
++++ b/content/browser/renderer_host/direct_manipulation_win_browsertest.cc
+@@ -49,33 +49,23 @@ class DirectManipulationBrowserTest : public ContentBrowserTest,
+ return rwhva->legacy_render_widget_host_HWND_;
+ }
+
+- HWND GetSubWindowHWND() {
+- LegacyRenderWidgetHostHWND* lrwhh = GetLegacyRenderWidgetHostHWND();
+-
+- return lrwhh->hwnd();
+- }
+-
+ ui::WindowEventTarget* GetWindowEventTarget() {
+ LegacyRenderWidgetHostHWND* lrwhh = GetLegacyRenderWidgetHostHWND();
+
+ return lrwhh->GetWindowEventTarget(lrwhh->GetParent());
+ }
+
+- void SimulatePointerHitTest() {
+- LegacyRenderWidgetHostHWND* lrwhh = GetLegacyRenderWidgetHostHWND();
+-
+- lrwhh->direct_manipulation_helper_->need_poll_events_ = true;
+- lrwhh->CreateAnimationObserver();
+- }
+-
+- void UpdateParent(HWND hwnd) {
++ void SetDirectManipulationInteraction(
++ DIRECTMANIPULATION_INTERACTION_TYPE type) {
+ LegacyRenderWidgetHostHWND* lrwhh = GetLegacyRenderWidgetHostHWND();
+
+- lrwhh->UpdateParent(hwnd);
++ lrwhh->direct_manipulation_helper_->event_handler_->OnInteraction(nullptr,
++ type);
+ }
+
+- bool HasCompositorAnimationObserver(LegacyRenderWidgetHostHWND* lrwhh) {
+- return lrwhh->compositor_animation_observer_ != nullptr;
++ bool HasAnimationObserver(LegacyRenderWidgetHostHWND* lrwhh) {
++ return lrwhh->direct_manipulation_helper_->compositor_
++ ->HasAnimationObserver(lrwhh->direct_manipulation_helper_.get());
+ }
+
+ private:
+@@ -88,8 +78,10 @@ INSTANTIATE_TEST_SUITE_P(WithScrollEventPhase,
+ DirectManipulationBrowserTest,
+ testing::Bool());
+
+-// Ensure the AnimationObserver destroy when hwnd reparent to other hwnd.
+-IN_PROC_BROWSER_TEST_P(DirectManipulationBrowserTest, HWNDReparent) {
++// Ensure the AnimationObserver is only created after direct manipulation
++// interaction begin and destroyed after direct manipulation interaction end.
++IN_PROC_BROWSER_TEST_P(DirectManipulationBrowserTest,
++ ObserverDuringInteraction) {
+ if (base::win::GetVersion() < base::win::Version::WIN10)
+ return;
+
+@@ -98,25 +90,20 @@ IN_PROC_BROWSER_TEST_P(DirectManipulationBrowserTest, HWNDReparent) {
+ LegacyRenderWidgetHostHWND* lrwhh = GetLegacyRenderWidgetHostHWND();
+ ASSERT_TRUE(lrwhh);
+
+- // The observer should not create before it needed.
+- ASSERT_TRUE(!HasCompositorAnimationObserver(lrwhh));
++ // The observer should not be created before it is needed.
++ EXPECT_FALSE(HasAnimationObserver(lrwhh));
+
+- // Add AnimationObserver to tab to simulate direct manipulation start.
+- SimulatePointerHitTest();
+- ASSERT_TRUE(HasCompositorAnimationObserver(lrwhh));
++ // Begin direct manipulation interaction.
++ SetDirectManipulationInteraction(DIRECTMANIPULATION_INTERACTION_BEGIN);
++ // AnimationObserver should be added after direct manipulation interaction
++ // begin.
++ EXPECT_TRUE(HasAnimationObserver(lrwhh));
+
+- // Create another browser.
+- Shell* shell2 = CreateBrowser();
+- NavigateToURL(shell2, GURL(url::kAboutBlankURL));
+-
+- // Move to the tab to browser2.
+- UpdateParent(
+- shell2->window()->GetRootWindow()->GetHost()->GetAcceleratedWidget());
++ // End direct manipulation interaction.
++ SetDirectManipulationInteraction(DIRECTMANIPULATION_INTERACTION_END);
+
+ // The animation observer should be removed.
+- EXPECT_FALSE(HasCompositorAnimationObserver(lrwhh));
+-
+- shell2->Close();
++ EXPECT_FALSE(HasAnimationObserver(lrwhh));
+ }
+
+ // EventLogger is to observe the events sent from WindowEventTarget (the root
+diff --git a/content/browser/renderer_host/direct_manipulation_win_unittest.cc b/content/browser/renderer_host/direct_manipulation_win_unittest.cc
+index 3bf1b55555d0485c25575264045d415cf534323c..ccfa4d90b4e5c546c78afdac7c6b7b36f6096514 100644
+--- a/content/browser/renderer_host/direct_manipulation_win_unittest.cc
++++ b/content/browser/renderer_host/direct_manipulation_win_unittest.cc
+@@ -31,6 +31,12 @@ class MockDirectManipulationViewport
+
+ ~MockDirectManipulationViewport() override {}
+
++ bool WasZoomToRectCalled() {
++ bool called = zoom_to_rect_called_;
++ zoom_to_rect_called_ = false;
++ return called;
++ }
++
+ HRESULT STDMETHODCALLTYPE Enable() override { return S_OK; }
+
+ HRESULT STDMETHODCALLTYPE Disable() override { return S_OK; }
+@@ -75,6 +81,7 @@ class MockDirectManipulationViewport
+ _In_ const float right,
+ _In_ const float bottom,
+ _In_ BOOL animate) override {
++ zoom_to_rect_called_ = true;
+ return S_OK;
+ }
+
+@@ -161,6 +168,8 @@ class MockDirectManipulationViewport
+ HRESULT STDMETHODCALLTYPE Abandon() override { return S_OK; }
+
+ private:
++ bool zoom_to_rect_called_ = false;
++
+ DISALLOW_COPY_AND_ASSIGN(MockDirectManipulationViewport);
+ };
+
+@@ -397,13 +406,7 @@ class DirectManipulationUnitTest : public testing::Test {
+ viewport_.Get(), content_.Get());
+ }
+
+- void SetNeedAnimation(bool need_poll_events) {
+- direct_manipulation_helper_->need_poll_events_ = need_poll_events;
+- }
+-
+- bool NeedAnimation() {
+- return direct_manipulation_helper_->need_poll_events_;
+- }
++ bool WasZoomToRectCalled() { return viewport_->WasZoomToRectCalled(); }
+
+ void SetDeviceScaleFactor(float factor) {
+ direct_manipulation_helper_->SetDeviceScaleFactorForTesting(factor);
+@@ -721,21 +724,19 @@ TEST_F(DirectManipulationUnitTest,
+ }
+
+ TEST_F(DirectManipulationUnitTest,
+- NeedAnimtationShouldBeFalseAfterSecondReset) {
++ ZoomToRectShouldNotBeCalledInEmptyRunningReadySequence) {
+ if (!GetDirectManipulationHelper())
+ return;
+
+- // Direct Manipulation will set need_poll_events_ true when DM_POINTERTEST
+- // from touchpad.
+- SetNeedAnimation(true);
++ ContentUpdated(1.0f, 5, 0);
+
+ // Receive first ready when gesture end.
+ ViewportStatusChanged(DIRECTMANIPULATION_READY, DIRECTMANIPULATION_RUNNING);
+- EXPECT_TRUE(NeedAnimation());
++ EXPECT_TRUE(WasZoomToRectCalled());
+
+ // Receive second ready from ZoomToRect.
+ ViewportStatusChanged(DIRECTMANIPULATION_READY, DIRECTMANIPULATION_RUNNING);
+- EXPECT_FALSE(NeedAnimation());
++ EXPECT_FALSE(WasZoomToRectCalled());
+ }
+
+ TEST_F(DirectManipulationUnitTest, HiDPIScroll) {
+diff --git a/content/browser/renderer_host/legacy_render_widget_host_win.cc b/content/browser/renderer_host/legacy_render_widget_host_win.cc
+index b78186969fc928468c67f0bfcc853f5d7418df95..d2dd02a743a9bc908b6f8438ccac9dd85aa0a281 100644
+--- a/content/browser/renderer_host/legacy_render_widget_host_win.cc
++++ b/content/browser/renderer_host/legacy_render_widget_host_win.cc
+@@ -27,7 +27,6 @@
+ #include "ui/base/view_prop.h"
+ #include "ui/base/win/internal_constants.h"
+ #include "ui/base/win/window_event_target.h"
+-#include "ui/compositor/compositor.h"
+ #include "ui/display/win/screen_win.h"
+ #include "ui/gfx/geometry/rect.h"
+
+@@ -38,47 +37,6 @@ namespace content {
+ // accessibility support.
+ const int kIdScreenReaderHoneyPot = 1;
+
+-// DirectManipulation needs to poll for new events every frame while finger
+-// gesturing on touchpad.
+-class CompositorAnimationObserverForDirectManipulation
+- : public ui::CompositorAnimationObserver {
+- public:
+- CompositorAnimationObserverForDirectManipulation(
+- LegacyRenderWidgetHostHWND* render_widget_host_hwnd,
+- ui::Compositor* compositor)
+- : render_widget_host_hwnd_(render_widget_host_hwnd),
+- compositor_(compositor) {
+- DCHECK(compositor_);
+- compositor_->AddAnimationObserver(this);
+- DebugLogging("Add AnimationObserverForDirectManipulation.");
+- }
+-
+- ~CompositorAnimationObserverForDirectManipulation() override {
+- if (compositor_) {
+- compositor_->RemoveAnimationObserver(this);
+- DebugLogging("Remove AnimationObserverForDirectManipulation.");
+- }
+- }
+-
+- // ui::CompositorAnimationObserver
+- void OnAnimationStep(base::TimeTicks timestamp) override {
+- render_widget_host_hwnd_->PollForNextEvent();
+- }
+-
+- // ui::CompositorAnimationObserver
+- void OnCompositingShuttingDown(ui::Compositor* compositor) override {
+- DebugLogging("OnCompositingShuttingDown.");
+- compositor->RemoveAnimationObserver(this);
+- compositor_ = nullptr;
+- }
+-
+- private:
+- LegacyRenderWidgetHostHWND* render_widget_host_hwnd_;
+- ui::Compositor* compositor_;
+-
+- DISALLOW_COPY_AND_ASSIGN(CompositorAnimationObserverForDirectManipulation);
+-};
+-
+ // static
+ LegacyRenderWidgetHostHWND* LegacyRenderWidgetHostHWND::Create(
+ HWND parent) {
+@@ -103,8 +61,9 @@ LegacyRenderWidgetHostHWND* LegacyRenderWidgetHostHWND::Create(
+ }
+
+ void LegacyRenderWidgetHostHWND::Destroy() {
+- // Stop the AnimationObserver when window close.
+- DestroyAnimationObserver();
++ // Delete DirectManipulationHelper before the window is destroyed.
++ if (direct_manipulation_helper_)
++ direct_manipulation_helper_.reset();
+ host_ = nullptr;
+ if (::IsWindow(hwnd()))
+ ::DestroyWindow(hwnd());
+@@ -113,10 +72,16 @@ void LegacyRenderWidgetHostHWND::Destroy() {
+ void LegacyRenderWidgetHostHWND::UpdateParent(HWND parent) {
+ if (GetWindowEventTarget(GetParent()))
+ GetWindowEventTarget(GetParent())->HandleParentChanged();
+- // Stop the AnimationObserver when window hide. eg. tab switch, move tab to
+- // another window.
+- DestroyAnimationObserver();
++
+ ::SetParent(hwnd(), parent);
++
++ // Direct Manipulation is enabled on Windows 10+. The CreateInstance function
++ // returns NULL if Direct Manipulation is not available. Recreate
++ // |direct_manipulation_helper_| when parent changed (compositor and window
++ // event target updated).
++ direct_manipulation_helper_ = DirectManipulationHelper::CreateInstance(
++ hwnd(), host_->GetNativeView()->GetHost()->compositor(),
++ GetWindowEventTarget(GetParent()));
+ }
+
+ HWND LegacyRenderWidgetHostHWND::GetParent() {
+@@ -125,14 +90,10 @@ HWND LegacyRenderWidgetHostHWND::GetParent() {
+
+ void LegacyRenderWidgetHostHWND::Show() {
+ ::ShowWindow(hwnd(), SW_SHOW);
+- if (direct_manipulation_helper_)
+- direct_manipulation_helper_->Activate();
+ }
+
+ void LegacyRenderWidgetHostHWND::Hide() {
+ ::ShowWindow(hwnd(), SW_HIDE);
+- if (direct_manipulation_helper_)
+- direct_manipulation_helper_->Deactivate();
+ }
+
+ void LegacyRenderWidgetHostHWND::SetBounds(const gfx::Rect& bounds) {
+@@ -191,11 +152,6 @@ bool LegacyRenderWidgetHostHWND::Init() {
+ CHILDID_SELF);
+ }
+
+- // Direct Manipulation is enabled on Windows 10+. The CreateInstance function
+- // returns NULL if Direct Manipulation is not available.
+- direct_manipulation_helper_ = DirectManipulationHelper::CreateInstance(
+- hwnd(), GetWindowEventTarget(GetParent()));
+-
+ // Disable pen flicks (http://crbug.com/506977)
+ base::win::DisableFlicks(hwnd());
+
+@@ -501,21 +457,6 @@ LRESULT LegacyRenderWidgetHostHWND::OnSize(UINT message,
+ return 0;
+ }
+
+-LRESULT LegacyRenderWidgetHostHWND::OnWindowPosChanged(UINT message,
+- WPARAM w_param,
+- LPARAM l_param) {
+- WINDOWPOS* window_pos = reinterpret_cast(l_param);
+- if (direct_manipulation_helper_) {
+- if (window_pos->flags & SWP_SHOWWINDOW) {
+- direct_manipulation_helper_->Activate();
+- } else if (window_pos->flags & SWP_HIDEWINDOW) {
+- direct_manipulation_helper_->Deactivate();
+- }
+- }
+- SetMsgHandled(FALSE);
+- return 0;
+-}
+-
+ LRESULT LegacyRenderWidgetHostHWND::OnDestroy(UINT message,
+ WPARAM w_param,
+ LPARAM l_param) {
+@@ -534,30 +475,12 @@ LRESULT LegacyRenderWidgetHostHWND::OnPointerHitTest(UINT message,
+ return 0;
+
+ DebugLogging("Receive DM_POINTERHITTEST.");
+- // Update window event target for each DM_POINTERHITTEST.
+- if (direct_manipulation_helper_->OnPointerHitTest(
+- w_param, GetWindowEventTarget(GetParent()))) {
+- if (compositor_animation_observer_) {
+- // This is reach if Windows send a DM_POINTERHITTEST before the last
+- // DM_POINTERHITTEST receive READY status. We never see this but still
+- // worth to handle it.
+- DebugLogging("AnimationObserverForDirectManipulation exists.");
+- return 0;
+- }
+
+- CreateAnimationObserver();
+- }
++ direct_manipulation_helper_->OnPointerHitTest(w_param);
+
+ return 0;
+ }
+
+-void LegacyRenderWidgetHostHWND::PollForNextEvent() {
+- DCHECK(direct_manipulation_helper_);
+-
+- if (!direct_manipulation_helper_->PollForNextEvent())
+- DestroyAnimationObserver();
+-}
+-
+ gfx::NativeViewAccessible
+ LegacyRenderWidgetHostHWND::GetOrCreateWindowRootAccessible() {
+ if (!host_)
+@@ -589,20 +512,4 @@ LegacyRenderWidgetHostHWND::GetOrCreateWindowRootAccessible() {
+ return root->GetNativeViewAccessible();
+ }
+
+-void LegacyRenderWidgetHostHWND::CreateAnimationObserver() {
+- DCHECK(!compositor_animation_observer_);
+- DCHECK(host_);
+- DCHECK(host_->GetNativeView()->GetHost());
+- DCHECK(host_->GetNativeView()->GetHost()->compositor());
+-
+- compositor_animation_observer_ =
+- std::make_unique(
+- this, host_->GetNativeView()->GetHost()->compositor());
+-}
+-
+-void LegacyRenderWidgetHostHWND::DestroyAnimationObserver() {
+- DebugLogging("DestroyAnimationObserver.");
+- compositor_animation_observer_.reset();
+-}
+-
+ } // namespace content
+diff --git a/content/browser/renderer_host/legacy_render_widget_host_win.h b/content/browser/renderer_host/legacy_render_widget_host_win.h
+index 4f12296e3185caac685c8326192d88d32037a9d9..be0ea7bdbf460f414c94b0f2275a00424ec3198a 100644
+--- a/content/browser/renderer_host/legacy_render_widget_host_win.h
++++ b/content/browser/renderer_host/legacy_render_widget_host_win.h
+@@ -17,7 +17,6 @@
+
+ #include "base/macros.h"
+ #include "content/common/content_export.h"
+-#include "ui/compositor/compositor_animation_observer.h"
+ #include "ui/gfx/geometry/rect.h"
+ #include "ui/gfx/native_widget_types.h"
+
+@@ -99,7 +98,6 @@ class CONTENT_EXPORT LegacyRenderWidgetHostHWND
+ OnMouseRange)
+ MESSAGE_HANDLER_EX(WM_NCCALCSIZE, OnNCCalcSize)
+ MESSAGE_HANDLER_EX(WM_SIZE, OnSize)
+- MESSAGE_HANDLER_EX(WM_WINDOWPOSCHANGED, OnWindowPosChanged)
+ MESSAGE_HANDLER_EX(WM_DESTROY, OnDestroy)
+ MESSAGE_HANDLER_EX(DM_POINTERHITTEST, OnPointerHitTest)
+ END_MSG_MAP()
+@@ -126,10 +124,6 @@ class CONTENT_EXPORT LegacyRenderWidgetHostHWND
+ host_ = host;
+ }
+
+- // DirectManipulation needs to poll for new events every frame while finger
+- // gesturing on touchpad.
+- void PollForNextEvent();
+-
+ // Return the root accessible object for either MSAA or UI Automation.
+ gfx::NativeViewAccessible GetOrCreateWindowRootAccessible();
+
+@@ -166,15 +160,10 @@ class CONTENT_EXPORT LegacyRenderWidgetHostHWND
+ LRESULT OnSetCursor(UINT message, WPARAM w_param, LPARAM l_param);
+ LRESULT OnNCCalcSize(UINT message, WPARAM w_param, LPARAM l_param);
+ LRESULT OnSize(UINT message, WPARAM w_param, LPARAM l_param);
+- LRESULT OnWindowPosChanged(UINT message, WPARAM w_param, LPARAM l_param);
+ LRESULT OnDestroy(UINT message, WPARAM w_param, LPARAM l_param);
+
+ LRESULT OnPointerHitTest(UINT message, WPARAM w_param, LPARAM l_param);
+
+- void CreateAnimationObserver();
+-
+- void DestroyAnimationObserver();
+-
+ Microsoft::WRL::ComPtr window_accessible_;
+
+ // Set to true if we turned on mouse tracking.
+@@ -193,9 +182,6 @@ class CONTENT_EXPORT LegacyRenderWidgetHostHWND
+ // in Chrome on Windows 10.
+ std::unique_ptr direct_manipulation_helper_;
+
+- std::unique_ptr
+- compositor_animation_observer_;
+-
+ DISALLOW_COPY_AND_ASSIGN(LegacyRenderWidgetHostHWND);
+ };
+
From ffb96acab04012e4bfe8a9a5038bba6ddcebd478 Mon Sep 17 00:00:00 2001
From: Milan Burda
Date: Thu, 10 Oct 2019 14:12:28 +0200
Subject: [PATCH 24/28] fix: when building with enable_plugins=false (#20354)
(#20508)
---
atom/app/atom_content_client.cc | 12 ++-
atom/browser/api/atom_api_web_contents.cc | 3 +
patches/common/chromium/.patches | 1 +
...n_building_with_enable_plugins_false.patch | 74 +++++++++++++++++++
4 files changed, 88 insertions(+), 2 deletions(-)
create mode 100644 patches/common/chromium/build_fix_when_building_with_enable_plugins_false.patch
diff --git a/atom/app/atom_content_client.cc b/atom/app/atom_content_client.cc
index f17184a8114a7..014c614a77eb1 100644
--- a/atom/app/atom_content_client.cc
+++ b/atom/app/atom_content_client.cc
@@ -15,9 +15,8 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "content/public/common/content_constants.h"
-#include "content/public/common/pepper_plugin_info.h"
#include "electron/buildflags/buildflags.h"
-#include "ppapi/shared_impl/ppapi_permissions.h"
+#include "ppapi/buildflags/buildflags.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "url/url_constants.h"
@@ -35,6 +34,11 @@
#include "pdf/pdf.h"
#endif // BUILDFLAG(ENABLE_PDF_VIEWER)
+#if BUILDFLAG(ENABLE_PLUGINS)
+#include "content/public/common/pepper_plugin_info.h"
+#include "ppapi/shared_impl/ppapi_permissions.h"
+#endif // BUILDFLAG(ENABLE_PLUGINS)
+
namespace atom {
namespace {
@@ -141,6 +145,7 @@ void AddPepperFlashFromCommandLine(
}
#endif // BUILDFLAG(ENABLE_PEPPER_FLASH)
+#if BUILDFLAG(ENABLE_PLUGINS)
void ComputeBuiltInPlugins(std::vector* plugins) {
#if BUILDFLAG(ENABLE_PDF_VIEWER)
content::PepperPluginInfo pdf_info;
@@ -161,6 +166,7 @@ void ComputeBuiltInPlugins(std::vector* plugins) {
plugins->push_back(pdf_info);
#endif // BUILDFLAG(ENABLE_PDF_VIEWER)
}
+#endif // BUILDFLAG(ENABLE_PLUGINS)
void AppendDelimitedSwitchToVector(const base::StringPiece cmd_switch,
std::vector* append_me) {
@@ -227,7 +233,9 @@ void AtomContentClient::AddPepperPlugins(
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
AddPepperFlashFromCommandLine(command_line, plugins);
#endif // BUILDFLAG(ENABLE_PEPPER_FLASH)
+#if BUILDFLAG(ENABLE_PLUGINS)
ComputeBuiltInPlugins(plugins);
+#endif // BUILDFLAG(ENABLE_PLUGINS)
}
void AtomContentClient::AddContentDecryptionModules(
diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc
index c7b6793db3684..ddd4939f54805 100644
--- a/atom/browser/api/atom_api_web_contents.cc
+++ b/atom/browser/api/atom_api_web_contents.cc
@@ -85,6 +85,7 @@
#include "native_mate/dictionary.h"
#include "native_mate/object_template_builder.h"
#include "net/url_request/url_request_context.h"
+#include "ppapi/buildflags/buildflags.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/mojom/frame/find_in_page.mojom.h"
#include "third_party/blink/public/platform/web_cursor_info.h"
@@ -833,10 +834,12 @@ void WebContents::RenderProcessGone(base::TerminationStatus status) {
void WebContents::PluginCrashed(const base::FilePath& plugin_path,
base::ProcessId plugin_pid) {
+#if BUILDFLAG(ENABLE_PLUGINS)
content::WebPluginInfo info;
auto* plugin_service = content::PluginService::GetInstance();
plugin_service->GetPluginInfoByPath(plugin_path, &info);
Emit("plugin-crashed", info.name, info.version);
+#endif // BUILDFLAG(ENABLE_PLUIGNS)
}
void WebContents::MediaStartedPlaying(const MediaPlayerInfo& video_type,
diff --git a/patches/common/chromium/.patches b/patches/common/chromium/.patches
index 2b0f234f8655b..9f6d231173f28 100644
--- a/patches/common/chromium/.patches
+++ b/patches/common/chromium/.patches
@@ -86,3 +86,4 @@ allow_new_privileges_in_unsandboxed_child_processes.patch
fix_add_more_checks_in_mojocdmservice.patch
recreate_directmanipulationhelper_when_every_lrwhh_updateparent.patch
notify_directmanipulationeventhandler_when_directmanipulationhelper.patch
+build_fix_when_building_with_enable_plugins_false.patch
diff --git a/patches/common/chromium/build_fix_when_building_with_enable_plugins_false.patch b/patches/common/chromium/build_fix_when_building_with_enable_plugins_false.patch
new file mode 100644
index 0000000000000..54809da2b4bf3
--- /dev/null
+++ b/patches/common/chromium/build_fix_when_building_with_enable_plugins_false.patch
@@ -0,0 +1,74 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: deepak1556
+Date: Tue, 8 Oct 2019 15:40:50 +0000
+Subject: build: fix when building with enable_plugins=false
+
+Bug: none
+Change-Id: If878b3a7f5bb051c6e99c617418475c12754ae90
+Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1845624
+Reviewed-by: Robert Sesek
+Commit-Queue: Robert Sesek
+Cr-Commit-Position: refs/heads/master@{#703739}
+
+diff --git a/AUTHORS b/AUTHORS
+index 32fc92e6113c6324cc0b09b7a7ff309e2c89ddda..ae51b1d483564c96cb98b603280ac510f90c36c1 100644
+--- a/AUTHORS
++++ b/AUTHORS
+@@ -219,6 +219,7 @@ Debashish Samantaray
+ Debug Wang
+ Deepak Dilip Borade
+ Deepak Mittal
++Deepak Mohan
+ Deepak Sharma
+ Deepak Singla
+ Deokjin Kim
+diff --git a/content/browser/sandbox_parameters_mac.mm b/content/browser/sandbox_parameters_mac.mm
+index b4d539bab49d468e0d2bdade76aad3dba0facfc4..73905a6eac811f9bff04e1b0ceb47b3ea326ee62 100644
+--- a/content/browser/sandbox_parameters_mac.mm
++++ b/content/browser/sandbox_parameters_mac.mm
+@@ -21,12 +21,16 @@
+ #include "content/public/browser/plugin_service.h"
+ #include "content/public/common/content_client.h"
+ #include "content/public/common/content_switches.h"
+-#include "content/public/common/pepper_plugin_info.h"
++#include "ppapi/buildflags/buildflags.h"
+ #include "sandbox/mac/seatbelt_exec.h"
+ #include "services/service_manager/sandbox/mac/sandbox_mac.h"
+ #include "services/service_manager/sandbox/sandbox_type.h"
+ #include "services/service_manager/sandbox/switches.h"
+
++#if BUILDFLAG(ENABLE_PLUGINS)
++#include "content/public/common/pepper_plugin_info.h"
++#endif
++
+ namespace content {
+
+ namespace {
+@@ -125,6 +129,7 @@ void SetupNetworkSandboxParameters(sandbox::SeatbeltExecClient* client) {
+ }
+ }
+
++#if BUILDFLAG(ENABLE_PLUGINS)
+ void SetupPPAPISandboxParameters(sandbox::SeatbeltExecClient* client) {
+ SetupCommonSandboxParameters(client);
+
+@@ -149,6 +154,7 @@ void SetupPPAPISandboxParameters(sandbox::SeatbeltExecClient* client) {
+ // to n+1 more than the plugins added.
+ CHECK(index <= 5);
+ }
++#endif
+
+ void SetupCDMSandboxParameters(sandbox::SeatbeltExecClient* client) {
+ SetupCommonSandboxParameters(client);
+@@ -186,9 +192,11 @@ void SetupSandboxParameters(service_manager::SandboxType sandbox_type,
+ case service_manager::SANDBOX_TYPE_NETWORK:
+ SetupNetworkSandboxParameters(client);
+ break;
++#if BUILDFLAG(ENABLE_PLUGINS)
+ case service_manager::SANDBOX_TYPE_PPAPI:
+ SetupPPAPISandboxParameters(client);
+ break;
++#endif
+ case service_manager::SANDBOX_TYPE_PROFILING:
+ case service_manager::SANDBOX_TYPE_UTILITY:
+ SetupUtilitySandboxParameters(client, command_line);
From e257981a6dc8755b0435cbdbebb59340020fc2ef Mon Sep 17 00:00:00 2001
From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com>
Date: Mon, 14 Oct 2019 12:38:01 -0700
Subject: [PATCH 25/28] spec: allow "Yu Gothic" as a Japanese sans-serif font
on Windows (#20569)
---
spec/chromium-spec.js | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/spec/chromium-spec.js b/spec/chromium-spec.js
index aecc974fc1b94..a06f429113283 100644
--- a/spec/chromium-spec.js
+++ b/spec/chromium-spec.js
@@ -1568,9 +1568,9 @@ describe('font fallback', () => {
const fonts = await getRenderedFonts(html)
expect(fonts).to.be.an('array')
expect(fonts).to.have.length(1)
- expect(fonts[0].familyName).to.equal({
- 'win32': 'Meiryo',
- 'darwin': 'Hiragino Kaku Gothic ProN'
+ expect(fonts[0].familyName).to.be.oneOf({
+ 'win32': ['Meiryo', 'Yu Gothic'],
+ 'darwin': ['Hiragino Kaku Gothic ProN']
}[process.platform])
})
})
From a12de693b08e1103aed6786e7468667acfe56f71 Mon Sep 17 00:00:00 2001
From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com>
Date: Tue, 15 Oct 2019 09:14:25 -0700
Subject: [PATCH 26/28] ci: add macOS debug builds (#20572)
* ci: add macOS debug builds
* Fix mac debug builds
* Remove ninja status as it is not available in 6-0-x
---
.circleci/config.yml | 29 +++++++++++++++++++++++++++++
BUILD.gn | 4 +---
2 files changed, 30 insertions(+), 3 deletions(-)
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 84c4f6ab3d67b..c2e835a0efadf 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -640,9 +640,11 @@ steps-electron-build-for-tests: &steps-electron-build-for-tests
- *step-depot-tools-add-to-path
- *step-setup-env-for-build
- *step-restore-brew-cache
+ - *step-get-more-space-on-mac
- *step-install-npm-deps-on-mac
- *step-fix-sync-on-mac
- *step-gn-gen-default
+ - *step-delete-git-directories
# Electron app
- *step-electron-build
@@ -1099,6 +1101,14 @@ jobs:
<<: *env-enable-sccache
<<: *steps-electron-build-for-tests
+ osx-debug:
+ <<: *machine-mac-large
+ environment:
+ <<: *env-mac-large
+ <<: *env-debug-build
+ <<: *env-enable-sccache
+ <<: *steps-electron-build-for-tests
+
osx-debug-gn-check:
<<: *machine-mac
environment:
@@ -1147,6 +1157,15 @@ jobs:
<<: *env-enable-sccache
<<: *steps-electron-build-for-tests
+ mas-debug:
+ <<: *machine-mac-large
+ environment:
+ <<: *env-mac-large
+ <<: *env-mas
+ <<: *env-debug-build
+ <<: *env-enable-sccache
+ <<: *steps-electron-build-for-tests
+
mas-debug-gn-check:
<<: *machine-mac
environment:
@@ -1470,9 +1489,14 @@ workflows:
requires:
- mac-checkout
+ - osx-debug:
+ requires:
+ - mac-checkout
+
- osx-debug-gn-check:
requires:
- mac-checkout
+
- osx-testing-gn-check:
requires:
- mac-checkout
@@ -1485,9 +1509,14 @@ workflows:
requires:
- mac-checkout
+ - mas-debug:
+ requires:
+ - mac-checkout
+
- mas-debug-gn-check:
requires:
- mac-checkout
+
- mas-testing-gn-check:
requires:
- mac-checkout
diff --git a/BUILD.gn b/BUILD.gn
index a7c471f611fac..de94f837acc9e 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -657,9 +657,7 @@ static_library("electron_lib") {
}
if (enable_desktop_capturer) {
- if (is_component_build && is_win) {
- # On windows the implementation relies on unexported
- # DxgiDuplicatorController class.
+ if (is_component_build && !is_linux) {
deps += [ "//third_party/webrtc/modules/desktop_capture" ]
}
sources += [
From d5b088bc26682d74e3f707f94ea95f71a2e57931 Mon Sep 17 00:00:00 2001
From: Robo
Date: Fri, 18 Oct 2019 09:57:08 -0700
Subject: [PATCH 27/28] fix: add patch to node for native module size issue on
windows (#20614) (#20627)
---
patches/node/.patches | 1 +
...ng_back_node_with_ltcg_configuration.patch | 42 +++++++++++++++++++
2 files changed, 43 insertions(+)
create mode 100644 patches/node/build_bring_back_node_with_ltcg_configuration.patch
diff --git a/patches/node/.patches b/patches/node/.patches
index bf7dc4efef84a..7fa240e76a173 100644
--- a/patches/node/.patches
+++ b/patches/node/.patches
@@ -57,3 +57,4 @@ fix_set_uptime_offset_in_correct_init_method.patch
fix_enable_worker_threads.patch
fsevents-stop-using-fsevents-to-watch-files.patch
fsevents-regression-in-watching.patch
+build_bring_back_node_with_ltcg_configuration.patch
diff --git a/patches/node/build_bring_back_node_with_ltcg_configuration.patch b/patches/node/build_bring_back_node_with_ltcg_configuration.patch
new file mode 100644
index 0000000000000..24fb0cd6e28d0
--- /dev/null
+++ b/patches/node/build_bring_back_node_with_ltcg_configuration.patch
@@ -0,0 +1,42 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Deepak Mohan
+Date: Wed, 16 Oct 2019 13:41:12 -0700
+Subject: build: bring back node_with_ltcg configuration
+
+This was moved to code node.gyp as part of https://github.com/nodejs/node/pull/25931
+which caused native modules size increase which were depending on
+this configuration transitively https://github.com/nodejs/node/issues/29501.
+THe fix for this should land in node-gyp as discussed in above issue,
+landing this as temporary patch.
+
+diff --git a/common.gypi b/common.gypi
+index f07e65f719a1a5939997dfcae7bc787ee6391f4d..69b5439a5c19230e5568450c3aca9ce27661d77c 100644
+--- a/common.gypi
++++ b/common.gypi
+@@ -180,6 +180,26 @@
+ 'cflags': [ '-fPIE' ],
+ 'ldflags': [ '-fPIE', '-pie' ]
+ }],
++ ['node_with_ltcg=="true"', {
++ 'msvs_settings': {
++ 'VCCLCompilerTool': {
++ 'WholeProgramOptimization': 'true' # /GL, whole program optimization, needed for LTCG
++ },
++ 'VCLibrarianTool': {
++ 'AdditionalOptions': [
++ '/LTCG:INCREMENTAL', # incremental link-time code generation
++ ]
++ },
++ 'VCLinkerTool': {
++ 'OptimizeReferences': 2, # /OPT:REF
++ 'EnableCOMDATFolding': 2, # /OPT:ICF
++ 'LinkIncremental': 1, # disable incremental linking
++ 'AdditionalOptions': [
++ '/LTCG:INCREMENTAL', # incremental link-time code generation
++ ]
++ }
++ }
++ }]
+ ],
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
From 9901700a91bfc9a03a2d8f0c73f02129664f62cf Mon Sep 17 00:00:00 2001
From: Milan Burda
Date: Mon, 21 Oct 2019 21:40:21 +0200
Subject: [PATCH 28/28] test: skip desktopCapturer / remote module tests when
the features are disabled (#20566) (#20577)
---
spec-main/api-app-spec.ts | 159 ++++++++++++++++++++------------------
spec-main/spec-helpers.ts | 4 +
2 files changed, 87 insertions(+), 76 deletions(-)
create mode 100644 spec-main/spec-helpers.ts
diff --git a/spec-main/api-app-spec.ts b/spec-main/api-app-spec.ts
index 710607a97c4ca..cf57a25e3d23d 100644
--- a/spec-main/api-app-spec.ts
+++ b/spec-main/api-app-spec.ts
@@ -9,6 +9,9 @@ import split = require('split')
import { app, BrowserWindow, Menu } from 'electron'
import { emittedOnce } from './events-helpers';
import { closeWindow } from './window-helpers';
+import { ifdescribe } from './spec-helpers';
+
+const features = process.electronBinding('features')
const { expect } = chai
@@ -405,103 +408,107 @@ describe('app module', () => {
expect(webContents).to.equal(w.webContents)
})
- it('should emit desktop-capturer-get-sources event when desktopCapturer.getSources() is invoked', async () => {
- w = new BrowserWindow({
- show: false,
- webPreferences: {
- nodeIntegration: true
- }
- })
- await w.loadURL('about:blank')
-
- const promise = emittedOnce(app, 'desktop-capturer-get-sources')
- w.webContents.executeJavaScript(`require('electron').desktopCapturer.getSources({ types: ['screen'] }, () => {})`)
+ ifdescribe(features.isDesktopCapturerEnabled())('desktopCapturer module filtering', () => {
+ it('should emit desktop-capturer-get-sources event when desktopCapturer.getSources() is invoked', async () => {
+ w = new BrowserWindow({
+ show: false,
+ webPreferences: {
+ nodeIntegration: true
+ }
+ })
+ await w.loadURL('about:blank')
- const [, webContents] = await promise
- expect(webContents).to.equal(w.webContents)
- })
+ const promise = emittedOnce(app, 'desktop-capturer-get-sources')
+ w.webContents.executeJavaScript(`require('electron').desktopCapturer.getSources({ types: ['screen'] }, () => {})`)
- it('should emit remote-require event when remote.require() is invoked', async () => {
- w = new BrowserWindow({
- show: false,
- webPreferences: {
- nodeIntegration: true
- }
+ const [, webContents] = await promise
+ expect(webContents).to.equal(w.webContents)
})
- await w.loadURL('about:blank')
+ })
- const promise = emittedOnce(app, 'remote-require')
- w.webContents.executeJavaScript(`require('electron').remote.require('test')`)
+ describe('remote module filtering', () => {
+ it('should emit remote-require event when remote.require() is invoked', async () => {
+ w = new BrowserWindow({
+ show: false,
+ webPreferences: {
+ nodeIntegration: true
+ }
+ })
+ await w.loadURL('about:blank')
- const [, webContents, moduleName] = await promise
- expect(webContents).to.equal(w.webContents)
- expect(moduleName).to.equal('test')
- })
+ const promise = emittedOnce(app, 'remote-require')
+ w.webContents.executeJavaScript(`require('electron').remote.require('test')`)
- it('should emit remote-get-global event when remote.getGlobal() is invoked', async () => {
- w = new BrowserWindow({
- show: false,
- webPreferences: {
- nodeIntegration: true
- }
+ const [, webContents, moduleName] = await promise
+ expect(webContents).to.equal(w.webContents)
+ expect(moduleName).to.equal('test')
})
- await w.loadURL('about:blank')
- const promise = emittedOnce(app, 'remote-get-global')
- w.webContents.executeJavaScript(`require('electron').remote.getGlobal('test')`)
+ it('should emit remote-get-global event when remote.getGlobal() is invoked', async () => {
+ w = new BrowserWindow({
+ show: false,
+ webPreferences: {
+ nodeIntegration: true
+ }
+ })
+ await w.loadURL('about:blank')
- const [, webContents, globalName] = await promise
- expect(webContents).to.equal(w.webContents)
- expect(globalName).to.equal('test')
- })
+ const promise = emittedOnce(app, 'remote-get-global')
+ w.webContents.executeJavaScript(`require('electron').remote.getGlobal('test')`)
- it('should emit remote-get-builtin event when remote.getBuiltin() is invoked', async () => {
- w = new BrowserWindow({
- show: false,
- webPreferences: {
- nodeIntegration: true
- }
+ const [, webContents, globalName] = await promise
+ expect(webContents).to.equal(w.webContents)
+ expect(globalName).to.equal('test')
})
- await w.loadURL('about:blank')
- const promise = emittedOnce(app, 'remote-get-builtin')
- w.webContents.executeJavaScript(`require('electron').remote.app`)
+ it('should emit remote-get-builtin event when remote.getBuiltin() is invoked', async () => {
+ w = new BrowserWindow({
+ show: false,
+ webPreferences: {
+ nodeIntegration: true
+ }
+ })
+ await w.loadURL('about:blank')
- const [, webContents, moduleName] = await promise
- expect(webContents).to.equal(w.webContents)
- expect(moduleName).to.equal('app')
- })
+ const promise = emittedOnce(app, 'remote-get-builtin')
+ w.webContents.executeJavaScript(`require('electron').remote.app`)
- it('should emit remote-get-current-window event when remote.getCurrentWindow() is invoked', async () => {
- w = new BrowserWindow({
- show: false,
- webPreferences: {
- nodeIntegration: true
- }
+ const [, webContents, moduleName] = await promise
+ expect(webContents).to.equal(w.webContents)
+ expect(moduleName).to.equal('app')
})
- await w.loadURL('about:blank')
- const promise = emittedOnce(app, 'remote-get-current-window')
- w.webContents.executeJavaScript(`require('electron').remote.getCurrentWindow()`)
+ it('should emit remote-get-current-window event when remote.getCurrentWindow() is invoked', async () => {
+ w = new BrowserWindow({
+ show: false,
+ webPreferences: {
+ nodeIntegration: true
+ }
+ })
+ await w.loadURL('about:blank')
- const [, webContents] = await promise
- expect(webContents).to.equal(w.webContents)
- })
+ const promise = emittedOnce(app, 'remote-get-current-window')
+ w.webContents.executeJavaScript(`require('electron').remote.getCurrentWindow()`)
- it('should emit remote-get-current-web-contents event when remote.getCurrentWebContents() is invoked', async () => {
- w = new BrowserWindow({
- show: false,
- webPreferences: {
- nodeIntegration: true
- }
+ const [, webContents] = await promise
+ expect(webContents).to.equal(w.webContents)
})
- await w.loadURL('about:blank')
- const promise = emittedOnce(app, 'remote-get-current-web-contents')
- w.webContents.executeJavaScript(`require('electron').remote.getCurrentWebContents()`)
+ it('should emit remote-get-current-web-contents event when remote.getCurrentWebContents() is invoked', async () => {
+ w = new BrowserWindow({
+ show: false,
+ webPreferences: {
+ nodeIntegration: true
+ }
+ })
+ await w.loadURL('about:blank')
+
+ const promise = emittedOnce(app, 'remote-get-current-web-contents')
+ w.webContents.executeJavaScript(`require('electron').remote.getCurrentWebContents()`)
- const [, webContents] = await promise
- expect(webContents).to.equal(w.webContents)
+ const [, webContents] = await promise
+ expect(webContents).to.equal(w.webContents)
+ })
})
})
diff --git a/spec-main/spec-helpers.ts b/spec-main/spec-helpers.ts
new file mode 100644
index 0000000000000..89953c17aae4c
--- /dev/null
+++ b/spec-main/spec-helpers.ts
@@ -0,0 +1,4 @@
+export const ifit = (condition: boolean) => (condition ? it : it.skip)
+export const ifdescribe = (condition: boolean) => (condition ? describe : describe.skip)
+
+export const delay = (time: number) => new Promise(r => setTimeout(r, time))