diff --git a/atom/app/atom_login_helper.mm b/atom/app/atom_login_helper.mm new file mode 100644 index 000000000000..327480adac20 --- /dev/null +++ b/atom/app/atom_login_helper.mm @@ -0,0 +1,11 @@ +#import + +int main(int argc, char* argv[]) { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSArray* pathComponents = [[[NSBundle mainBundle] bundlePath] pathComponents]; + pathComponents = [pathComponents subarrayWithRange:NSMakeRange(0, [pathComponents count] - 4)]; + NSString* path = [NSString pathWithComponents:pathComponents]; + [[NSWorkspace sharedWorkspace] launchApplication:path]; + [pool drain]; + return 0; +} diff --git a/atom/app/resources/mac/loginhelper-Info.plist b/atom/app/resources/mac/loginhelper-Info.plist new file mode 100644 index 000000000000..68348d27a1eb --- /dev/null +++ b/atom/app/resources/mac/loginhelper-Info.plist @@ -0,0 +1,16 @@ + + + + + CFBundleIdentifier + ${ATOM_BUNDLE_ID} + CFBundleName + ${PRODUCT_NAME} + CFBundleExecutable + ${PRODUCT_NAME} + CFBundlePackageType + APPL + LSBackgroundOnly + + + diff --git a/atom/browser/browser_mac.mm b/atom/browser/browser_mac.mm index d187fa6cf905..d12de2c14c9d 100644 --- a/atom/browser/browser_mac.mm +++ b/atom/browser/browser_mac.mm @@ -4,6 +4,7 @@ #include "atom/browser/browser.h" +#include "atom/common/platform_util.h" #include "atom/browser/mac/atom_application.h" #include "atom/browser/mac/atom_application_delegate.h" #include "atom/browser/mac/dict_util.h" @@ -193,19 +194,27 @@ bool Browser::UpdateUserActivityState(const std::string& type, Browser::LoginItemSettings Browser::GetLoginItemSettings( const LoginItemSettings& options) { LoginItemSettings settings; +#if defined(MAS_BUILD) + settings.open_at_login = platform_util::GetLoginItemEnabled(); +#else settings.open_at_login = base::mac::CheckLoginItemStatus( &settings.open_as_hidden); settings.restore_state = base::mac::WasLaunchedAsLoginItemRestoreState(); settings.opened_at_login = base::mac::WasLaunchedAsLoginOrResumeItem(); settings.opened_as_hidden = base::mac::WasLaunchedAsHiddenLoginItem(); +#endif return settings; } void Browser::SetLoginItemSettings(LoginItemSettings settings) { +#if defined(MAS_BUILD) + platform_util::SetLoginItemEnabled(settings.open_at_login); +#else if (settings.open_at_login) base::mac::AddToLoginItems(settings.open_as_hidden); else base::mac::RemoveFromLoginItems(); +#endif } std::string Browser::GetExecutableFileVersion() const { diff --git a/atom/common/platform_util.h b/atom/common/platform_util.h index dc4b4723589b..6fd84056a06a 100644 --- a/atom/common/platform_util.h +++ b/atom/common/platform_util.h @@ -57,6 +57,11 @@ bool MoveItemToTrash(const base::FilePath& full_path); void Beep(); +#if defined(OS_MACOSX) +bool GetLoginItemEnabled(); +void SetLoginItemEnabled(bool enabled); +#endif + } // namespace platform_util #endif // ATOM_COMMON_PLATFORM_UTIL_H_ diff --git a/atom/common/platform_util_mac.mm b/atom/common/platform_util_mac.mm index b48ec51c10fe..c69d05ebbf44 100644 --- a/atom/common/platform_util_mac.mm +++ b/atom/common/platform_util_mac.mm @@ -6,6 +6,7 @@ #import #import +#import #include "base/callback.h" #include "base/files/file_path.h" @@ -98,6 +99,10 @@ std::string OpenURL(NSURL* ns_url, bool activate) { return ""; } +NSString* GetLoginHelperBundleIdentifier() { + return [[[NSBundle mainBundle] bundleIdentifier] stringByAppendingString:@".loginhelper"]; +} + } // namespace namespace platform_util { @@ -177,4 +182,26 @@ void Beep() { NSBeep(); } +bool GetLoginItemEnabled() { + BOOL enabled = NO; + // SMJobCopyDictionary does not work in sandbox (see rdar://13626319) + CFArrayRef jobs = SMCopyAllJobDictionaries(kSMDomainUserLaunchd); + NSArray* jobs_ = CFBridgingRelease(jobs); + NSString* identifier = GetLoginHelperBundleIdentifier(); + if (jobs_ && [jobs_ count] > 0) { + for (NSDictionary* job in jobs_) { + if ([identifier isEqualToString:[job objectForKey:@"Label"]]) { + enabled = [[job objectForKey:@"OnDemand"] boolValue]; + break; + } + } + } + return enabled; +} + +void SetLoginItemEnabled(bool enabled) { + NSString* identifier = GetLoginHelperBundleIdentifier(); + SMLoginItemSetEnabled((__bridge CFStringRef) identifier, enabled); +} + } // namespace platform_util diff --git a/brightray/browser/inspectable_web_contents_impl.cc b/brightray/browser/inspectable_web_contents_impl.cc index 874215f7d917..4d0826990c8c 100644 --- a/brightray/browser/inspectable_web_contents_impl.cc +++ b/brightray/browser/inspectable_web_contents_impl.cc @@ -800,16 +800,21 @@ void InspectableWebContentsImpl::OnURLFetchComplete( DCHECK(it != pending_requests_.end()); base::DictionaryValue response; - auto headers = base::MakeUnique(); + net::HttpResponseHeaders* rh = source->GetResponseHeaders(); response.SetInteger("statusCode", rh ? rh->response_code() : 200); - response.Set("headers", std::move(headers)); - size_t iterator = 0; - std::string name; - std::string value; - while (rh && rh->EnumerateHeaderLines(&iterator, &name, &value)) - headers->SetString(name, value); + { + auto headers = base::MakeUnique(); + + size_t iterator = 0; + std::string name; + std::string value; + while (rh && rh->EnumerateHeaderLines(&iterator, &name, &value)) + headers->SetString(name, value); + + response.Set("headers", std::move(headers)); + } it->second.Run(&response); pending_requests_.erase(it); diff --git a/default_app/main.js b/default_app/main.js index ce77a15362d3..7fdfc7c3fa36 100644 --- a/default_app/main.js +++ b/default_app/main.js @@ -306,7 +306,6 @@ function startRepl () { if (process.platform === 'win32') { console.error('Electron REPL not currently supported on Windows') process.exit(1) - return } const repl = require('repl') diff --git a/docs/api/app.md b/docs/api/app.md index f7ff23e3a755..ff37e9898609 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -893,30 +893,27 @@ need to pass the same arguments here for `openAtLogin` to be set correctly. Returns `Object`: * `openAtLogin` Boolean - `true` if the app is set to open at login. -* `openAsHidden` Boolean - `true` if the app is set to open as hidden at login. - This setting is only supported on macOS. -* `wasOpenedAtLogin` Boolean - `true` if the app was opened at login - automatically. This setting is only supported on macOS. -* `wasOpenedAsHidden` Boolean - `true` if the app was opened as a hidden login +* `openAsHidden` Boolean _macOS_ - `true` if the app is set to open as hidden at login. + This setting is not available on [MAS builds][mas-builds]. +* `wasOpenedAtLogin` Boolean _macOS_ - `true` if the app was opened at login + automatically. This setting is not available on [MAS builds][mas-builds]. +* `wasOpenedAsHidden` Boolean _macOS_ - `true` if the app was opened as a hidden login item. This indicates that the app should not open any windows at startup. - This setting is only supported on macOS. -* `restoreState` Boolean - `true` if the app was opened as a login item that + This setting is not available on [MAS builds][mas-builds]. +* `restoreState` Boolean _macOS_ - `true` if the app was opened as a login item that should restore the state from the previous session. This indicates that the app should restore the windows that were open the last time the app was - closed. This setting is only supported on macOS. - -**Note:** This API has no effect on [MAS builds][mas-builds]. + closed. This setting is not available on [MAS builds][mas-builds]. ### `app.setLoginItemSettings(settings)` _macOS_ _Windows_ * `settings` Object * `openAtLogin` Boolean (optional) - `true` to open the app at login, `false` to remove the app as a login item. Defaults to `false`. - * `openAsHidden` Boolean (optional) - `true` to open the app as hidden. Defaults to + * `openAsHidden` Boolean (optional) _macOS_ - `true` to open the app as hidden. Defaults to `false`. The user can edit this setting from the System Preferences so `app.getLoginItemStatus().wasOpenedAsHidden` should be checked when the app - is opened to know the current value. This setting is only supported on - macOS. + is opened to know the current value. This setting is not available on [MAS builds][mas-builds]. * `path` String (optional) _Windows_ - The executable to launch at login. Defaults to `process.execPath`. * `args` String[] (optional) _Windows_ - The command-line arguments to pass to @@ -944,8 +941,6 @@ app.setLoginItemSettings({ }) ``` -**Note:** This API has no effect on [MAS builds][mas-builds]. - ### `app.isAccessibilitySupportEnabled()` _macOS_ _Windows_ Returns `Boolean` - `true` if Chrome's accessibility support is enabled, diff --git a/docs/api/menu.md b/docs/api/menu.md index 3ccd118091a4..7f694d037892 100644 --- a/docs/api/menu.md +++ b/docs/api/menu.md @@ -67,9 +67,6 @@ The `menu` object has the following instance methods: Must be declared if `y` is declared. * `y` Number (optional) - Default is the current mouse cursor position. Must be declared if `x` is declared. - * `async` Boolean (optional) - Set to `true` to have this method return - immediately called, `false` to return after the menu has been selected - or closed. Defaults to `false`. * `positioningItem` Number (optional) _macOS_ - The index of the menu item to be positioned under the mouse cursor at the specified coordinates. Default is -1. diff --git a/docs/tutorial/mac-app-store-submission-guide.md b/docs/tutorial/mac-app-store-submission-guide.md index 7453857e1ecb..3b77207e4751 100644 --- a/docs/tutorial/mac-app-store-submission-guide.md +++ b/docs/tutorial/mac-app-store-submission-guide.md @@ -45,7 +45,7 @@ has your Team ID as value: ``` -Then, you need to prepare two entitlements files. +Then, you need to prepare three entitlements files. `child.plist`: @@ -77,6 +77,19 @@ Then, you need to prepare two entitlements files. ``` +`loginhelper.plist`: + +```xml + + + + + com.apple.security.app-sandbox + + + +``` + You have to replace `TEAM_ID` with your Team ID, and replace `your.bundle.id` with the Bundle ID of your app. @@ -97,6 +110,7 @@ INSTALLER_KEY="3rd Party Mac Developer Installer: Company Name (APPIDENTITY)" # The path of your plist files. CHILD_PLIST="/path/to/child.plist" PARENT_PLIST="/path/to/parent.plist" +LOGINHELPER_PLIST="/path/to/loginhelper.plist" FRAMEWORKS_PATH="$APP_PATH/Contents/Frameworks" @@ -110,6 +124,8 @@ codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP H codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper EH.app/" codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper NP.app/Contents/MacOS/$APP Helper NP" codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper NP.app/" +codesign -s "$APP_KEY" -f --entitlements "$LOGINHELPER_PLIST" "$APP_PATH/Contents/Library/LoginItems/$APP Login Helper.app/Contents/MacOS/$APP Login Helper" +codesign -s "$APP_KEY" -f --entitlements "$LOGINHELPER_PLIST" "$APP_PATH/Contents/Library/LoginItems/$APP Login Helper.app/" codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$APP_PATH/Contents/MacOS/$APP" codesign -s "$APP_KEY" -f --entitlements "$PARENT_PLIST" "$APP_PATH" @@ -162,8 +178,6 @@ and the following behaviors have been changed: * Video capture may not work for some machines. * Certain accessibility features may not work. * Apps will not be aware of DNS changes. -* APIs for launching apps at login are disabled. See -https://github.com/electron/electron/issues/7312#issuecomment-249479237 Also, due to the usage of app sandboxing, the resources which can be accessed by the app are strictly limited; you can read [App Sandboxing][app-sandboxing] for diff --git a/electron.gyp b/electron.gyp index 645e6aa9aad0..4f3554d88a9a 100644 --- a/electron.gyp +++ b/electron.gyp @@ -122,6 +122,19 @@ }, ], }], + ['mas_build==1', { + 'dependencies': [ + '<(project_name)_login_helper', + ], + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)/<(product_name).app/Contents/Library/LoginItems', + 'files': [ + '<(PRODUCT_DIR)/<(product_name) Login Helper.app', + ], + }, + ], + }], ], }], # OS!="mac" ['OS=="win"', { @@ -577,6 +590,7 @@ '$(SDKROOT)/System/Library/Frameworks/Quartz.framework', '$(SDKROOT)/System/Library/Frameworks/Security.framework', '$(SDKROOT)/System/Library/Frameworks/SecurityInterface.framework', + '$(SDKROOT)/System/Library/Frameworks/ServiceManagement.framework', ], }, 'mac_bundle': 1, @@ -695,6 +709,32 @@ ], }, }, # target helper + { + 'target_name': '<(project_name)_login_helper', + 'product_name': '<(product_name) Login Helper', + 'type': 'executable', + 'sources': [ + '<@(login_helper_sources)', + ], + 'include_dirs': [ + '.', + 'vendor', + '<(libchromiumcontent_src_dir)', + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/AppKit.framework', + ], + }, + 'mac_bundle': 1, + 'xcode_settings': { + 'ATOM_BUNDLE_ID': 'com.<(company_abbr).<(project_name).loginhelper', + 'INFOPLIST_FILE': 'atom/app/resources/mac/loginhelper-Info.plist', + 'OTHER_LDFLAGS': [ + '-ObjC', + ], + }, + }, # target login_helper ], }], # OS!="mac" ], diff --git a/filenames.gypi b/filenames.gypi index f071924231c0..f83be716af21 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -663,6 +663,9 @@ 'atom/app/atom_library_main.h', 'atom/app/atom_library_main.mm', ], + 'login_helper_sources': [ + 'atom/app/atom_login_helper.mm', + ], 'locales': [ 'am', 'ar', 'bg', 'bn', 'ca', 'cs', 'da', 'de', 'el', 'en-GB', 'en-US', 'es-419', 'es', 'et', 'fa', 'fi', 'fil', 'fr', 'gu', 'he', diff --git a/lib/browser/api/auto-updater/squirrel-update-win.js b/lib/browser/api/auto-updater/squirrel-update-win.js index 60345f1a1abe..b0813d1fcdda 100644 --- a/lib/browser/api/auto-updater/squirrel-update-win.js +++ b/lib/browser/api/auto-updater/squirrel-update-win.js @@ -28,7 +28,9 @@ var spawnUpdate = function (args, detached, callback) { // Process spawned, different args: Return with error // No process spawned: Spawn new process if (spawnedProcess && !isSameArgs(args)) { - return callback('AutoUpdater process with arguments ' + args + ' is already running') + // Disabled for backwards compatibility: + // eslint-disable-next-line standard/no-callback-literal + return callback(`AutoUpdater process with arguments ${args} is already running`) } else if (!spawnedProcess) { spawnedProcess = spawn(updateExe, args, { detached: detached @@ -68,7 +70,9 @@ var spawnUpdate = function (args, detached, callback) { // Process terminated with error. if (code !== 0) { - return callback('Command failed: ' + (signal != null ? signal : code) + '\n' + stderr) + // Disabled for backwards compatibility: + // eslint-disable-next-line standard/no-callback-literal + return callback(`Command failed: ${signal != null ? signal : code}\n${stderr}`) } // Success. @@ -93,7 +97,9 @@ exports.checkForUpdate = function (updateURL, callback) { json = stdout.trim().split('\n').pop() update = (ref = JSON.parse(json)) != null ? (ref1 = ref.releasesToApply) != null ? typeof ref1.pop === 'function' ? ref1.pop() : void 0 : void 0 : void 0 } catch (jsonError) { - return callback('Invalid result:\n' + stdout) + // Disabled for backwards compatibility: + // eslint-disable-next-line standard/no-callback-literal + return callback(`Invalid result:\n${stdout}`) } return callback(null, update) }) diff --git a/lib/browser/api/net.js b/lib/browser/api/net.js index d588e238d43a..54ef99d407ff 100644 --- a/lib/browser/api/net.js +++ b/lib/browser/api/net.js @@ -79,7 +79,6 @@ class IncomingMessage extends Readable { this.shouldPush = true this._pushInternalData() } - } URLRequest.prototype._emitRequestEvent = function (isAsync, ...rest) { @@ -103,7 +102,6 @@ URLRequest.prototype._emitResponseEvent = function (isAsync, ...rest) { } class ClientRequest extends EventEmitter { - constructor (options, callback) { super() @@ -354,7 +352,6 @@ class ClientRequest extends EventEmitter { abort () { this.urlRequest.cancel() } - } function writeAfterEndNT (self, error, callback) { diff --git a/lib/browser/api/session.js b/lib/browser/api/session.js index 33f3b47dee0e..6c103d25d623 100644 --- a/lib/browser/api/session.js +++ b/lib/browser/api/session.js @@ -26,6 +26,8 @@ Session.prototype.setCertificateVerifyProc = function (verifyProc) { // TODO(kevinsawicki): Remove in 2.0, deprecate before then with warnings this._setCertificateVerifyProc(({hostname, certificate, verificationResult}, cb) => { verifyProc(hostname, certificate, (result) => { + // Disabled due to false positive in StandardJS + // eslint-disable-next-line standard/no-callback-literal cb(result ? 0 : -2) }) }) diff --git a/lib/browser/api/web-contents.js b/lib/browser/api/web-contents.js index 61b37f773317..f770dbb31b3c 100644 --- a/lib/browser/api/web-contents.js +++ b/lib/browser/api/web-contents.js @@ -6,6 +6,7 @@ const {app, ipcMain, session, NavigationController} = electron // session is not used here, the purpose is to make sure session is initalized // before the webContents module. +// eslint-disable-next-line session let nextId = 0 diff --git a/lib/browser/chrome-extension.js b/lib/browser/chrome-extension.js index 868e07e96096..af88438d33dd 100644 --- a/lib/browser/chrome-extension.js +++ b/lib/browser/chrome-extension.js @@ -311,6 +311,8 @@ const chromeExtensionHandler = function (request, callback) { const page = backgroundPages[parsed.hostname] if (page && parsed.path === `/${page.name}`) { + // Disabled due to false positive in StandardJS + // eslint-disable-next-line standard/no-callback-literal return callback({ mimeType: 'text/html', data: page.html @@ -319,6 +321,8 @@ const chromeExtensionHandler = function (request, callback) { fs.readFile(path.join(manifest.srcDirectory, parsed.path), function (err, content) { if (err) { + // Disabled due to false positive in StandardJS + // eslint-disable-next-line standard/no-callback-literal return callback(-6) // FILE_NOT_FOUND } else { return callback(content) diff --git a/lib/common/asar.js b/lib/common/asar.js index e35efc279958..1b9a993a2e67 100644 --- a/lib/common/asar.js +++ b/lib/common/asar.js @@ -367,6 +367,8 @@ return invalidArchiveError(asarPath, callback) } process.nextTick(function () { + // Disabled due to false positive in StandardJS + // eslint-disable-next-line standard/no-callback-literal callback(archive.stat(filePath) !== false) }) } @@ -482,7 +484,7 @@ } if (info.size === 0) { return process.nextTick(function () { - callback(null, encoding ? '' : new Buffer(0)) + callback(null, encoding ? '' : Buffer.alloc(0)) }) } if (info.unpacked) { @@ -490,7 +492,7 @@ return fs.readFile(realPath, options, callback) } - const buffer = new Buffer(info.size) + const buffer = Buffer.alloc(info.size) const fd = archive.getFd() if (!(fd >= 0)) { return notFoundError(asarPath, filePath, callback) @@ -519,7 +521,7 @@ if (options) { return '' } else { - return new Buffer(0) + return Buffer.alloc(0) } } if (info.unpacked) { @@ -538,7 +540,7 @@ throw new TypeError('Bad arguments') } const {encoding} = options - const buffer = new Buffer(info.size) + const buffer = Buffer.alloc(info.size) const fd = archive.getFd() if (!(fd >= 0)) { notFoundError(asarPath, filePath) @@ -611,7 +613,7 @@ encoding: 'utf8' }) } - const buffer = new Buffer(info.size) + const buffer = Buffer.alloc(info.size) const fd = archive.getFd() if (!(fd >= 0)) { return diff --git a/lib/renderer/chrome-api.js b/lib/renderer/chrome-api.js index 1b509178f49e..07b940675b30 100644 --- a/lib/renderer/chrome-api.js +++ b/lib/renderer/chrome-api.js @@ -147,6 +147,8 @@ exports.injectTo = function (extensionId, isBackgroundPage, context) { executeScript (tabId, details, callback) { const requestId = ++nextId ipcRenderer.once(`CHROME_TABS_EXECUTESCRIPT_RESULT_${requestId}`, (event, result) => { + // Disabled due to false positive in StandardJS + // eslint-disable-next-line standard/no-callback-literal callback([event.result]) }) ipcRenderer.send('CHROME_TABS_EXECUTESCRIPT', requestId, tabId, extensionId, details) diff --git a/lib/renderer/extensions/storage.js b/lib/renderer/extensions/storage.js index 2920a2860e03..f2a560f81c2c 100644 --- a/lib/renderer/extensions/storage.js +++ b/lib/renderer/extensions/storage.js @@ -51,6 +51,8 @@ const getStorage = (storageType, extensionId, cb) => { if (data !== null) { cb(JSON.parse(data)) } else { + // Disabled due to false positive in StandardJS + // eslint-disable-next-line standard/no-callback-literal cb({}) } }) @@ -82,6 +84,9 @@ const getStorageManager = (storageType, extensionId) => { } break } + + // Disabled due to false positive in StandardJS + // eslint-disable-next-line standard/no-callback-literal if (keys.length === 0) return callback({}) let items = {} diff --git a/package.json b/package.json index 14c3ba9421db..acf290904f64 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "remark-cli": "^4.0.0", "remark-preset-lint-markdown-style-guide": "^2.1.1", "request": "^2.68.0", - "standard": "^8.4.0", + "standard": "^10.0.0", "standard-markdown": "^4.0.0", "sumchecker": "^2.0.2", "temp": "^0.8.3" diff --git a/script/ci-release-build.js b/script/ci-release-build.js index e6870246b569..d80025ab9d45 100644 --- a/script/ci-release-build.js +++ b/script/ci-release-build.js @@ -32,7 +32,7 @@ async function makeRequest (requestOptions, parseResponse) { } else { console.log('Error: ', `(status ${res.statusCode})`, err || res.body, requestOptions) } - reject() + reject(err) } }) }) diff --git a/script/merge-release.js b/script/merge-release.js index 60ac3acb244c..8917da4f2f23 100755 --- a/script/merge-release.js +++ b/script/merge-release.js @@ -31,7 +31,7 @@ async function checkoutBranch (branchName) { console.log(`Checking out ${branchName}.`) let errorMessage = `Error checking out branch ${branchName}:` let successMessage = `Successfully checked out branch ${branchName}.` - return await callGit(['checkout', branchName], errorMessage, successMessage) + return callGit(['checkout', branchName], errorMessage, successMessage) } async function commitMerge () { @@ -39,7 +39,7 @@ async function commitMerge () { let errorMessage = `Error committing merge:` let successMessage = `Successfully committed the merge for v${pkg.version}` let gitArgs = ['commit', '-m', `v${pkg.version}`] - return await callGit(gitArgs, errorMessage, successMessage) + return callGit(gitArgs, errorMessage, successMessage) } async function mergeReleaseIntoBranch (branchName) { @@ -67,14 +67,14 @@ async function pushBranch (branchName) { let pushArgs = ['push', 'origin', branchName] let errorMessage = `Could not push branch ${branchName} due to an error:` let successMessage = `Successfully pushed branch ${branchName}.` - return await callGit(pushArgs, errorMessage, successMessage) + return callGit(pushArgs, errorMessage, successMessage) } async function pull () { console.log(`Performing a git pull`) let errorMessage = `Could not pull due to an error:` let successMessage = `Successfully performed a git pull` - return await callGit(['pull'], errorMessage, successMessage) + return callGit(['pull'], errorMessage, successMessage) } async function rebase (targetBranch) { @@ -82,7 +82,7 @@ async function rebase (targetBranch) { let errorMessage = `Could not rebase due to an error:` let successMessage = `Successfully rebased release branch from ` + `${targetBranch}` - return await callGit(['rebase', targetBranch], errorMessage, successMessage) + return callGit(['rebase', targetBranch], errorMessage, successMessage) } async function mergeRelease () { diff --git a/script/release.js b/script/release.js index 1baa56a7c886..50ab0aff0897 100755 --- a/script/release.js +++ b/script/release.js @@ -215,7 +215,7 @@ async function uploadShasumFile (filePath, fileName, release) { filePath, name: fileName } - return await github.repos.uploadAsset(githubOpts) + return github.repos.uploadAsset(githubOpts) .catch(err => { console.log(`${fail} Error uploading ${filePath} to GitHub:`, err) process.exit(1) @@ -250,7 +250,7 @@ async function publishRelease (release) { tag_name: release.tag_name, draft: false } - return await github.repos.editRelease(githubOpts) + return github.repos.editRelease(githubOpts) .catch(err => { console.log(`${fail} Error publishing release:`, err) process.exit(1) @@ -447,7 +447,7 @@ async function cleanupReleaseBranch () { await callGit(['branch', '-D', 'release'], errorMessage, successMessage) errorMessage = `Could not delete remote release branch.` successMessage = `Successfully deleted remote release branch.` - return await callGit(['push', 'origin', ':release'], errorMessage, successMessage) + return callGit(['push', 'origin', ':release'], errorMessage, successMessage) } async function callGit (args, errorMessage, successMessage) { diff --git a/spec/api-app-spec.js b/spec/api-app-spec.js index e296e8a5c21f..2807df607029 100644 --- a/spec/api-app-spec.js +++ b/spec/api-app-spec.js @@ -397,7 +397,7 @@ describe('app module', () => { app.setLoginItemSettings({openAtLogin: false, path: updateExe, args: processStartArgs}) }) - it('returns the login item status of the app', () => { + it('returns the login item status of the app', (done) => { app.setLoginItemSettings({openAtLogin: true}) assert.deepEqual(app.getLoginItemSettings(), { openAtLogin: true, @@ -410,20 +410,25 @@ describe('app module', () => { app.setLoginItemSettings({openAtLogin: true, openAsHidden: true}) assert.deepEqual(app.getLoginItemSettings(), { openAtLogin: true, - openAsHidden: process.platform === 'darwin', // Only available on macOS + openAsHidden: process.platform === 'darwin' && !process.mas, // Only available on macOS wasOpenedAtLogin: false, wasOpenedAsHidden: false, restoreState: false }) app.setLoginItemSettings({}) - assert.deepEqual(app.getLoginItemSettings(), { - openAtLogin: false, - openAsHidden: false, - wasOpenedAtLogin: false, - wasOpenedAsHidden: false, - restoreState: false - }) + // Wait because login item settings are not applied immediately in MAS build + const delay = process.mas ? 100 : 0 + setTimeout(() => { + assert.deepEqual(app.getLoginItemSettings(), { + openAtLogin: false, + openAsHidden: false, + wasOpenedAtLogin: false, + wasOpenedAsHidden: false, + restoreState: false + }) + done() + }, delay) }) it('allows you to pass a custom executable and arguments', function () { diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index 55ca6c66c77f..d04c340dbb90 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -27,7 +27,7 @@ describe('BrowserWindow module', () => { postData = [ { type: 'rawData', - bytes: new Buffer('username=test&file=') + bytes: Buffer.from('username=test&file=') }, { type: 'file', @@ -153,7 +153,7 @@ describe('BrowserWindow module', () => { ] const responseEvent = 'window-webContents-destroyed' - function* genNavigationEvent () { + function * genNavigationEvent () { let eventOptions = null while ((eventOptions = events.shift()) && events.length) { let w = new BrowserWindow({show: false}) @@ -270,7 +270,7 @@ describe('BrowserWindow module', () => { assert.equal(isMainFrame, true) done() }) - const data = new Buffer(2 * 1024 * 1024).toString('base64') + const data = Buffer.alloc(2 * 1024 * 1024).toString('base64') w.loadURL(`data:image/png;base64,${data}`) }) @@ -1056,6 +1056,8 @@ describe('BrowserWindow module', () => { // http protocol to simulate accessing another domain. This is required // because the code paths for cross domain popups is different. function crossDomainHandler (request, callback) { + // Disabled due to false positive in StandardJS + // eslint-disable-next-line standard/no-callback-literal callback({ mimeType: 'text/html', data: `

