@@ -4,6 +4,9 @@ const common = require('../common');
44const fixtures = require ( '../common/fixtures' ) ;
55const tmpdir = require ( '../common/tmpdir' ) ;
66const { inspect } = require ( 'util' ) ;
7+ const fs = require ( 'fs' ) ;
8+ const path = require ( 'path' ) ;
9+ const assert = require ( 'assert' ) ;
710
811const { readFileSync, copyFileSync, statSync } = require ( 'fs' ) ;
912const {
@@ -70,37 +73,71 @@ function skipIfSingleExecutableIsNotSupported() {
7073 }
7174}
7275
73- function generateSEA ( targetExecutable , sourceExecutable , seaBlob , verifyWorkflow = false ) {
76+ function generateSEA ( fixtureDir , workingDir = tmpdir . path , configPath = 'sea-config.json' , verifyWorkflow = false ) {
77+ // Copy fixture files to working directory if they are different.
78+ if ( fixtureDir !== workingDir ) {
79+ fs . cpSync ( fixtureDir , workingDir , { recursive : true } ) ;
80+ }
81+
82+ // Determine the output executable path.
83+ const outputFile = path . resolve ( workingDir , process . platform === 'win32' ? 'sea.exe' : 'sea' ) ;
84+
7485 try {
75- copyFileSync ( sourceExecutable , targetExecutable ) ;
86+ // Copy the executable.
87+ copyFileSync ( process . execPath , outputFile ) ;
88+ console . log ( `Copied ${ process . execPath } to ${ outputFile } ` ) ;
7689 } catch ( e ) {
77- const message = `Cannot copy ${ sourceExecutable } to ${ targetExecutable } : ${ inspect ( e ) } ` ;
90+ const message = `Cannot copy ${ process . execPath } to ${ outputFile } : ${ inspect ( e ) } ` ;
7891 if ( verifyWorkflow ) {
7992 throw new Error ( message ) ;
8093 }
8194 common . skip ( message ) ;
8295 }
83- console . log ( `Copied ${ sourceExecutable } to ${ targetExecutable } ` ) ;
8496
97+ // Generate the blob using --experimental-sea-config.
98+ spawnSyncAndExitWithoutError (
99+ process . execPath ,
100+ [ '--experimental-sea-config' , configPath ] ,
101+ {
102+ cwd : workingDir ,
103+ env : {
104+ NODE_DEBUG_NATIVE : 'SEA' ,
105+ ...process . env ,
106+ } ,
107+ } ,
108+ ) ;
109+
110+ // Parse the config to get the output file path.
111+ const config = JSON . parse ( fs . readFileSync ( path . resolve ( workingDir , configPath ) ) ) ;
112+ assert . strictEqual ( typeof config . output , 'string' ) ;
113+ const seaPrepBlob = path . resolve ( workingDir , config . output ) ;
114+ assert ( fs . existsSync ( seaPrepBlob ) , `Expected SEA blob ${ seaPrepBlob } to exist` ) ;
115+
116+ // Use postject to inject the blob.
85117 const postjectFile = fixtures . path ( 'postject-copy' , 'node_modules' , 'postject' , 'dist' , 'cli.js' ) ;
86118 try {
87119 spawnSyncAndExitWithoutError ( process . execPath , [
88120 postjectFile ,
89- targetExecutable ,
121+ outputFile ,
90122 'NODE_SEA_BLOB' ,
91- seaBlob ,
123+ seaPrepBlob ,
92124 '--sentinel-fuse' , 'NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2' ,
93125 ...process . platform === 'darwin' ? [ '--macho-segment-name' , 'NODE_SEA' ] : [ ] ,
94126 ] ) ;
95127 } catch ( e ) {
96- const message = `Cannot inject ${ seaBlob } into ${ targetExecutable } : ${ inspect ( e ) } ` ;
128+ const message = `Cannot inject ${ seaPrepBlob } into ${ outputFile } : ${ inspect ( e ) } ` ;
97129 if ( verifyWorkflow ) {
98130 throw new Error ( message ) ;
99131 }
100132 common . skip ( message ) ;
101133 }
102- console . log ( `Injected ${ seaBlob } into ${ targetExecutable } ` ) ;
134+ console . log ( `Injected ${ seaPrepBlob } into ${ outputFile } ` ) ;
135+
136+ signSEA ( outputFile , verifyWorkflow ) ;
137+ return outputFile ;
138+ }
103139
140+ function signSEA ( targetExecutable , verifyWorkflow = false ) {
104141 if ( process . platform === 'darwin' ) {
105142 try {
106143 spawnSyncAndExitWithoutError ( 'codesign' , [ '--sign' , '-' , targetExecutable ] ) ;
0 commit comments