@@ -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,76 @@ function skipIfSingleExecutableIsNotSupported() {
7073 }
7174}
7275
73- function generateSEA ( targetExecutable , sourceExecutable , seaBlob , verifyWorkflow = false ) {
76+ function generateSEA ( fixtureDir , options = { } ) {
77+ const {
78+ workingDir = tmpdir . path ,
79+ configPath = 'sea-config.json' ,
80+ verifyWorkflow = false ,
81+ } = options ;
82+ // Copy fixture files to working directory if they are different.
83+ if ( fixtureDir !== workingDir ) {
84+ fs . cpSync ( fixtureDir , workingDir , { recursive : true } ) ;
85+ }
86+
87+ // Determine the output executable path.
88+ const outputFile = path . resolve ( workingDir , process . platform === 'win32' ? 'sea.exe' : 'sea' ) ;
89+
7490 try {
75- copyFileSync ( sourceExecutable , targetExecutable ) ;
91+ // Copy the executable.
92+ copyFileSync ( process . execPath , outputFile ) ;
93+ console . log ( `Copied ${ process . execPath } to ${ outputFile } ` ) ;
7694 } catch ( e ) {
77- const message = `Cannot copy ${ sourceExecutable } to ${ targetExecutable } : ${ inspect ( e ) } ` ;
95+ const message = `Cannot copy ${ process . execPath } to ${ outputFile } : ${ inspect ( e ) } ` ;
7896 if ( verifyWorkflow ) {
7997 throw new Error ( message ) ;
8098 }
8199 common . skip ( message ) ;
82100 }
83- console . log ( `Copied ${ sourceExecutable } to ${ targetExecutable } ` ) ;
84101
102+ // Generate the blob using --experimental-sea-config.
103+ spawnSyncAndExitWithoutError (
104+ process . execPath ,
105+ [ '--experimental-sea-config' , configPath ] ,
106+ {
107+ cwd : workingDir ,
108+ env : {
109+ NODE_DEBUG_NATIVE : 'SEA' ,
110+ ...process . env ,
111+ } ,
112+ } ,
113+ ) ;
114+
115+ // Parse the config to get the output file path.
116+ const config = JSON . parse ( fs . readFileSync ( path . resolve ( workingDir , configPath ) ) ) ;
117+ assert . strictEqual ( typeof config . output , 'string' ) ;
118+ const seaPrepBlob = path . resolve ( workingDir , config . output ) ;
119+ assert ( fs . existsSync ( seaPrepBlob ) , `Expected SEA blob ${ seaPrepBlob } to exist` ) ;
120+
121+ // Use postject to inject the blob.
85122 const postjectFile = fixtures . path ( 'postject-copy' , 'node_modules' , 'postject' , 'dist' , 'cli.js' ) ;
86123 try {
87124 spawnSyncAndExitWithoutError ( process . execPath , [
88125 postjectFile ,
89- targetExecutable ,
126+ outputFile ,
90127 'NODE_SEA_BLOB' ,
91- seaBlob ,
128+ seaPrepBlob ,
92129 '--sentinel-fuse' , 'NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2' ,
93130 ...process . platform === 'darwin' ? [ '--macho-segment-name' , 'NODE_SEA' ] : [ ] ,
94131 ] ) ;
95132 } catch ( e ) {
96- const message = `Cannot inject ${ seaBlob } into ${ targetExecutable } : ${ inspect ( e ) } ` ;
133+ const message = `Cannot inject ${ seaPrepBlob } into ${ outputFile } : ${ inspect ( e ) } ` ;
97134 if ( verifyWorkflow ) {
98135 throw new Error ( message ) ;
99136 }
100137 common . skip ( message ) ;
101138 }
102- console . log ( `Injected ${ seaBlob } into ${ targetExecutable } ` ) ;
139+ console . log ( `Injected ${ seaPrepBlob } into ${ outputFile } ` ) ;
140+
141+ signSEA ( outputFile , verifyWorkflow ) ;
142+ return outputFile ;
143+ }
103144
145+ function signSEA ( targetExecutable , verifyWorkflow = false ) {
104146 if ( process . platform === 'darwin' ) {
105147 try {
106148 spawnSyncAndExitWithoutError ( 'codesign' , [ '--sign' , '-' , targetExecutable ] ) ;
0 commit comments