Repository: electron/electron-packager (js)

Issue:
Add support for official builds of Windows ARM64 binaries
### Preflight Checklist
<!-- Please ensure you've completed the following steps by replacing [ ] with [x]-->

* [x ] I have read the [contribution documentation](https://github.com/electron/electron-packager/blob/master/CONTRIBUTING.md) for this project.
* [x ] I agree to follow the [code of conduct](https://github.com/electron/electron/blob/master/CODE_OF_CONDUCT.md) that this project follows, as appropriate.
* [x ] I have searched the issue tracker for a feature request that matches the one I want to file, without success.

### Problem Description
Since chromium/electron started to support windows arm64, is there a support for windows arm64 of electron-packager? or it is under working?



Pull request description:
feat: add support for win32/arm64 official builds
* [x] I have read the [contribution documentation](https://github.com/electron/electron-packager/blob/master/CONTRIBUTING.md) for this project.
* [x] I agree to follow the [code of conduct](https://github.com/electron/electron/blob/master/CODE_OF_CONDUCT.md) that this project follows, as appropriate.
* [x] The changes are appropriately documented (if applicable).
* [x] The changes have sufficient test coverage (if applicable).
* [x] The testsuite passes successfully on my local machine (if applicable).

**Summarize your changes:**

Official win32/arm64 builds were added in Electron [6.0.8](https://github.com/electron/electron/releases/tag/v6.0.8).

Fixes #1052.

Patch:
diff --git a/NEWS.md b/NEWS.md
index 70227ce..4909b80 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -7,6 +7,7 @@
 ### Added
 
 * (darwin/mas only) `usageDescription` option
+* Support for official win32/arm64 builds
 
 ## [14.0.6] - 2019-09-09
 
diff --git a/README.md b/README.md
index 67a253a..82bc8b0 100644
--- a/README.md
+++ b/README.md
@@ -43,7 +43,7 @@ Electron Packager is known to run on the following **host** platforms:
 
 It generates executables/bundles for the following **target** platforms:
 
-* Windows (also known as `win32`, for both 32/64 bit)
+* Windows (also known as `win32`, for x86, x86_64, and arm64 architectures)
 * macOS (also known as `darwin`) / [Mac App Store](https://electronjs.org/docs/tutorial/mac-app-store-submission-guide/) (also known as `mas`)<sup>*</sup>
 * Linux (for x86, x86_64, armv7l, arm64, and mips64el architectures)
 
diff --git a/package.json b/package.json
index 863f1b0..6d049a6 100644
--- a/package.json
+++ b/package.json
@@ -41,7 +41,7 @@
     "resolve": "^1.1.6",
     "sanitize-filename": "^1.6.0",
     "semver": "^6.0.0",
-    "yargs-parser": "^13.0.0"
+    "yargs-parser": "^15.0.0"
   },
   "devDependencies": {
     "ava": "^2.0.0",
@@ -49,9 +49,9 @@
     "codecov": "^3.0.0",
     "eslint": "^6.0.0",
     "eslint-config-standard": "^14.0.0",
-    "eslint-plugin-ava": "^8.0.0",
+    "eslint-plugin-ava": "^9.0.0",
     "eslint-plugin-import": "^2.2.0",
-    "eslint-plugin-node": "^9.0.1",
+    "eslint-plugin-node": "^10.0.0",
     "eslint-plugin-promise": "^4.0.1",
     "eslint-plugin-standard": "^4.0.0",
     "nyc": "^14.0.0",
diff --git a/src/targets.js b/src/targets.js
index 9e62825..8575fcb 100644
--- a/src/targets.js
+++ b/src/targets.js
@@ -10,12 +10,17 @@ const officialPlatformArchCombos = {
   darwin: ['x64'],
   linux: ['ia32', 'x64', 'armv7l', 'arm64', 'mips64el'],
   mas: ['x64'],
-  win32: ['ia32', 'x64']
+  win32: ['ia32', 'x64', 'arm64']
 }
 
-const linuxArchBuildVersions = {
-  arm64: '>= 1.8.0',
-  mips64el: '^1.8.2-beta.5'
+const buildVersions = {
+  linux: {
+    arm64: '>= 1.8.0',
+    mips64el: '^1.8.2-beta.5'
+  },
+  win32: {
+    arm64: '>= 6.0.8'
+  }
 }
 
 // Maps to module filename for each platform (lazy-required if used)
@@ -39,10 +44,10 @@ function createPlatformArchPairs (opts, selectedPlatforms, selectedArchs, ignore
         if (!validOfficialPlatformArch(opts, platform, arch)) {
           warnIfAllNotSpecified(opts, `The platform/arch combination ${platform}/${arch} is not currently supported by Electron Packager`)
           continue
-        } else if (platform === 'linux') {
-          const buildVersion = linuxArchBuildVersions[arch]
-          if (buildVersion && !officialLinuxBuildExists(opts, buildVersion)) {
-            warnIfAllNotSpecified(opts, `Official linux/${arch} support only exists in Electron ${buildVersion}`)
+        } else if (buildVersions[platform] && buildVersions[platform][arch]) {
+          const buildVersion = buildVersions[platform][arch]
+          if (buildVersion && !officialBuildExists(opts, buildVersion)) {
+            warnIfAllNotSpecified(opts, `Official ${platform}/${arch} support only exists in Electron ${buildVersion}`)
             continue
           }
         }
@@ -67,7 +72,7 @@ function validOfficialPlatformArch (opts, platform, arch) {
   return officialPlatformArchCombos[platform] && officialPlatformArchCombos[platform].includes(arch)
 }
 
-function officialLinuxBuildExists (opts, buildVersion) {
+function officialBuildExists (opts, buildVersion) {
   return semver.satisfies(opts.electronVersion, buildVersion)
 }
 
@@ -84,9 +89,9 @@ function warnIfAllNotSpecified (opts, message) {
 module.exports = {
   allOfficialArchsForPlatformAndVersion: function allOfficialArchsForPlatformAndVersion (platform, electronVersion) {
     const archs = officialPlatformArchCombos[platform]
-    if (platform === 'linux') {
-      const excludedArchs = Object.keys(linuxArchBuildVersions)
-        .filter(arch => !officialLinuxBuildExists({ electronVersion: electronVersion }, linuxArchBuildVersions[arch]))
+    if (buildVersions[platform]) {
+      const excludedArchs = Object.keys(buildVersions[platform])
+        .filter(arch => !officialBuildExists({ electronVersion: electronVersion }, buildVersions[platform][arch]))
       return archs.filter(arch => !excludedArchs.includes(arch))
     }
 


Test patch:
diff --git a/test/_util.js b/test/_util.js
index 7cf7428..6f189ef 100644
--- a/test/_util.js
+++ b/test/_util.js
@@ -47,7 +47,7 @@ function packagerTestOptions (t) {
 }
 
 module.exports = {
-  allPlatformArchCombosCount: 9,
+  allPlatformArchCombosCount: 10,
   assertDirectory: async function assertDirectory (t, pathToCheck, message) {
     const stats = await fs.stat(pathToCheck)
     t.true(stats.isDirectory(), message)
diff --git a/test/targets.js b/test/targets.js
index 60525ba..a9c271c 100644
--- a/test/targets.js
+++ b/test/targets.js
@@ -39,20 +39,27 @@ test('allOfficialArchsForPlatformAndVersion returns the correct arches for a kno
   t.deepEqual(targets.allOfficialArchsForPlatformAndVersion('darwin', '1.0.0'), ['x64'])
 })
 
-test('allOfficialArchsForPlatformAndVersion returns arm64 when the correct version is specified', t => {
+test('allOfficialArchsForPlatformAndVersion returns linux/arm64 when the correct version is specified', t => {
   t.true(targets.allOfficialArchsForPlatformAndVersion('linux', '1.8.0').includes('arm64'),
          'should be found when version is >= 1.8.0')
   t.false(targets.allOfficialArchsForPlatformAndVersion('linux', '1.7.0').includes('arm64'),
           'should not be found when version is < 1.8.0')
 })
 
-test('allOfficialArchsForPlatformAndVersion returns mips64el when the correct version is specified', t => {
+test('allOfficialArchsForPlatformAndVersion returns linux/mips64el when the correct version is specified', t => {
   t.true(targets.allOfficialArchsForPlatformAndVersion('linux', '1.8.2').includes('mips64el'),
          'should be found when version is >= 1.8.2-beta.5')
   t.false(targets.allOfficialArchsForPlatformAndVersion('linux', '1.8.0').includes('mips64el'),
           'should not be found when version is < 1.8.2-beta.5')
 })
 
+test('allOfficialArchsForPlatformAndVersion returns win32/arm64 when the correct version is specified', t => {
+  t.true(targets.allOfficialArchsForPlatformAndVersion('win32', '6.0.8').includes('arm64'),
+         'should be found when version is >= 6.0.8')
+  t.false(targets.allOfficialArchsForPlatformAndVersion('win32', '5.0.0').includes('arm64'),
+          'should not be found when version is < 6.0.8')
+})
+
 test('validateListFromOptions does not take non-Array/String values', t => {
   targets.supported.digits = new Set(['64', '65'])
   t.false(targets.validateListFromOptions({ digits: 64 }, 'digits') instanceof Array,
@@ -70,11 +77,11 @@ test('validateListFromOptions works for armv7l host and target arch', t => {
 })
 
 test('build for all available official targets',
-     testMultiTarget({ all: true, electronVersion: '1.8.2' }, util.allPlatformArchCombosCount,
-                     'Packages should be generated for all possible platforms'))
+     testMultiTarget({ all: true, electronVersion: '1.8.2' }, util.allPlatformArchCombosCount - 1,
+                     'Packages should be generated for all possible platforms (except win32/arm64)'))
 test('build for all available official targets for a version without arm64 or mips64el support',
-     testMultiTarget({ all: true }, util.allPlatformArchCombosCount - 2,
-                     'Packages should be generated for all possible platforms (except arm64 and mips64el)'))
+     testMultiTarget({ all: true }, util.allPlatformArchCombosCount - 3,
+                     'Packages should be generated for all possible platforms (except linux/arm64, linux/mips64el, or win32/arm64)'))
 test('platform=all (one arch)',
      testMultiTarget({ arch: 'ia32', platform: 'all' }, 2, 'Packages should be generated for both 32-bit platforms'))
 test('arch=all test (one platform)',
@@ -94,11 +101,17 @@ test('fails with invalid platform', util.invalidOptionTest({
 }))
 
 test('invalid official combination', testMultiTarget({ arch: 'ia32', platform: 'darwin' }, 0, 'Package should not be generated for invalid official combination'))
-test('platform=linux and arch=arm64 with a supported official Electron version', testMultiTarget({ arch: 'arm64', platform: 'linux', electronVersion: '1.8.0' }, 1, 'Package should be generated for arm64'))
-test('platform=linux and arch=arm64 with an unsupported official Electron version', testMultiTarget({ arch: 'arm64', platform: 'linux' }, 0, 'Package should not be generated for arm64'))
+
+test('platform=linux and arch=arm64 with a supported official Electron version', testMultiTarget({ arch: 'arm64', platform: 'linux', electronVersion: '1.8.0' }, 1, 'Package should be generated for linux/arm64'))
+test('platform=linux and arch=arm64 with an unsupported official Electron version', testMultiTarget({ arch: 'arm64', platform: 'linux' }, 0, 'Package should not be generated for linux/arm64'))
+
 test('platform=linux and arch=mips64el with a supported official Electron version', testMultiTarget({ arch: 'mips64el', platform: 'linux', electronVersion: '1.8.2-beta.5' }, 1, 'Package should be generated for mips64el'))
-test('platform=linux and arch=mips64el with an unsupported official Electron version', testMultiTarget({ arch: 'mips64el', platform: 'linux' }, 0, 'Package should not be generated for mips64el'))
-test('platform=linux and arch=mips64el with an unsupported official Electron version (2.0.0)', testMultiTarget({ arch: 'mips64el', platform: 'linux', electronVersion: '2.0.0' }, 0, 'Package should not be generated for mips64el'))
+test('platform=linux and arch=mips64el with an unsupported official Electron version', testMultiTarget({ arch: 'mips64el', platform: 'linux' }, 0, 'Package should not be generated for linux/mips64el'))
+test('platform=linux and arch=mips64el with an unsupported official Electron version (2.0.0)', testMultiTarget({ arch: 'mips64el', platform: 'linux', electronVersion: '2.0.0' }, 0, 'Package should not be generated for linux/mips64el'))
+
+test('platform=win32 and arch=arm64 with a supported official Electron version', testMultiTarget({ arch: 'arm64', platform: 'win32', electronVersion: '6.0.8' }, 1, 'Package should be generated for win32/arm64'))
+test('platform=win32 and arch=arm64 with an unsupported official Electron version', testMultiTarget({ arch: 'arm64', platform: 'win32' }, 0, 'Package should not be generated for win32/arm64'))
+
 test('unofficial arch', testMultiTarget({ arch: 'z80', platform: 'linux', download: { mirrorOptions: { mirror: 'mirror' } } }, 1,
                                         'Package should be generated for non-standard arch from non-official mirror'))
 test('unofficial platform', testMultiTarget({ arch: 'ia32', platform: 'minix', download: { mirrorOptions: { mirror: 'mirror' } } }, 1,