@@ -158,6 +158,49 @@ function createMountpoint(interior, exterior) {
158
158
mountpoints . push ( { interior, exterior } ) ;
159
159
}
160
160
161
+ function copyFileSync ( source , target ) {
162
+ let targetFile = target ;
163
+
164
+ // If target is a directory, a new file with the same name will be created
165
+ if ( fs . existsSync ( target ) ) {
166
+ if ( fs . lstatSync ( target ) . isDirectory ( ) ) {
167
+ targetFile = path . join ( target , path . basename ( source ) ) ;
168
+ }
169
+ }
170
+
171
+ fs . writeFileSync ( targetFile , fs . readFileSync ( source ) ) ;
172
+ }
173
+
174
+ function copyFolderRecursiveSync ( source , target ) {
175
+ let files = [ ] ;
176
+
177
+ // Check if folder needs to be created or integrated
178
+ const targetFolder = path . join ( target , path . basename ( source ) ) ;
179
+ if ( ! fs . existsSync ( targetFolder ) ) {
180
+ fs . mkdirSync ( targetFolder ) ;
181
+ }
182
+
183
+ // Copy
184
+ if ( fs . lstatSync ( source ) . isDirectory ( ) ) {
185
+ files = fs . readdirSync ( source ) ;
186
+ files . forEach ( ( file ) => {
187
+ const curSource = path . join ( source , file ) ;
188
+ if ( fs . lstatSync ( curSource ) . isDirectory ( ) ) {
189
+ copyFolderRecursiveSync ( curSource , targetFolder ) ;
190
+ } else {
191
+ copyFileSync ( curSource , targetFolder ) ;
192
+ }
193
+ } ) ;
194
+ }
195
+ }
196
+
197
+ function createDirRecursively ( dir ) {
198
+ if ( ! fs . existsSync ( dir ) ) {
199
+ createDirRecursively ( path . join ( dir , '..' ) ) ;
200
+ fs . mkdirSync ( dir ) ;
201
+ }
202
+ }
203
+
161
204
/*
162
205
163
206
// TODO move to some test
@@ -2020,88 +2063,41 @@ function payloadFileSync(pointer) {
2020
2063
const modulePath = revertMakingLong ( args [ 1 ] ) ;
2021
2064
const moduleBaseName = path . basename ( modulePath ) ;
2022
2065
const moduleFolder = path . dirname ( modulePath ) ;
2023
- const unknownModuleErrorRegex = / ( [ ^ : ] + ) : c a n n o t o p e n s h a r e d o b j e c t f i l e : N o s u c h f i l e o r d i r e c t o r y / ;
2024
2066
2025
- function tryImporting ( _tmpFolder , previousErrorMessage ) {
2026
- try {
2027
- const res = ancestor . dlopen . apply ( process , args ) ;
2028
- return res ;
2029
- } catch ( e ) {
2030
- if ( e . message === previousErrorMessage ) {
2031
- // we already tried to fix this and it didn't work, give up
2032
- throw e ;
2033
- }
2034
- if ( e . message . match ( unknownModuleErrorRegex ) ) {
2035
- // this case triggers on linux, the error message give us a clue on what dynamic linking library
2036
- // is missing.
2037
- // some modules are packaged with dynamic linking and needs to open other files that should be in
2038
- // the same directory, in this case, we write this file in the same /tmp directory and try to
2039
- // import the module again
2040
-
2041
- const moduleName = e . message . match ( unknownModuleErrorRegex ) [ 1 ] ;
2042
- const importModulePath = path . join ( moduleFolder , moduleName ) ;
2043
-
2044
- if ( ! fs . existsSync ( importModulePath ) ) {
2045
- throw new Error (
2046
- `INTERNAL ERROR this file doesn't exist in the virtual file system :${ importModulePath } `
2047
- ) ;
2048
- }
2049
- const moduleContent1 = fs . readFileSync ( importModulePath ) ;
2050
- const tmpModulePath1 = path . join ( _tmpFolder , moduleName ) ;
2051
-
2052
- try {
2053
- fs . statSync ( tmpModulePath1 ) ;
2054
- } catch ( err ) {
2055
- fs . writeFileSync ( tmpModulePath1 , moduleContent1 , { mode : 0o555 } ) ;
2056
- }
2057
- return tryImporting ( _tmpFolder , e . message ) ;
2058
- }
2067
+ // Example: moduleFolder = /snapshot/appname/node_modules/sharp/build/Release
2068
+ const modulePkgPathRegex = / .* ?n o d e _ m o d u l e s \/ ( ( .+ ?) \/ .* ) / ;
2069
+ // Example: modulePackagePath = sharp/build/Release
2070
+ const modulePackagePath = moduleFolder . match ( modulePkgPathRegex ) [ 1 ] ;
2071
+ // Example: modulePackageName = sharp
2072
+ const modulePackageName = moduleFolder . match ( modulePkgPathRegex ) [ 2 ] ;
2073
+ // Example: modulePkgFolder = /snapshot/appname/node_modules/sharp
2074
+ const modulePkgFolder = moduleFolder . replace (
2075
+ modulePackagePath ,
2076
+ modulePackageName
2077
+ ) ;
2059
2078
2060
- // this case triggers on windows mainly.
2061
- // we copy all stuff that exists in the folder of the .node module
2062
- // into the temporary folders...
2063
- const files = fs . readdirSync ( moduleFolder ) ;
2064
- for ( const file of files ) {
2065
- if ( file === moduleBaseName ) {
2066
- // ignore the current module
2067
- continue ;
2068
- }
2069
- const filenameSrc = path . join ( moduleFolder , file ) ;
2070
-
2071
- if ( fs . statSync ( filenameSrc ) . isDirectory ( ) ) {
2072
- continue ;
2073
- }
2074
- const filenameDst = path . join ( _tmpFolder , file ) ;
2075
- const content = fs . readFileSync ( filenameSrc ) ;
2076
-
2077
- fs . writeFileSync ( filenameDst , content , { mode : 0o555 } ) ;
2078
- }
2079
- return tryImporting ( _tmpFolder , e . message ) ;
2080
- }
2081
- }
2082
2079
if ( insideSnapshot ( modulePath ) ) {
2083
2080
const moduleContent = fs . readFileSync ( modulePath ) ;
2084
2081
2085
2082
// Node addon files and .so cannot be read with fs directly, they are loaded with process.dlopen which needs a filesystem path
2086
2083
// we need to write the file somewhere on disk first and then load it
2084
+ // the hash is needed to be sure we reload the module in case it changes
2087
2085
const hash = createHash ( 'sha256' ) . update ( moduleContent ) . digest ( 'hex' ) ;
2088
2086
2089
- const tmpFolder = path . join ( tmpdir ( ) , hash ) ;
2087
+ // Example: /tmp/pkg/<hash>
2088
+ const tmpFolder = path . join ( tmpdir ( ) , 'pkg' , hash ) ;
2090
2089
if ( ! fs . existsSync ( tmpFolder ) ) {
2091
- fs . mkdirSync ( tmpFolder ) ;
2090
+ // here we copy all files from the snapshot module folder to temporary folder
2091
+ // we keep the module folder structure to prevent issues with modules that are statically
2092
+ // linked using relative paths (Fix #1075)
2093
+ createDirRecursively ( tmpFolder ) ;
2094
+ copyFolderRecursiveSync ( modulePkgFolder , tmpFolder ) ;
2092
2095
}
2093
- const tmpModulePath = path . join ( tmpFolder , moduleBaseName ) ;
2094
2096
2095
- try {
2096
- fs . statSync ( tmpModulePath ) ;
2097
- } catch ( e ) {
2098
- // Most likely this means the module is not on disk yet
2099
- fs . writeFileSync ( tmpModulePath , moduleContent , { mode : 0o755 } ) ;
2100
- }
2101
- args [ 1 ] = tmpModulePath ;
2102
- tryImporting ( tmpFolder ) ;
2103
- } else {
2104
- return ancestor . dlopen . apply ( process , args ) ;
2097
+ // replace the path with the new module path
2098
+ args [ 1 ] = path . join ( tmpFolder , modulePackagePath , moduleBaseName ) ;
2105
2099
}
2100
+
2101
+ return ancestor . dlopen . apply ( process , args ) ;
2106
2102
} ;
2107
2103
} ) ( ) ;
0 commit comments