${request.url}

` @@ -3033,6 +3035,8 @@ const isScaleFactorRounding = () => { function serveFileFromProtocol (protocolName, filePath) { return new Promise((resolve, reject) => { protocol.registerBufferProtocol(protocolName, (request, callback) => { + // Disabled due to false positive in StandardJS + // eslint-disable-next-line standard/no-callback-literal callback({ mimeType: 'text/html', data: fs.readFileSync(filePath) diff --git a/spec/api-ipc-spec.js b/spec/api-ipc-spec.js index 79f7c0927037..b7b233adc3db 100644 --- a/spec/api-ipc-spec.js +++ b/spec/api-ipc-spec.js @@ -145,7 +145,7 @@ describe('ipc module', () => { describe('remote.createFunctionWithReturnValue', () => { it('should be called in browser synchronously', () => { - const buf = new Buffer('test') + const buf = Buffer.from('test') const call = remote.require(path.join(fixtures, 'module', 'call.js')) const result = call.call(remote.createFunctionWithReturnValue(buf)) assert.equal(result.constructor.name, 'Buffer') @@ -195,6 +195,7 @@ describe('ipc module', () => { const foo = remote.require(path.join(fixtures, 'module', 'error-properties.js')) assert.throws(() => { + // eslint-disable-next-line foo.bar }, /getting error/) @@ -239,7 +240,7 @@ describe('ipc module', () => { const printName = remote.require(print) it('keeps its constructor name for objects', () => { - const buf = new Buffer('test') + const buf = Buffer.from('test') assert.equal(printName.print(buf), 'Buffer') }) diff --git a/spec/api-native-image-spec.js b/spec/api-native-image-spec.js index 9a7896e5b945..75c55bd4bab8 100644 --- a/spec/api-native-image-spec.js +++ b/spec/api-native-image-spec.js @@ -1,5 +1,7 @@ 'use strict' +/* eslint-disable no-unused-expressions */ + const {expect} = require('chai') const {nativeImage} = require('electron') const path = require('path') diff --git a/spec/api-net-spec.js b/spec/api-net-spec.js index 69aa1154ee8e..4f9abfe1a5ff 100644 --- a/spec/api-net-spec.js +++ b/spec/api-net-spec.js @@ -6,6 +6,9 @@ const url = require('url') const {net} = remote const {session} = remote +/* The whole net API doesn't use standard callbacks */ +/* eslint-disable standard/no-callback-literal */ + function randomBuffer (size, start, end) { start = start || 0 end = end || 255 @@ -855,6 +858,8 @@ describe('net module', () => { (details, callback) => { if (details.url === `${server.url}${requestUrl}`) { requestIsIntercepted = true + // Disabled due to false positive in StandardJS + // eslint-disable-next-line standard/no-callback-literal callback({ redirectURL: `${server.url}${redirectUrl}` }) @@ -907,6 +912,8 @@ describe('net module', () => { customSession.webRequest.onBeforeRequest((details, callback) => { if (details.url === `${server.url}${requestUrl}`) { requestIsIntercepted = true + // Disabled due to false positive in StandardJS + // eslint-disable-next-line standard/no-callback-literal callback({ redirectURL: `${server.url}${redirectUrl}` }) @@ -1154,6 +1161,8 @@ describe('net module', () => { url: `${server.url}${requestUrl}`, session: 1 }) + + // eslint-disable-next-line urlRequest } catch (exception) { done() @@ -1223,6 +1232,8 @@ describe('net module', () => { url: `${server.url}${requestUrl}`, partition: 1 }) + + // eslint-disable-next-line urlRequest } catch (exception) { done() diff --git a/spec/api-protocol-spec.js b/spec/api-protocol-spec.js index 2d76d49c6a53..f214bfc6d27f 100644 --- a/spec/api-protocol-spec.js +++ b/spec/api-protocol-spec.js @@ -10,6 +10,9 @@ const {BrowserWindow, ipcMain, protocol, session, webContents} = remote // and use Stream instances created in the browser process. const stream = remote.require('stream') +/* The whole protocol API doesn't use standard callbacks */ +/* eslint-disable standard/no-callback-literal */ + describe('protocol module', () => { const protocolName = 'sp' const text = 'valar morghulis' @@ -28,7 +31,7 @@ describe('protocol module', () => { const body = stream.PassThrough() async function sendChunks () { - let buf = new Buffer(data) + let buf = Buffer.from(data) for (;;) { body.push(buf.slice(0, chunkSize)) buf = buf.slice(chunkSize) @@ -204,7 +207,7 @@ describe('protocol module', () => { }) describe('protocol.registerBufferProtocol', () => { - const buffer = new Buffer(text) + const buffer = Buffer.from(text) it('sends Buffer as response', (done) => { const handler = (request, callback) => callback(buffer) protocol.registerBufferProtocol(protocolName, handler, (error) => { @@ -767,7 +770,7 @@ describe('protocol module', () => { describe('protocol.interceptBufferProtocol', () => { it('can intercept http protocol', (done) => { - const handler = (request, callback) => callback(new Buffer(text)) + const handler = (request, callback) => callback(Buffer.from(text)) protocol.interceptBufferProtocol('http', handler, (error) => { if (error) return done(error) $.ajax({ diff --git a/spec/api-session-spec.js b/spec/api-session-spec.js index 54235a334a54..cf6296cd448f 100644 --- a/spec/api-session-spec.js +++ b/spec/api-session-spec.js @@ -10,6 +10,9 @@ const {closeWindow} = require('./window-helpers') const {ipcRenderer, remote} = require('electron') const {ipcMain, session, BrowserWindow, net} = remote +/* The whole session API doesn't use standard callbacks */ +/* eslint-disable standard/no-callback-literal */ + describe('session module', () => { let fixtures = path.resolve(__dirname, 'fixtures') let w = null @@ -242,7 +245,7 @@ describe('session module', () => { }) it('can cancel default download behavior', (done) => { - const mockFile = new Buffer(1024) + const mockFile = Buffer.alloc(1024) const contentDisposition = 'inline; filename="mockFile.txt"' const downloadServer = http.createServer((req, res) => { res.writeHead(200, { @@ -271,7 +274,7 @@ describe('session module', () => { }) describe('DownloadItem', () => { - const mockPDF = new Buffer(1024 * 1024 * 5) + const mockPDF = Buffer.alloc(1024 * 1024 * 5) let contentDisposition = 'inline; filename="mock.pdf"' const downloadFilePath = path.join(fixtures, 'mock.pdf') const downloadServer = http.createServer((req, res) => { diff --git a/spec/api-web-contents-spec.js b/spec/api-web-contents-spec.js index 39e466d56bce..4e5cc022df7c 100644 --- a/spec/api-web-contents-spec.js +++ b/spec/api-web-contents-spec.js @@ -10,6 +10,9 @@ const {BrowserWindow, webContents, ipcMain, session} = remote const isCi = remote.getGlobal('isCi') +/* The whole webContents API doesn't use standard callbacks */ +/* eslint-disable standard/no-callback-literal */ + describe('webContents module', () => { const fixtures = path.resolve(__dirname, 'fixtures') let w @@ -634,7 +637,7 @@ describe('webContents module', () => { ] const responseEvent = 'webcontents-destroyed' - function* genNavigationEvent () { + function * genNavigationEvent () { let eventOptions = null while ((eventOptions = events.shift()) && events.length) { eventOptions.responseEvent = responseEvent diff --git a/spec/api-web-frame-spec.js b/spec/api-web-frame-spec.js index ce0d0436ec58..a62c075d8e86 100644 --- a/spec/api-web-frame-spec.js +++ b/spec/api-web-frame-spec.js @@ -4,6 +4,9 @@ const {closeWindow} = require('./window-helpers') const {remote, webFrame} = require('electron') const {BrowserWindow, protocol, ipcMain} = remote +/* Most of the APIs here don't use standard callbacks */ +/* eslint-disable standard/no-callback-literal */ + describe('webFrame module', function () { var fixtures = path.resolve(__dirname, 'fixtures') var w = null diff --git a/spec/api-web-request-spec.js b/spec/api-web-request-spec.js index 6ad0550eb7d4..7dc1f370ce86 100644 --- a/spec/api-web-request-spec.js +++ b/spec/api-web-request-spec.js @@ -4,6 +4,9 @@ const qs = require('querystring') const remote = require('electron').remote const session = remote.session +/* The whole webRequest API doesn't use standard callbacks */ +/* eslint-disable standard/no-callback-literal */ + describe('webRequest module', () => { const ses = session.defaultSession const server = http.createServer((req, res) => { diff --git a/spec/asar-spec.js b/spec/asar-spec.js index 31f15ef77284..f87554f32e26 100644 --- a/spec/asar-spec.js +++ b/spec/asar-spec.js @@ -15,7 +15,7 @@ describe('asar package', function () { describe('node api', function () { it('supports paths specified as a Buffer', function () { - var file = new Buffer(path.join(fixtures, 'asar', 'a.asar', 'file1')) + var file = Buffer.from(path.join(fixtures, 'asar', 'a.asar', 'file1')) assert.equal(fs.existsSync(file), true) }) @@ -491,7 +491,7 @@ describe('asar package', function () { file = ref2[j] p = path.join(fixtures, 'asar', 'a.asar', file) fd = fs.openSync(p, 'r') - buffer = new Buffer(6) + buffer = Buffer.alloc(6) fs.readSync(fd, buffer, 0, 6, 0) assert.equal(String(buffer).trim(), 'file1') fs.closeSync(fd) @@ -512,7 +512,7 @@ describe('asar package', function () { var p = path.join(fixtures, 'asar', 'a.asar', 'file1') fs.open(p, 'r', function (err, fd) { assert.equal(err, null) - var buffer = new Buffer(6) + var buffer = Buffer.alloc(6) fs.read(fd, buffer, 0, 6, 0, function (err) { assert.equal(err, null) assert.equal(String(buffer).trim(), 'file1') diff --git a/spec/chromium-spec.js b/spec/chromium-spec.js index 1420fed7c6a7..f068ef75f12d 100644 --- a/spec/chromium-spec.js +++ b/spec/chromium-spec.js @@ -11,6 +11,9 @@ const {app, BrowserWindow, ipcMain, protocol, session, webContents} = remote const isCI = remote.getGlobal('isCi') +/* Most of the APIs here don't use standard callbacks */ +/* eslint-disable standard/no-callback-literal */ + describe('chromium feature', () => { const fixtures = path.resolve(__dirname, 'fixtures') let listener = null diff --git a/spec/node-spec.js b/spec/node-spec.js index 44174e3c772f..48121ee84ceb 100644 --- a/spec/node-spec.js +++ b/spec/node-spec.js @@ -300,7 +300,7 @@ describe('node feature', () => { it('can be created from WebKit external string', () => { const p = document.createElement('p') p.innerText = '闲云潭影日悠悠,物换星移几度秋' - const b = new Buffer(p.innerText) + const b = Buffer.from(p.innerText) assert.equal(b.toString(), '闲云潭影日悠悠,物换星移几度秋') assert.equal(Buffer.byteLength(p.innerText), 45) }) @@ -308,15 +308,15 @@ describe('node feature', () => { it('correctly parses external one-byte UTF8 string', () => { const p = document.createElement('p') p.innerText = 'Jøhänñéß' - const b = new Buffer(p.innerText) + const b = Buffer.from(p.innerText) assert.equal(b.toString(), 'Jøhänñéß') assert.equal(Buffer.byteLength(p.innerText), 13) }) it('does not crash when creating large Buffers', () => { - let buffer = new Buffer(new Array(4096).join(' ')) + let buffer = Buffer.from(new Array(4096).join(' ')) assert.equal(buffer.length, 4095) - buffer = new Buffer(new Array(4097).join(' ')) + buffer = Buffer.from(new Array(4097).join(' ')) assert.equal(buffer.length, 4096) }) }) @@ -324,6 +324,7 @@ describe('node feature', () => { describe('process.stdout', () => { it('does not throw an exception when accessed', () => { assert.doesNotThrow(() => { + // eslint-disable-next-line process.stdout }) }) @@ -358,7 +359,7 @@ describe('node feature', () => { describe('process.stdin', () => { it('does not throw an exception when accessed', () => { assert.doesNotThrow(() => { - process.stdin + process.stdin // eslint-disable-line }) }) diff --git a/spec/static/main.js b/spec/static/main.js index 4a4dfd109df3..80c8e716c678 100644 --- a/spec/static/main.js +++ b/spec/static/main.js @@ -32,9 +32,11 @@ app.commandLine.appendSwitch('disable-renderer-backgrounding') // Accessing stdout in the main process will result in the process.stdout // throwing UnknownSystemError in renderer process sometimes. This line makes // sure we can reproduce it in renderer process. +// eslint-disable-next-line process.stdout // Access console to reproduce #3482. +// eslint-disable-next-line console ipcMain.on('message', function (event, ...args) { @@ -378,6 +380,8 @@ const suspendListeners = (emitter, eventName, callback) => { listeners.forEach((listener) => { emitter.on(eventName, listener) }) + + // eslint-disable-next-line standard/no-callback-literal callback(...args) }) } diff --git a/spec/webview-spec.js b/spec/webview-spec.js index c68a492bbdf2..aaf2cbee3866 100644 --- a/spec/webview-spec.js +++ b/spec/webview-spec.js @@ -9,6 +9,9 @@ const {closeWindow} = require('./window-helpers') const isCI = remote.getGlobal('isCi') const nativeModulesEnabled = remote.getGlobal('nativeModulesEnabled') +/* Most of the APIs here don't use standard callbacks */ +/* eslint-disable standard/no-callback-literal */ + describe(' tag', function () { this.timeout(3 * 60 * 1000) @@ -1425,7 +1428,7 @@ describe(' tag', function () { }) webview.style.display = 'none' - webview.offsetHeight + webview.offsetHeight // eslint-disable-line webview.style.display = 'block' }) webview.src = `file://${fixtures}/pages/a.html` @@ -1444,7 +1447,7 @@ describe(' tag', function () { }) webview.style.display = 'none' - webview.offsetHeight + webview.offsetHeight // eslint-disable-line webview.style.display = 'block' }) webview.src = `file://${fixtures}/pages/a.html` diff --git a/vendor/libchromiumcontent b/vendor/libchromiumcontent index 5d55b4ebd1f1..fe78f44d3e1d 160000 --- a/vendor/libchromiumcontent +++ b/vendor/libchromiumcontent @@ -1 +1 @@ -Subproject commit 5d55b4ebd1f1597394360c16eb4fcec7889148b9 +Subproject commit fe78f44d3e1d6cc38454fd6fbae324124830b1ef