From c791fabc0e905d5bda1ceafb9ead81394cd1622e Mon Sep 17 00:00:00 2001 From: Alok Yadav Date: Fri, 14 Mar 2025 23:36:19 +0530 Subject: [PATCH 01/14] feat: add ASAR packaging support and update tests --- package.json | 1 + src/fiddle.ts | 49 ++++++++++++++++++++++++++++++++++++-------- src/runner.ts | 5 ++++- tests/fiddle.test.ts | 39 +++++++++++++++++++++++++++++++++++ yarn.lock | 16 ++++++++++++++- 5 files changed, 100 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 27fb1b7..377a288 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "test:ci": "jest --runInBand --coverage" }, "dependencies": { + "@electron/asar": "^3.3.1", "@electron/get": "^2.0.0", "debug": "^4.3.3", "env-paths": "^2.2.1", diff --git a/src/fiddle.ts b/src/fiddle.ts index 17b8864..d222970 100644 --- a/src/fiddle.ts +++ b/src/fiddle.ts @@ -1,5 +1,6 @@ import * as fs from 'fs-extra'; import * as path from 'path'; +import * as asar from '@electron/asar'; import debug from 'debug'; import simpleGit from 'simple-git'; import { createHash } from 'crypto'; @@ -95,16 +96,48 @@ export class FiddleFactory { return new Fiddle(path.join(folder, 'main.js'), 'entries'); } - public async create(src: FiddleSource): Promise { - if (src instanceof Fiddle) return src; + public async create( + src: FiddleSource, + options?: { packAsAsar?: boolean }, + ): Promise { + let fiddle: Fiddle; + if (src instanceof Fiddle) { + fiddle = src; + } else if (typeof src === 'string') { + if (fs.existsSync(src)) { + fiddle = await this.fromFolder(src); + } else if (/^[0-9A-Fa-f]{32}$/.test(src)) { + fiddle = await this.fromGist(src); + } else if (/^https:/.test(src) || /\.git$/.test(src)) { + fiddle = await this.fromRepo(src); + } else { + return; + } + } else { + fiddle = await this.fromEntries(src as Iterable<[string, string]>); + } - if (typeof src === 'string') { - if (fs.existsSync(src)) return this.fromFolder(src); - if (/^[0-9A-Fa-f]{32}$/.test(src)) return this.fromGist(src); - if (/^https:/.test(src) || /\.git$/.test(src)) return this.fromRepo(src); - return; + const { packAsAsar } = options || {}; + if (packAsAsar) { + fiddle = await this.packageFiddleAsAsar(fiddle); } + return fiddle; + } + + private async packageFiddleAsAsar(fiddle: Fiddle): Promise { + const mainJsPath = fiddle.mainPath; + const sourceDir = path.dirname(mainJsPath); + const asarOutputDir = path.join(this.fiddles, hashString(sourceDir)); + const asarFilePath = path.join(asarOutputDir, 'app.asar'); - return this.fromEntries(src); + await asar.createPackage(sourceDir, asarFilePath); + fiddle = new Fiddle(asarFilePath, fiddle.source); + + try { + await fs.remove(sourceDir); + } catch (err) { + console.log('Error deleting unpacked folder:', err); + } + return fiddle; } } diff --git a/src/runner.ts b/src/runner.ts index f23ec19..eb96ee6 100644 --- a/src/runner.ts +++ b/src/runner.ts @@ -142,7 +142,10 @@ export class Runner { // process the input parameters opts = { ...DefaultRunnerOpts, ...opts }; const version = versionIn instanceof SemVer ? versionIn.version : versionIn; - const fiddle = await this.fiddleFactory.create(fiddleIn); + const isRunFromAsar = opts.args?.includes('runFromAsar'); + const fiddle = await this.fiddleFactory.create(fiddleIn, { + packAsAsar: isRunFromAsar, + }); if (!fiddle) throw new Error(`Invalid fiddle: "${inspect(fiddleIn)}"`); // set up the electron binary and the fiddle diff --git a/tests/fiddle.test.ts b/tests/fiddle.test.ts index a352ad7..bfd046a 100644 --- a/tests/fiddle.test.ts +++ b/tests/fiddle.test.ts @@ -1,6 +1,7 @@ import * as fs from 'fs-extra'; import * as os from 'os'; import * as path from 'path'; +import asar from '@electron/asar'; import { Fiddle, FiddleFactory } from '../src/index'; @@ -35,6 +36,9 @@ describe('FiddleFactory', () => { const dirname = path.dirname(fiddle!.mainPath); expect(dirname).not.toEqual(sourceDir); + // test that main.js file is created (not app.asar) + expect(path.basename(fiddle!.mainPath)).toBe('main.js'); + // test that the fiddle is kept in the fiddle cache expect(path.dirname(dirname)).toBe(fiddleDir); @@ -93,6 +97,41 @@ describe('FiddleFactory', () => { expect(fiddle).toBe(fiddleIn); }); + it('packages fiddle into ASAR archive', async () => { + const sourceDir = fiddleFixture('642fa8daaebea6044c9079e3f8a46390'); + const fiddle = await fiddleFactory.create(sourceDir, { + packAsAsar: true, + }); + + function normalizeAsarFiles(files: string[]): string[] { + return files.map( + (f) => f.replace(/^\//, ''), // Remove leading slash + ); + } + + // test that app.asar file is created + expect(fiddle).toBeTruthy(); + expect(path.basename(fiddle!.mainPath)).toBe('app.asar'); + + // test that the file list is identical + const dirname: string = fiddle!.mainPath; + const sourceFiles = fs.readdirSync(sourceDir); + const asarFiles = normalizeAsarFiles( + asar.listPackage(dirname, { isPack: false }), + ); + expect(asarFiles).toStrictEqual(sourceFiles); + + // test that the files' contents are identical + for (const file of sourceFiles) { + const sourceFileContent = fs.readFileSync( + path.join(sourceDir, file), + 'utf-8', + ); + const asarFileContent = asar.extractFile(dirname, file).toString(); + expect(asarFileContent).toStrictEqual(sourceFileContent); + } + }); + it.todo('reads fiddles from git repositories'); it.todo('refreshes the cache if given a previously-cached git repository'); diff --git a/yarn.lock b/yarn.lock index 098522e..b044274 100644 --- a/yarn.lock +++ b/yarn.lock @@ -575,6 +575,15 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== +"@electron/asar@^3.3.1": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@electron/asar/-/asar-3.3.1.tgz#cd14e897770d9844673dd7c1dc8944e086e1e0ea" + integrity sha512-WtpC/+34p0skWZiarRjLAyqaAX78DofhDxnREy/V5XHfu1XEXbFCSSMcDQ6hNCPJFaPy8/NnUgYuf9uiCkvKPg== + dependencies: + commander "^5.0.0" + glob "^7.1.6" + minimatch "^3.0.4" + "@electron/get@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@electron/get/-/get-2.0.0.tgz#d991e68dc089fc66b521ec3ca4021515482bef91" @@ -1733,6 +1742,11 @@ commander@^2.7.1: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== +commander@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" + integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== + compress-brotli@^1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/compress-brotli/-/compress-brotli-1.3.8.tgz#0c0a60c97a989145314ec381e84e26682e7b38db" @@ -2362,7 +2376,7 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" -glob@^7.1.3: +glob@^7.1.3, glob@^7.1.6: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== From daa21ba03d8722169ae273c07784653ee259548c Mon Sep 17 00:00:00 2001 From: Alok Yadav Date: Fri, 14 Mar 2025 23:36:19 +0530 Subject: [PATCH 02/14] feat: add ASAR packaging support and update tests --- package.json | 1 + src/fiddle.ts | 49 ++++++++++++++++++++++++++++++++++++-------- src/runner.ts | 5 ++++- tests/fiddle.test.ts | 39 +++++++++++++++++++++++++++++++++++ yarn.lock | 16 ++++++++++++++- 5 files changed, 100 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 27fb1b7..377a288 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "test:ci": "jest --runInBand --coverage" }, "dependencies": { + "@electron/asar": "^3.3.1", "@electron/get": "^2.0.0", "debug": "^4.3.3", "env-paths": "^2.2.1", diff --git a/src/fiddle.ts b/src/fiddle.ts index 17b8864..d222970 100644 --- a/src/fiddle.ts +++ b/src/fiddle.ts @@ -1,5 +1,6 @@ import * as fs from 'fs-extra'; import * as path from 'path'; +import * as asar from '@electron/asar'; import debug from 'debug'; import simpleGit from 'simple-git'; import { createHash } from 'crypto'; @@ -95,16 +96,48 @@ export class FiddleFactory { return new Fiddle(path.join(folder, 'main.js'), 'entries'); } - public async create(src: FiddleSource): Promise { - if (src instanceof Fiddle) return src; + public async create( + src: FiddleSource, + options?: { packAsAsar?: boolean }, + ): Promise { + let fiddle: Fiddle; + if (src instanceof Fiddle) { + fiddle = src; + } else if (typeof src === 'string') { + if (fs.existsSync(src)) { + fiddle = await this.fromFolder(src); + } else if (/^[0-9A-Fa-f]{32}$/.test(src)) { + fiddle = await this.fromGist(src); + } else if (/^https:/.test(src) || /\.git$/.test(src)) { + fiddle = await this.fromRepo(src); + } else { + return; + } + } else { + fiddle = await this.fromEntries(src as Iterable<[string, string]>); + } - if (typeof src === 'string') { - if (fs.existsSync(src)) return this.fromFolder(src); - if (/^[0-9A-Fa-f]{32}$/.test(src)) return this.fromGist(src); - if (/^https:/.test(src) || /\.git$/.test(src)) return this.fromRepo(src); - return; + const { packAsAsar } = options || {}; + if (packAsAsar) { + fiddle = await this.packageFiddleAsAsar(fiddle); } + return fiddle; + } + + private async packageFiddleAsAsar(fiddle: Fiddle): Promise { + const mainJsPath = fiddle.mainPath; + const sourceDir = path.dirname(mainJsPath); + const asarOutputDir = path.join(this.fiddles, hashString(sourceDir)); + const asarFilePath = path.join(asarOutputDir, 'app.asar'); - return this.fromEntries(src); + await asar.createPackage(sourceDir, asarFilePath); + fiddle = new Fiddle(asarFilePath, fiddle.source); + + try { + await fs.remove(sourceDir); + } catch (err) { + console.log('Error deleting unpacked folder:', err); + } + return fiddle; } } diff --git a/src/runner.ts b/src/runner.ts index f23ec19..eb96ee6 100644 --- a/src/runner.ts +++ b/src/runner.ts @@ -142,7 +142,10 @@ export class Runner { // process the input parameters opts = { ...DefaultRunnerOpts, ...opts }; const version = versionIn instanceof SemVer ? versionIn.version : versionIn; - const fiddle = await this.fiddleFactory.create(fiddleIn); + const isRunFromAsar = opts.args?.includes('runFromAsar'); + const fiddle = await this.fiddleFactory.create(fiddleIn, { + packAsAsar: isRunFromAsar, + }); if (!fiddle) throw new Error(`Invalid fiddle: "${inspect(fiddleIn)}"`); // set up the electron binary and the fiddle diff --git a/tests/fiddle.test.ts b/tests/fiddle.test.ts index a352ad7..bfd046a 100644 --- a/tests/fiddle.test.ts +++ b/tests/fiddle.test.ts @@ -1,6 +1,7 @@ import * as fs from 'fs-extra'; import * as os from 'os'; import * as path from 'path'; +import asar from '@electron/asar'; import { Fiddle, FiddleFactory } from '../src/index'; @@ -35,6 +36,9 @@ describe('FiddleFactory', () => { const dirname = path.dirname(fiddle!.mainPath); expect(dirname).not.toEqual(sourceDir); + // test that main.js file is created (not app.asar) + expect(path.basename(fiddle!.mainPath)).toBe('main.js'); + // test that the fiddle is kept in the fiddle cache expect(path.dirname(dirname)).toBe(fiddleDir); @@ -93,6 +97,41 @@ describe('FiddleFactory', () => { expect(fiddle).toBe(fiddleIn); }); + it('packages fiddle into ASAR archive', async () => { + const sourceDir = fiddleFixture('642fa8daaebea6044c9079e3f8a46390'); + const fiddle = await fiddleFactory.create(sourceDir, { + packAsAsar: true, + }); + + function normalizeAsarFiles(files: string[]): string[] { + return files.map( + (f) => f.replace(/^\//, ''), // Remove leading slash + ); + } + + // test that app.asar file is created + expect(fiddle).toBeTruthy(); + expect(path.basename(fiddle!.mainPath)).toBe('app.asar'); + + // test that the file list is identical + const dirname: string = fiddle!.mainPath; + const sourceFiles = fs.readdirSync(sourceDir); + const asarFiles = normalizeAsarFiles( + asar.listPackage(dirname, { isPack: false }), + ); + expect(asarFiles).toStrictEqual(sourceFiles); + + // test that the files' contents are identical + for (const file of sourceFiles) { + const sourceFileContent = fs.readFileSync( + path.join(sourceDir, file), + 'utf-8', + ); + const asarFileContent = asar.extractFile(dirname, file).toString(); + expect(asarFileContent).toStrictEqual(sourceFileContent); + } + }); + it.todo('reads fiddles from git repositories'); it.todo('refreshes the cache if given a previously-cached git repository'); diff --git a/yarn.lock b/yarn.lock index 098522e..b044274 100644 --- a/yarn.lock +++ b/yarn.lock @@ -575,6 +575,15 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== +"@electron/asar@^3.3.1": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@electron/asar/-/asar-3.3.1.tgz#cd14e897770d9844673dd7c1dc8944e086e1e0ea" + integrity sha512-WtpC/+34p0skWZiarRjLAyqaAX78DofhDxnREy/V5XHfu1XEXbFCSSMcDQ6hNCPJFaPy8/NnUgYuf9uiCkvKPg== + dependencies: + commander "^5.0.0" + glob "^7.1.6" + minimatch "^3.0.4" + "@electron/get@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@electron/get/-/get-2.0.0.tgz#d991e68dc089fc66b521ec3ca4021515482bef91" @@ -1733,6 +1742,11 @@ commander@^2.7.1: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== +commander@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" + integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== + compress-brotli@^1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/compress-brotli/-/compress-brotli-1.3.8.tgz#0c0a60c97a989145314ec381e84e26682e7b38db" @@ -2362,7 +2376,7 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" -glob@^7.1.3: +glob@^7.1.3, glob@^7.1.6: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== From 36412276bffc1c5e877a3ef28bd0ca5235150fe6 Mon Sep 17 00:00:00 2001 From: Erick Zhao Date: Mon, 31 Mar 2025 12:37:40 -0700 Subject: [PATCH 03/14] temporarily disable LF --- .gitattributes | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.gitattributes b/.gitattributes index 2eec074..dbec287 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,6 +1,6 @@ # Source code and markdown files should always use LF as line ending. -*.js text eol=lf -*.json text eol=lf -*.md text eol=lf -*.ts text eol=lf -*.yml text eol=lf +# *.js text eol=lf +# *.json text eol=lf +# *.md text eol=lf +# *.ts text eol=lf +# *.yml text eol=lf From aaf3e88a552268e5665b11ac6beb3cbe363c5372 Mon Sep 17 00:00:00 2001 From: Erick Zhao Date: Mon, 31 Mar 2025 12:38:56 -0700 Subject: [PATCH 04/14] Revert "temporarily disable LF" This reverts commit 36412276bffc1c5e877a3ef28bd0ca5235150fe6. --- .gitattributes | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.gitattributes b/.gitattributes index dbec287..2eec074 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,6 +1,6 @@ # Source code and markdown files should always use LF as line ending. -# *.js text eol=lf -# *.json text eol=lf -# *.md text eol=lf -# *.ts text eol=lf -# *.yml text eol=lf +*.js text eol=lf +*.json text eol=lf +*.md text eol=lf +*.ts text eol=lf +*.yml text eol=lf From 36d10a895c83d1d6164f268e08da7a18f6a81028 Mon Sep 17 00:00:00 2001 From: Erick Zhao Date: Mon, 31 Mar 2025 12:39:20 -0700 Subject: [PATCH 05/14] revert yarn.lock --- yarn.lock | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/yarn.lock b/yarn.lock index b044274..098522e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -575,15 +575,6 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@electron/asar@^3.3.1": - version "3.3.1" - resolved "https://registry.yarnpkg.com/@electron/asar/-/asar-3.3.1.tgz#cd14e897770d9844673dd7c1dc8944e086e1e0ea" - integrity sha512-WtpC/+34p0skWZiarRjLAyqaAX78DofhDxnREy/V5XHfu1XEXbFCSSMcDQ6hNCPJFaPy8/NnUgYuf9uiCkvKPg== - dependencies: - commander "^5.0.0" - glob "^7.1.6" - minimatch "^3.0.4" - "@electron/get@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@electron/get/-/get-2.0.0.tgz#d991e68dc089fc66b521ec3ca4021515482bef91" @@ -1742,11 +1733,6 @@ commander@^2.7.1: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== -commander@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" - integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== - compress-brotli@^1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/compress-brotli/-/compress-brotli-1.3.8.tgz#0c0a60c97a989145314ec381e84e26682e7b38db" @@ -2376,7 +2362,7 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" -glob@^7.1.3, glob@^7.1.6: +glob@^7.1.3: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== From b23e17c584a331da7aa6fe4e1b263673e8db2659 Mon Sep 17 00:00:00 2001 From: Erick Zhao Date: Mon, 31 Mar 2025 12:40:19 -0700 Subject: [PATCH 06/14] fixup: temporarily disable LF --- .gitattributes | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.gitattributes b/.gitattributes index 2eec074..dbec287 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,6 +1,6 @@ # Source code and markdown files should always use LF as line ending. -*.js text eol=lf -*.json text eol=lf -*.md text eol=lf -*.ts text eol=lf -*.yml text eol=lf +# *.js text eol=lf +# *.json text eol=lf +# *.md text eol=lf +# *.ts text eol=lf +# *.yml text eol=lf From 63eee2b7171b90a843158d5140290e4cc0f16df8 Mon Sep 17 00:00:00 2001 From: Erick Zhao Date: Mon, 31 Mar 2025 12:40:39 -0700 Subject: [PATCH 07/14] Revert "fixup: temporarily disable LF" This reverts commit b23e17c584a331da7aa6fe4e1b263673e8db2659. --- .gitattributes | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.gitattributes b/.gitattributes index dbec287..2eec074 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,6 +1,6 @@ # Source code and markdown files should always use LF as line ending. -# *.js text eol=lf -# *.json text eol=lf -# *.md text eol=lf -# *.ts text eol=lf -# *.yml text eol=lf +*.js text eol=lf +*.json text eol=lf +*.md text eol=lf +*.ts text eol=lf +*.yml text eol=lf From b9f02d56434446fba788e8a80ff969afa6f75577 Mon Sep 17 00:00:00 2001 From: Erick Zhao Date: Mon, 31 Mar 2025 12:40:53 -0700 Subject: [PATCH 08/14] chore: reset yarn.lock --- yarn.lock | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/yarn.lock b/yarn.lock index b044274..098522e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -575,15 +575,6 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@electron/asar@^3.3.1": - version "3.3.1" - resolved "https://registry.yarnpkg.com/@electron/asar/-/asar-3.3.1.tgz#cd14e897770d9844673dd7c1dc8944e086e1e0ea" - integrity sha512-WtpC/+34p0skWZiarRjLAyqaAX78DofhDxnREy/V5XHfu1XEXbFCSSMcDQ6hNCPJFaPy8/NnUgYuf9uiCkvKPg== - dependencies: - commander "^5.0.0" - glob "^7.1.6" - minimatch "^3.0.4" - "@electron/get@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@electron/get/-/get-2.0.0.tgz#d991e68dc089fc66b521ec3ca4021515482bef91" @@ -1742,11 +1733,6 @@ commander@^2.7.1: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== -commander@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" - integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== - compress-brotli@^1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/compress-brotli/-/compress-brotli-1.3.8.tgz#0c0a60c97a989145314ec381e84e26682e7b38db" @@ -2376,7 +2362,7 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" -glob@^7.1.3, glob@^7.1.6: +glob@^7.1.3: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== From c949c47e89e8aedf517d19f332f938815694be27 Mon Sep 17 00:00:00 2001 From: Erick Zhao Date: Mon, 31 Mar 2025 12:41:04 -0700 Subject: [PATCH 09/14] re-commit yarn.lock --- yarn.lock | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/yarn.lock b/yarn.lock index 098522e..b044274 100644 --- a/yarn.lock +++ b/yarn.lock @@ -575,6 +575,15 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== +"@electron/asar@^3.3.1": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@electron/asar/-/asar-3.3.1.tgz#cd14e897770d9844673dd7c1dc8944e086e1e0ea" + integrity sha512-WtpC/+34p0skWZiarRjLAyqaAX78DofhDxnREy/V5XHfu1XEXbFCSSMcDQ6hNCPJFaPy8/NnUgYuf9uiCkvKPg== + dependencies: + commander "^5.0.0" + glob "^7.1.6" + minimatch "^3.0.4" + "@electron/get@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@electron/get/-/get-2.0.0.tgz#d991e68dc089fc66b521ec3ca4021515482bef91" @@ -1733,6 +1742,11 @@ commander@^2.7.1: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== +commander@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" + integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== + compress-brotli@^1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/compress-brotli/-/compress-brotli-1.3.8.tgz#0c0a60c97a989145314ec381e84e26682e7b38db" @@ -2362,7 +2376,7 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" -glob@^7.1.3: +glob@^7.1.3, glob@^7.1.6: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== From 9cd9193bf0ee3c2c2dd2df86a443d58c20e6a4ea Mon Sep 17 00:00:00 2001 From: Alok Yadav Date: Tue, 1 Apr 2025 02:47:35 +0530 Subject: [PATCH 10/14] fix: ensure cross-platform path normalization --- tests/fiddle.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fiddle.test.ts b/tests/fiddle.test.ts index bfd046a..5f4a259 100644 --- a/tests/fiddle.test.ts +++ b/tests/fiddle.test.ts @@ -105,7 +105,7 @@ describe('FiddleFactory', () => { function normalizeAsarFiles(files: string[]): string[] { return files.map( - (f) => f.replace(/^\//, ''), // Remove leading slash + (f) => f.replace(/^[\\/]/, ''), // Remove leading slash or backslash ); } From 41ff1bf852bf374479b0dad23b89aea7437bdb8c Mon Sep 17 00:00:00 2001 From: Erick Zhao Date: Mon, 31 Mar 2025 15:35:03 -0700 Subject: [PATCH 11/14] update docs --- etc/fiddle-core.api.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/etc/fiddle-core.api.md b/etc/fiddle-core.api.md index 061d0bb..5666b05 100644 --- a/etc/fiddle-core.api.md +++ b/etc/fiddle-core.api.md @@ -111,7 +111,9 @@ export class Fiddle { export class FiddleFactory { constructor(fiddles?: string); // (undocumented) - create(src: FiddleSource): Promise; + create(src: FiddleSource, options?: { + packAsAsar?: boolean; + }): Promise; // (undocumented) fromEntries(src: Iterable<[string, string]>): Promise; // (undocumented) From 274113d4f0c1bc97550b65829a1d99b1d5e1a8d7 Mon Sep 17 00:00:00 2001 From: Alok Yadav Date: Tue, 1 Apr 2025 04:56:48 +0530 Subject: [PATCH 12/14] refactor: address review comments --- src/fiddle.ts | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/fiddle.ts b/src/fiddle.ts index d222970..32d620b 100644 --- a/src/fiddle.ts +++ b/src/fiddle.ts @@ -125,19 +125,14 @@ export class FiddleFactory { } private async packageFiddleAsAsar(fiddle: Fiddle): Promise { - const mainJsPath = fiddle.mainPath; - const sourceDir = path.dirname(mainJsPath); + const sourceDir = path.dirname(fiddle.mainPath); const asarOutputDir = path.join(this.fiddles, hashString(sourceDir)); const asarFilePath = path.join(asarOutputDir, 'app.asar'); await asar.createPackage(sourceDir, asarFilePath); - fiddle = new Fiddle(asarFilePath, fiddle.source); + const packagedFiddle = new Fiddle(asarFilePath, fiddle.source); - try { - await fs.remove(sourceDir); - } catch (err) { - console.log('Error deleting unpacked folder:', err); - } - return fiddle; + await fs.remove(sourceDir); + return packagedFiddle; } } From 7807b5e55250d93ec6f8a032ed02a060fe72562a Mon Sep 17 00:00:00 2001 From: Alok Yadav Date: Fri, 4 Apr 2025 16:13:52 +0530 Subject: [PATCH 13/14] refactor: address review feedback --- src/fiddle.ts | 6 +++++- src/index.ts | 3 ++- src/runner.ts | 5 +++-- tests/runner.test.ts | 42 ++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 50 insertions(+), 6 deletions(-) diff --git a/src/fiddle.ts b/src/fiddle.ts index 32d620b..efb7d1d 100644 --- a/src/fiddle.ts +++ b/src/fiddle.ts @@ -32,6 +32,10 @@ export class Fiddle { */ export type FiddleSource = Fiddle | string | Iterable<[string, string]>; +export interface CreateOptions { + packAsAsar?: boolean; +} + export class FiddleFactory { constructor(private readonly fiddles: string = DefaultPaths.fiddles) {} @@ -98,7 +102,7 @@ export class FiddleFactory { public async create( src: FiddleSource, - options?: { packAsAsar?: boolean }, + options?: CreateOptions, ): Promise { let fiddle: Fiddle; if (src instanceof Fiddle) { diff --git a/src/index.ts b/src/index.ts index ed47d46..b6d6d0a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -10,7 +10,7 @@ import { Mirrors, ProgressObject, } from './installer'; -import { Fiddle, FiddleFactory, FiddleSource } from './fiddle'; +import { CreateOptions, Fiddle, FiddleFactory, FiddleSource } from './fiddle'; import { BisectResult, Runner, @@ -33,6 +33,7 @@ import { runFromCommandLine } from './command-line'; export { BaseVersions, BisectResult, + CreateOptions, DefaultPaths, ElectronBinary, ElectronVersions, diff --git a/src/runner.ts b/src/runner.ts index eb96ee6..2c593c1 100644 --- a/src/runner.ts +++ b/src/runner.ts @@ -22,6 +22,8 @@ export interface RunnerOptions { out?: Writable; // whether to show config info (e.g. platform os & arch) in the log showConfig?: boolean; + // whether to run the fiddle from asar + runFromAsar?: boolean; } const DefaultRunnerOpts: RunnerOptions = { @@ -142,9 +144,8 @@ export class Runner { // process the input parameters opts = { ...DefaultRunnerOpts, ...opts }; const version = versionIn instanceof SemVer ? versionIn.version : versionIn; - const isRunFromAsar = opts.args?.includes('runFromAsar'); const fiddle = await this.fiddleFactory.create(fiddleIn, { - packAsAsar: isRunFromAsar, + packAsAsar: opts.runFromAsar, }); if (!fiddle) throw new Error(`Invalid fiddle: "${inspect(fiddleIn)}"`); diff --git a/tests/runner.test.ts b/tests/runner.test.ts index 334d41e..8aeb8dc 100644 --- a/tests/runner.test.ts +++ b/tests/runner.test.ts @@ -1,4 +1,10 @@ -import { Installer, FiddleFactory, Runner, TestResult } from '../src/index'; +import { + Installer, + FiddleFactory, + Runner, + TestResult, + CreateOptions, +} from '../src/index'; import child_process from 'child_process'; import { EventEmitter } from 'events'; import * as fs from 'fs-extra'; @@ -58,7 +64,14 @@ async function createFakeRunner({ install: jest.fn().mockResolvedValue(pathToExecutable), } as Pick as Installer, fiddleFactory: { - create: jest.fn().mockResolvedValue(generatedFiddle), + create: jest.fn().mockImplementation((_, options?: CreateOptions) => { + if (options?.packAsAsar) + return Promise.resolve({ + ...generatedFiddle, + mainPath: '/path/to/fiddle/app.asar', + }); + return Promise.resolve(generatedFiddle); + }), } as Pick as FiddleFactory, paths: { versionsCache, @@ -181,6 +194,31 @@ describe('Runner', () => { new Error(`Invalid fiddle: "'invalid-fiddle'"`), ); }); + + it('spawns a subprocess with ASAR path when runFromAsar is true', async () => { + const runner = await createFakeRunner({}); + (child_process.spawn as jest.Mock).mockReturnValueOnce(mockSubprocess); + + await runner.spawn('12.0.1', '642fa8daaebea6044c9079e3f8a46390', { + out: { + write: mockStdout, + } as Pick as Writable, + runFromAsar: true, + }); + + expect(child_process.spawn).toHaveBeenCalledTimes(1); + expect(child_process.spawn).toHaveBeenCalledWith( + '/path/to/electron/executable', + ['/path/to/fiddle/app.asar'], + { + args: [], + headless: false, + out: expect.any(Object) as Writable, + showConfig: true, + runFromAsar: true, + }, + ); + }); }); describe('run()', () => { From bdc98bcbe12b770dfce8495d94a0d45c126e8c55 Mon Sep 17 00:00:00 2001 From: Alok Yadav Date: Mon, 7 Apr 2025 08:56:48 +0530 Subject: [PATCH 14/14] refactor: address review feedback --- etc/fiddle-core.api.md | 12 +++++++++--- src/fiddle.ts | 4 ++-- src/index.ts | 9 +++++++-- tests/runner.test.ts | 28 ++++++++++++---------------- 4 files changed, 30 insertions(+), 23 deletions(-) diff --git a/etc/fiddle-core.api.md b/etc/fiddle-core.api.md index 5666b05..d288fb0 100644 --- a/etc/fiddle-core.api.md +++ b/etc/fiddle-core.api.md @@ -111,9 +111,7 @@ export class Fiddle { export class FiddleFactory { constructor(fiddles?: string); // (undocumented) - create(src: FiddleSource, options?: { - packAsAsar?: boolean; - }): Promise; + create(src: FiddleSource, options?: FiddleFactoryCreateOptions): Promise; // (undocumented) fromEntries(src: Iterable<[string, string]>): Promise; // (undocumented) @@ -124,6 +122,12 @@ export class FiddleFactory { fromRepo(url: string, checkout?: string): Promise; } +// @public (undocumented) +export interface FiddleFactoryCreateOptions { + // (undocumented) + packAsAsar?: boolean; +} + // @public export type FiddleSource = Fiddle | string | Iterable<[string, string]>; @@ -244,6 +248,8 @@ export interface RunnerOptions { // (undocumented) out?: Writable; // (undocumented) + runFromAsar?: boolean; + // (undocumented) showConfig?: boolean; } diff --git a/src/fiddle.ts b/src/fiddle.ts index efb7d1d..214b1db 100644 --- a/src/fiddle.ts +++ b/src/fiddle.ts @@ -32,7 +32,7 @@ export class Fiddle { */ export type FiddleSource = Fiddle | string | Iterable<[string, string]>; -export interface CreateOptions { +export interface FiddleFactoryCreateOptions { packAsAsar?: boolean; } @@ -102,7 +102,7 @@ export class FiddleFactory { public async create( src: FiddleSource, - options?: CreateOptions, + options?: FiddleFactoryCreateOptions, ): Promise { let fiddle: Fiddle; if (src instanceof Fiddle) { diff --git a/src/index.ts b/src/index.ts index b6d6d0a..dc3105d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -10,7 +10,12 @@ import { Mirrors, ProgressObject, } from './installer'; -import { CreateOptions, Fiddle, FiddleFactory, FiddleSource } from './fiddle'; +import { + Fiddle, + FiddleFactory, + FiddleSource, + FiddleFactoryCreateOptions, +} from './fiddle'; import { BisectResult, Runner, @@ -33,13 +38,13 @@ import { runFromCommandLine } from './command-line'; export { BaseVersions, BisectResult, - CreateOptions, DefaultPaths, ElectronBinary, ElectronVersions, ElectronVersionsCreateOptions, Fiddle, FiddleFactory, + FiddleFactoryCreateOptions, FiddleSource, InstallState, InstallStateEvent, diff --git a/tests/runner.test.ts b/tests/runner.test.ts index 8aeb8dc..77f86c9 100644 --- a/tests/runner.test.ts +++ b/tests/runner.test.ts @@ -3,7 +3,7 @@ import { FiddleFactory, Runner, TestResult, - CreateOptions, + FiddleFactoryCreateOptions, } from '../src/index'; import child_process from 'child_process'; import { EventEmitter } from 'events'; @@ -64,14 +64,16 @@ async function createFakeRunner({ install: jest.fn().mockResolvedValue(pathToExecutable), } as Pick as Installer, fiddleFactory: { - create: jest.fn().mockImplementation((_, options?: CreateOptions) => { - if (options?.packAsAsar) - return Promise.resolve({ - ...generatedFiddle, - mainPath: '/path/to/fiddle/app.asar', - }); - return Promise.resolve(generatedFiddle); - }), + create: jest + .fn() + .mockImplementation((_, options?: FiddleFactoryCreateOptions) => { + if (options?.packAsAsar) + return Promise.resolve({ + ...generatedFiddle, + mainPath: '/path/to/fiddle/app.asar', + }); + return Promise.resolve(generatedFiddle); + }), } as Pick as FiddleFactory, paths: { versionsCache, @@ -210,13 +212,7 @@ describe('Runner', () => { expect(child_process.spawn).toHaveBeenCalledWith( '/path/to/electron/executable', ['/path/to/fiddle/app.asar'], - { - args: [], - headless: false, - out: expect.any(Object) as Writable, - showConfig: true, - runFromAsar: true, - }, + expect.anything(), ); }); });