@hakobu/hakobu 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (284) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +673 -0
  3. package/dictionary/angular-bridge.js +3 -0
  4. package/dictionary/any-promise.js +3 -0
  5. package/dictionary/async.js +3 -0
  6. package/dictionary/aws-sdk.js +7 -0
  7. package/dictionary/babel-core.js +3 -0
  8. package/dictionary/batch.js +3 -0
  9. package/dictionary/bcrypt.js +3 -0
  10. package/dictionary/better-sqlite3.js +3 -0
  11. package/dictionary/bignum.js +3 -0
  12. package/dictionary/bindings.js +3 -0
  13. package/dictionary/blessed.js +8 -0
  14. package/dictionary/body-parser.js +9 -0
  15. package/dictionary/browserify.js +7 -0
  16. package/dictionary/bson.js +3 -0
  17. package/dictionary/buffermaker.js +7 -0
  18. package/dictionary/bunyan.js +9 -0
  19. package/dictionary/busboy.js +7 -0
  20. package/dictionary/bytes.js +3 -0
  21. package/dictionary/callsites.js +3 -0
  22. package/dictionary/chokidar.js +3 -0
  23. package/dictionary/coffee-script.js +7 -0
  24. package/dictionary/colors.js +3 -0
  25. package/dictionary/compression.js +3 -0
  26. package/dictionary/compressjs.js +7 -0
  27. package/dictionary/connect-mongo.js +3 -0
  28. package/dictionary/connect-mongodb.js +3 -0
  29. package/dictionary/connect-redis.js +3 -0
  30. package/dictionary/connect.js +10 -0
  31. package/dictionary/consolidate.js +3 -0
  32. package/dictionary/cookie-parser.js +3 -0
  33. package/dictionary/cookie.js +3 -0
  34. package/dictionary/cors.js +3 -0
  35. package/dictionary/cron.js +3 -0
  36. package/dictionary/cross-env.js +11 -0
  37. package/dictionary/cross-spawn-async.js +3 -0
  38. package/dictionary/curve25519.js +3 -0
  39. package/dictionary/data-preflight.js +7 -0
  40. package/dictionary/debug.js +3 -0
  41. package/dictionary/denymount.js +3 -0
  42. package/dictionary/diff.js +3 -0
  43. package/dictionary/drivelist.js +22 -0
  44. package/dictionary/ed25519.js +3 -0
  45. package/dictionary/ejs.js +3 -0
  46. package/dictionary/elasticsearch.js +3 -0
  47. package/dictionary/electron.js +17 -0
  48. package/dictionary/emailjs.js +3 -0
  49. package/dictionary/engine.io.js +3 -0
  50. package/dictionary/epoll.js +3 -0
  51. package/dictionary/errorhandler.js +7 -0
  52. package/dictionary/errors.js +7 -0
  53. package/dictionary/eslint.js +7 -0
  54. package/dictionary/etcher-image-write.js +3 -0
  55. package/dictionary/exceljs.js +21 -0
  56. package/dictionary/exiftool.exe.js +13 -0
  57. package/dictionary/exiftool.pl.js +13 -0
  58. package/dictionary/express-load.js +12 -0
  59. package/dictionary/express-session.js +3 -0
  60. package/dictionary/express.js +14 -0
  61. package/dictionary/extender.js +11 -0
  62. package/dictionary/extsprintf.js +3 -0
  63. package/dictionary/faye-websocket.js +3 -0
  64. package/dictionary/feathers.js +3 -0
  65. package/dictionary/findup-sync.js +3 -0
  66. package/dictionary/floordate.js +3 -0
  67. package/dictionary/fmt.js +3 -0
  68. package/dictionary/formidable.js +3 -0
  69. package/dictionary/fs-extra.js +3 -0
  70. package/dictionary/fsevents.js +3 -0
  71. package/dictionary/geoip-lite.js +7 -0
  72. package/dictionary/github.js +7 -0
  73. package/dictionary/gm.js +3 -0
  74. package/dictionary/google-closure-compiler-java.js +13 -0
  75. package/dictionary/google-closure-compiler.js +13 -0
  76. package/dictionary/googleapis.js +7 -0
  77. package/dictionary/got.js +3 -0
  78. package/dictionary/graceful-fs.js +19 -0
  79. package/dictionary/grpc.js +11 -0
  80. package/dictionary/gulp.js +3 -0
  81. package/dictionary/hap-nodejs.js +3 -0
  82. package/dictionary/heapdump.js +3 -0
  83. package/dictionary/hoek.js +3 -0
  84. package/dictionary/homebridge.js +3 -0
  85. package/dictionary/http-proxy.js +3 -0
  86. package/dictionary/http-server.js +3 -0
  87. package/dictionary/image-size.js +3 -0
  88. package/dictionary/indexof.js +3 -0
  89. package/dictionary/inquirer.js +3 -0
  90. package/dictionary/j.js +16 -0
  91. package/dictionary/jade.js +3 -0
  92. package/dictionary/jsdom.js +3 -0
  93. package/dictionary/json-stringify-date.js +3 -0
  94. package/dictionary/json-stringify-safe.js +3 -0
  95. package/dictionary/jsonwebtoken.js +3 -0
  96. package/dictionary/kerberos.js +3 -0
  97. package/dictionary/knex.js +7 -0
  98. package/dictionary/later.js +7 -0
  99. package/dictionary/level.js +3 -0
  100. package/dictionary/leveldown.js +10 -0
  101. package/dictionary/levelup.js +3 -0
  102. package/dictionary/liftoff.js +12 -0
  103. package/dictionary/lodash.js +3 -0
  104. package/dictionary/log4js.js +7 -0
  105. package/dictionary/logform.js +7 -0
  106. package/dictionary/machinepack-urls.js +7 -0
  107. package/dictionary/markdown.js +3 -0
  108. package/dictionary/mdns.js +6 -0
  109. package/dictionary/method-override.js +3 -0
  110. package/dictionary/microjob.js +16 -0
  111. package/dictionary/mime-types.js +3 -0
  112. package/dictionary/mime.js +3 -0
  113. package/dictionary/minimatch.js +3 -0
  114. package/dictionary/minstache.js +3 -0
  115. package/dictionary/module-deps.js +3 -0
  116. package/dictionary/moment-timezone.js +3 -0
  117. package/dictionary/moment.js +7 -0
  118. package/dictionary/mongodb-core.js +22 -0
  119. package/dictionary/mongodb.js +7 -0
  120. package/dictionary/mongoose.js +7 -0
  121. package/dictionary/mongoskin.js +7 -0
  122. package/dictionary/ms.js +3 -0
  123. package/dictionary/msgpack.js +3 -0
  124. package/dictionary/multer.js +3 -0
  125. package/dictionary/muri.js +3 -0
  126. package/dictionary/native-or-bluebird.js +3 -0
  127. package/dictionary/natives.js +3 -0
  128. package/dictionary/nconf.js +7 -0
  129. package/dictionary/nedb.js +3 -0
  130. package/dictionary/negotiator.js +7 -0
  131. package/dictionary/newrelic.js +3 -0
  132. package/dictionary/nib.js +3 -0
  133. package/dictionary/nightmare.js +18 -0
  134. package/dictionary/node-forge.js +7 -0
  135. package/dictionary/node-libcurl.js +3 -0
  136. package/dictionary/node-notifier.js +30 -0
  137. package/dictionary/node-pre-gyp.js +7 -0
  138. package/dictionary/node-redis-pubsub.js +3 -0
  139. package/dictionary/node-sass.js +3 -0
  140. package/dictionary/node-uuid.js +3 -0
  141. package/dictionary/node-xlsx.js +3 -0
  142. package/dictionary/node-zookeeper-client.js +7 -0
  143. package/dictionary/nodegit.js +7 -0
  144. package/dictionary/nodemailer-sendmail-transport.js +3 -0
  145. package/dictionary/nodemailer.js +3 -0
  146. package/dictionary/npm-registry-client.js +7 -0
  147. package/dictionary/npm.js +7 -0
  148. package/dictionary/nssocket.js +3 -0
  149. package/dictionary/oauth2orize.js +7 -0
  150. package/dictionary/octobat.js +3 -0
  151. package/dictionary/open.js +13 -0
  152. package/dictionary/opn.js +4 -0
  153. package/dictionary/optimist.js +3 -0
  154. package/dictionary/passport-local.js +3 -0
  155. package/dictionary/passport.js +3 -0
  156. package/dictionary/pg-cursor.js +3 -0
  157. package/dictionary/pg-query-stream.js +3 -0
  158. package/dictionary/pg-types.js +7 -0
  159. package/dictionary/pg.js +7 -0
  160. package/dictionary/pg.js.js +7 -0
  161. package/dictionary/pgpass.js +7 -0
  162. package/dictionary/phantom.js +19 -0
  163. package/dictionary/phantomjs-prebuilt.js +16 -0
  164. package/dictionary/pkginfo.js +3 -0
  165. package/dictionary/pm2.js +7 -0
  166. package/dictionary/pmx.js +3 -0
  167. package/dictionary/pouchdb.js +3 -0
  168. package/dictionary/primus-emitter.js +3 -0
  169. package/dictionary/primus-spark-latency.js +3 -0
  170. package/dictionary/primus.js +3 -0
  171. package/dictionary/publicsuffixlist.js +15 -0
  172. package/dictionary/pug.js +3 -0
  173. package/dictionary/punt.js +3 -0
  174. package/dictionary/puppeteer.js +13 -0
  175. package/dictionary/pwd.js +3 -0
  176. package/dictionary/q.js +3 -0
  177. package/dictionary/raven.js +3 -0
  178. package/dictionary/rc.js +12 -0
  179. package/dictionary/readable-stream.js +3 -0
  180. package/dictionary/rechoir.js +3 -0
  181. package/dictionary/redis-parser.js +3 -0
  182. package/dictionary/redis.js +3 -0
  183. package/dictionary/regression.js +3 -0
  184. package/dictionary/reload.js +7 -0
  185. package/dictionary/request.js +3 -0
  186. package/dictionary/require-uncached.js +3 -0
  187. package/dictionary/require_optional.js +3 -0
  188. package/dictionary/s3.js +3 -0
  189. package/dictionary/safe_datejs.js +3 -0
  190. package/dictionary/sails.js +33 -0
  191. package/dictionary/sax.js +3 -0
  192. package/dictionary/scrypt.js +3 -0
  193. package/dictionary/semver.js +3 -0
  194. package/dictionary/sequelize.js +7 -0
  195. package/dictionary/serialport.js +3 -0
  196. package/dictionary/sha3.js +3 -0
  197. package/dictionary/sharp.js +11 -0
  198. package/dictionary/shelljs.js +7 -0
  199. package/dictionary/sinon.js +3 -0
  200. package/dictionary/socket.io-client.js +13 -0
  201. package/dictionary/socket.io.js +12 -0
  202. package/dictionary/sqip.js +7 -0
  203. package/dictionary/sqlite3.js +7 -0
  204. package/dictionary/steam-crypto.js +7 -0
  205. package/dictionary/steam-resources.js +19 -0
  206. package/dictionary/steam.js +3 -0
  207. package/dictionary/stripe-webhook-middleware.js +3 -0
  208. package/dictionary/stripe.js +3 -0
  209. package/dictionary/strong-globalize.js +3 -0
  210. package/dictionary/stylus.js +14 -0
  211. package/dictionary/supervisor.js +3 -0
  212. package/dictionary/svgo.js +8 -0
  213. package/dictionary/tabtab.js +3 -0
  214. package/dictionary/tesseract.js.js +7 -0
  215. package/dictionary/thread-stream.js +7 -0
  216. package/dictionary/throng.js +3 -0
  217. package/dictionary/time.js +3 -0
  218. package/dictionary/tinify.js +7 -0
  219. package/dictionary/tiny-worker.js +7 -0
  220. package/dictionary/tmp.js +3 -0
  221. package/dictionary/transformers.js +3 -0
  222. package/dictionary/uglify-js.js +9 -0
  223. package/dictionary/umd.js +19 -0
  224. package/dictionary/underscore.js +3 -0
  225. package/dictionary/union.js +3 -0
  226. package/dictionary/update-notifier.js +3 -0
  227. package/dictionary/usage.js +7 -0
  228. package/dictionary/v8flags.js +13 -0
  229. package/dictionary/verror.js +3 -0
  230. package/dictionary/voc.js +3 -0
  231. package/dictionary/webdriverio.js +7 -0
  232. package/dictionary/winston-uber.js +7 -0
  233. package/dictionary/winston.js +7 -0
  234. package/dictionary/ws.js +3 -0
  235. package/dictionary/xlsx.js +16 -0
  236. package/dictionary/xml2js.js +3 -0
  237. package/dictionary/yargs.js +3 -0
  238. package/dictionary/zeromq.js +13 -0
  239. package/lib-es5/addon-extract.js +164 -0
  240. package/lib-es5/analyzer.js +687 -0
  241. package/lib-es5/app-bundle.js +133 -0
  242. package/lib-es5/appdir.js +265 -0
  243. package/lib-es5/bin.js +304 -0
  244. package/lib-es5/bootstrap.js +179 -0
  245. package/lib-es5/bundler.js +496 -0
  246. package/lib-es5/chmod.js +15 -0
  247. package/lib-es5/colors.js +12 -0
  248. package/lib-es5/commands.js +376 -0
  249. package/lib-es5/common.js +328 -0
  250. package/lib-es5/compress_type.js +10 -0
  251. package/lib-es5/config.js +291 -0
  252. package/lib-es5/detector.js +421 -0
  253. package/lib-es5/esm-hooks.js +366 -0
  254. package/lib-es5/esm-resolver.js +292 -0
  255. package/lib-es5/esm-transformer.js +378 -0
  256. package/lib-es5/exports-resolver.js +184 -0
  257. package/lib-es5/external-artifacts.js +170 -0
  258. package/lib-es5/fabricator.js +137 -0
  259. package/lib-es5/follow.js +190 -0
  260. package/lib-es5/help.js +52 -0
  261. package/lib-es5/index.d.ts +2 -0
  262. package/lib-es5/index.js +552 -0
  263. package/lib-es5/log.js +7 -0
  264. package/lib-es5/mach-o.js +262 -0
  265. package/lib-es5/manifest.js +21 -0
  266. package/lib-es5/options.js +19 -0
  267. package/lib-es5/packager.js +1036 -0
  268. package/lib-es5/packer.js +137 -0
  269. package/lib-es5/pe-metadata.js +130 -0
  270. package/lib-es5/producer.js +378 -0
  271. package/lib-es5/refiner.js +87 -0
  272. package/lib-es5/resolver.js +142 -0
  273. package/lib-es5/runtime-diagnostics.js +172 -0
  274. package/lib-es5/sea.js +307 -0
  275. package/lib-es5/snapshot-fs-patch.js +396 -0
  276. package/lib-es5/snapshot-fs.js +255 -0
  277. package/lib-es5/snapshot-index.js +135 -0
  278. package/lib-es5/snapshot-path.js +168 -0
  279. package/lib-es5/types.js +9 -0
  280. package/lib-es5/walker.js +1019 -0
  281. package/lib-es5/windows-sign.js +139 -0
  282. package/package.json +99 -0
  283. package/prelude/bootstrap.js +2263 -0
  284. package/prelude/diagnostic.js +147 -0
@@ -0,0 +1,2263 @@
1
+ /* global EXECPATH_FD */
2
+ /* global PAYLOAD_POSITION */
3
+ /* global PAYLOAD_SIZE */
4
+ /* global REQUIRE_COMMON */
5
+ /* global VIRTUAL_FILESYSTEM */
6
+ /* global DEFAULT_ENTRYPOINT */
7
+ /* global DICT */
8
+ /* global DOCOMPRESS */
9
+ /* global SYMLINKS */
10
+
11
+ 'use strict';
12
+
13
+ const childProcess = require('child_process');
14
+ const { createHash } = require('crypto');
15
+ const fs = require('fs');
16
+ const { isRegExp } = require('util').types;
17
+ const Module = require('module');
18
+ const path = require('path');
19
+ const { promisify } = require('util');
20
+ const { Script } = require('vm');
21
+ const { homedir } = require('os');
22
+ const util = require('util');
23
+ const {
24
+ brotliDecompress,
25
+ brotliDecompressSync,
26
+ gunzip,
27
+ gunzipSync,
28
+ } = require('zlib');
29
+
30
+ const common = {};
31
+ REQUIRE_COMMON(common);
32
+
33
+ const {
34
+ STORE_BLOB,
35
+ STORE_CONTENT,
36
+ STORE_LINKS,
37
+ STORE_STAT,
38
+ isRootPath,
39
+ normalizePath,
40
+ insideSnapshot,
41
+ stripSnapshot,
42
+ removeUplevels,
43
+ } = common;
44
+
45
+ let FLAG_ENABLE_PROJECT = false;
46
+ const NODE_VERSION_MAJOR = process.version.match(/^v(\d+)/)[1] | 0;
47
+ const NODE_VERSION_MINOR = process.version.match(/^v\d+.(\d+)/)[1] | 0;
48
+
49
+ // /////////////////////////////////////////////////////////////////
50
+ // ENTRYPOINT //////////////////////////////////////////////////////
51
+ // /////////////////////////////////////////////////////////////////
52
+
53
+ // set ENTRYPOINT and ARGV0 here because
54
+ // they can be altered during process run
55
+ const ARGV0 = process.argv[0];
56
+ const EXECPATH = process.execPath;
57
+ let ENTRYPOINT = process.argv[1];
58
+
59
+ if (process.env.PKG_EXECPATH === 'PKG_INVOKE_NODEJS') {
60
+ return { undoPatch: true };
61
+ }
62
+
63
+ if (NODE_VERSION_MAJOR < 12 || require('worker_threads').isMainThread) {
64
+ if (process.argv[1] !== 'PKG_DUMMY_ENTRYPOINT') {
65
+ // expand once patchless is introduced, that
66
+ // will obviously lack any work in node_main.cc
67
+ throw new Error('PKG_DUMMY_ENTRYPOINT EXPECTED');
68
+ }
69
+ }
70
+
71
+ if (process.env.PKG_EXECPATH === EXECPATH) {
72
+ process.argv.splice(1, 1);
73
+
74
+ if (process.argv[1] && process.argv[1] !== '-') {
75
+ // https://github.com/nodejs/node/blob/1a96d83a223ff9f05f7d942fb84440d323f7b596/lib/internal/bootstrap/node.js#L269
76
+ process.argv[1] = path.resolve(process.argv[1]);
77
+ }
78
+ } else {
79
+ process.argv[1] = DEFAULT_ENTRYPOINT;
80
+ }
81
+
82
+ [, ENTRYPOINT = DEFAULT_ENTRYPOINT] = process.argv;
83
+ delete process.env.PKG_EXECPATH;
84
+
85
+ // /////////////////////////////////////////////////////////////////
86
+ // EXECSTAT ////////////////////////////////////////////////////////
87
+ // /////////////////////////////////////////////////////////////////
88
+
89
+ const EXECSTAT = fs.statSync(EXECPATH);
90
+
91
+ EXECSTAT.atimeMs = EXECSTAT.atime.getTime();
92
+ EXECSTAT.mtimeMs = EXECSTAT.mtime.getTime();
93
+ EXECSTAT.ctimeMs = EXECSTAT.ctime.getTime();
94
+ EXECSTAT.birthtimeMs = EXECSTAT.birthtime.getTime();
95
+
96
+ // /////////////////////////////////////////////////////////////////
97
+ // MOUNTPOINTS /////////////////////////////////////////////////////
98
+ // /////////////////////////////////////////////////////////////////
99
+
100
+ const mountpoints = [];
101
+
102
+ function insideMountpoint(f) {
103
+ if (!insideSnapshot(f)) return null;
104
+ const file = normalizePath(f);
105
+ const found = mountpoints
106
+ .map((mountpoint) => {
107
+ const { interior, exterior } = mountpoint;
108
+ if (isRegExp(interior) && interior.test(file))
109
+ return file.replace(interior, exterior);
110
+ if (interior === file) return exterior;
111
+ const left = interior + path.sep;
112
+ if (file.slice(0, left.length) !== left) return null;
113
+ return exterior + file.slice(left.length - 1);
114
+ })
115
+ .filter((result) => result);
116
+
117
+ if (found.length >= 2) throw new Error('UNEXPECTED-00');
118
+ if (found.length === 0) return null;
119
+ return found[0];
120
+ }
121
+
122
+ function readdirMountpoints(path_) {
123
+ return mountpoints
124
+ .filter(({ interior }) => {
125
+ if (isRegExp(interior)) return interior.test(path_);
126
+ return path.dirname(interior) === path_;
127
+ })
128
+ .map(({ interior, exterior }) => {
129
+ if (isRegExp(interior)) return path_.replace(interior, exterior);
130
+ return path.basename(interior);
131
+ });
132
+ }
133
+
134
+ function translate(f) {
135
+ const result = insideMountpoint(f);
136
+ if (!result) throw new Error('UNEXPECTED-05');
137
+ return result;
138
+ }
139
+
140
+ function cloneArgs(args_) {
141
+ return Array.prototype.slice.call(args_);
142
+ }
143
+
144
+ function translateNth(args_, index, f) {
145
+ const args = cloneArgs(args_);
146
+ args[index] = translate(f);
147
+ return args;
148
+ }
149
+
150
+ function createMountpoint(interior, exterior) {
151
+ // TODO validate
152
+ mountpoints.push({ interior, exterior });
153
+ }
154
+
155
+ const DEFAULT_COPY_CHUNK_SIZE = 10 * 1024 * 1024; // 10 MB
156
+ function copyInChunks(
157
+ source,
158
+ target,
159
+ chunkSize = DEFAULT_COPY_CHUNK_SIZE,
160
+ fs_ = fs,
161
+ ) {
162
+ const sourceFile = fs_.openSync(source, 'r');
163
+ const targetFile = fs_.openSync(target, 'w');
164
+
165
+ let bytesRead = 1;
166
+ while (bytesRead > 0) {
167
+ const buffer = Buffer.alloc(chunkSize);
168
+ bytesRead = fs_.readSync(sourceFile, buffer, 0, chunkSize);
169
+ fs_.writeSync(targetFile, buffer, 0, bytesRead);
170
+ }
171
+
172
+ fs_.closeSync(sourceFile);
173
+ fs_.closeSync(targetFile);
174
+ }
175
+
176
+ // TODO: replace this with fs.cpSync when we drop Node < 16
177
+ function copyFolderRecursiveSync(source, target) {
178
+ // Build target folder
179
+ const targetFolder = path.join(target, path.basename(source));
180
+
181
+ // Check if target folder needs to be created or integrated
182
+ fs.mkdirSync(targetFolder, { recursive: true });
183
+
184
+ // Copy
185
+ if (fs.lstatSync(source).isDirectory()) {
186
+ const files = fs.readdirSync(source);
187
+
188
+ for (const file of files) {
189
+ // Build source name
190
+ const curSource = path.join(source, file);
191
+
192
+ // Call this function recursively as long as source is a directory
193
+ if (fs.lstatSync(curSource).isDirectory()) {
194
+ copyFolderRecursiveSync(curSource, targetFolder);
195
+ } else {
196
+ // Current source is a file, it must be available on the real filesystem
197
+ // instead of the virtual snapshot file system to load it by process.dlopen.
198
+ //
199
+ // Before we try to copy we do some checks.
200
+ // See https://github.com/vercel/pkg/issues/1589 for more details.
201
+
202
+ // Build target file name
203
+ const curTarget = path.join(targetFolder, path.basename(curSource));
204
+
205
+ if (fs.existsSync(curTarget)) {
206
+ // Target file already exists, read source and target file...
207
+ const curSourceContent = fs.readFileSync(curSource, {
208
+ encoding: 'binary',
209
+ });
210
+ const curTargetContent = fs.readFileSync(curTarget, {
211
+ encoding: 'binary',
212
+ });
213
+
214
+ // ...and calculate checksum from source and target file
215
+ const curSourceHash = createHash('sha256')
216
+ .update(curSourceContent)
217
+ .digest('hex');
218
+ const curTargetHash = createHash('sha256')
219
+ .update(curTargetContent)
220
+ .digest('hex');
221
+
222
+ // If checksums are equal then there is nothing to do here
223
+ // ==> target already exists and is up-to-date
224
+ if (curSourceHash === curTargetHash) {
225
+ continue;
226
+ }
227
+ }
228
+
229
+ // Target must be copied because it either does not exist or is outdated.
230
+ // Due to the possibility that mutliple instances of this app start simultaneously,
231
+ // the copy action might fail. Only one starting instance gets write access.
232
+ //
233
+ // We don't catch any error here because it does not make sense to go ahead and to
234
+ // try to load the file while another instance has not yet finished the copy action.
235
+ // If the app start fails then the user should try to start the app later again.
236
+ // Unfortunately, we cannot implement delayed retries ourselves because process.dlopen
237
+ // is a synchronous function, promises are not supported.
238
+ fs.copyFileSync(curSource, curTarget);
239
+ }
240
+ }
241
+ }
242
+ }
243
+
244
+ /*
245
+
246
+ // TODO move to some test
247
+
248
+ createMountpoint("d:\\snapshot\\countly\\plugins-ext", "d:\\deploy\\countly\\v16.02\\plugins-ext");
249
+
250
+ console.log(insideMountpoint("d:\\snapshot"));
251
+ console.log(insideMountpoint("d:\\snapshot\\"));
252
+ console.log(insideMountpoint("d:\\snapshot\\countly"));
253
+ console.log(insideMountpoint("d:\\snapshot\\countly\\"));
254
+ console.log(insideMountpoint("d:\\snapshot\\countly\\plugins-ext"));
255
+ console.log(insideMountpoint("d:\\snapshot\\countly\\plugins-ext\\"));
256
+ console.log(insideMountpoint("d:\\snapshot\\countly\\plugins-ext\\1234"));
257
+
258
+ console.log(translate("d:\\snapshot\\countly\\plugins-ext"));
259
+ console.log(translate("d:\\snapshot\\countly\\plugins-ext\\"));
260
+ console.log(translate("d:\\snapshot\\countly\\plugins-ext\\1234"));
261
+
262
+ console.log(translateNth([], 0, "d:\\snapshot\\countly\\plugins-ext"));
263
+ console.log(translateNth([], 0, "d:\\snapshot\\countly\\plugins-ext\\"));
264
+ console.log(translateNth([], 0, "d:\\snapshot\\countly\\plugins-ext\\1234"));
265
+
266
+ console.log(translateNth(["", "r+"], 0, "d:\\snapshot\\countly\\plugins-ext"));
267
+ console.log(translateNth(["", "rw"], 0, "d:\\snapshot\\countly\\plugins-ext\\"));
268
+ console.log(translateNth(["", "a+"], 0, "d:\\snapshot\\countly\\plugins-ext\\1234"));
269
+ */
270
+ const dictRev = {};
271
+ const separator = '/';
272
+ let maxKey = Object.values(DICT).length;
273
+
274
+ function replace(k) {
275
+ let v = DICT[k];
276
+ // we have found a part of a missing file => let record for latter use
277
+ if (v === undefined) {
278
+ maxKey += 1;
279
+ v = maxKey.toString(36);
280
+ DICT[k] = v;
281
+ dictRev[v] = k;
282
+ }
283
+ return v;
284
+ }
285
+
286
+ function findVirtualFileSystemKey(path_, slash) {
287
+ const normalizedPath = normalizePath(path_);
288
+ if (!DOCOMPRESS) {
289
+ return normalizedPath;
290
+ }
291
+ const a = normalizedPath.split(slash).map(replace).join(separator);
292
+ return a || normalizedPath;
293
+ }
294
+
295
+ Object.entries(DICT).forEach(([k, v]) => {
296
+ dictRev[v] = k;
297
+ });
298
+
299
+ function toOriginal(fShort) {
300
+ if (!DOCOMPRESS) {
301
+ return fShort;
302
+ }
303
+ return fShort
304
+ .split(separator)
305
+ .map((x) => dictRev[x])
306
+ .join(path.sep);
307
+ }
308
+
309
+ const symlinksEntries = Object.entries(SYMLINKS);
310
+
311
+ // separator for substitution depends on platform;
312
+ const sepsep = DOCOMPRESS ? separator : path.sep;
313
+
314
+ function findVirtualFileSystemKeyAndFollowLinks(path_) {
315
+ let vfsKey = findVirtualFileSystemKey(path_, path.sep);
316
+ let needToSubstitute = true;
317
+ while (needToSubstitute) {
318
+ needToSubstitute = false;
319
+ for (const [k, v] of symlinksEntries) {
320
+ if (vfsKey.startsWith(`${k}${sepsep}`) || vfsKey === k) {
321
+ vfsKey = vfsKey.replace(k, v);
322
+ needToSubstitute = true;
323
+ break;
324
+ }
325
+ }
326
+ }
327
+ return vfsKey;
328
+ }
329
+
330
+ function realpathFromSnapshot(path_) {
331
+ const realPath = toOriginal(findVirtualFileSystemKeyAndFollowLinks(path_));
332
+ return realPath;
333
+ }
334
+
335
+ function findVirtualFileSystemEntry(path_) {
336
+ const vfsKey = findVirtualFileSystemKeyAndFollowLinks(path_);
337
+ return VIRTUAL_FILESYSTEM[vfsKey];
338
+ }
339
+
340
+ // /////////////////////////////////////////////////////////////////
341
+ // PROJECT /////////////////////////////////////////////////////////
342
+ // /////////////////////////////////////////////////////////////////
343
+
344
+ const xpdn = path.dirname(EXECPATH);
345
+ const maxUplevels = xpdn.split(path.sep).length;
346
+ function projectToFilesystem(f) {
347
+ const relatives = [];
348
+ relatives.push(
349
+ removeUplevels(path.relative(path.dirname(DEFAULT_ENTRYPOINT), f)),
350
+ );
351
+
352
+ if (relatives[0].slice(0, 'node_modules'.length) === 'node_modules') {
353
+ // one more relative without starting 'node_modules'
354
+ relatives.push(relatives[0].slice('node_modules'.length + 1));
355
+ }
356
+
357
+ const uplevels = [];
358
+ for (let i = 0, u = ''; i < maxUplevels; i += 1) {
359
+ uplevels.push(u);
360
+ u += '/..';
361
+ }
362
+
363
+ const results = [];
364
+ uplevels.forEach((uplevel) => {
365
+ relatives.forEach((relative) => {
366
+ results.push(path.join(xpdn, uplevel, relative));
367
+ });
368
+ });
369
+ return results;
370
+ }
371
+
372
+ function projectToNearby(f) {
373
+ return path.join(xpdn, path.basename(f));
374
+ }
375
+ function findNativeAddonSyncFreeFromRequire(path_) {
376
+ if (!insideSnapshot(path_)) throw new Error(`UNEXPECTED-10 ${path_}`);
377
+ if (path_.slice(-5) !== '.node') return null; // leveldown.node.js
378
+ // check nearby first to prevent .node tampering
379
+ const projector = projectToNearby(path_);
380
+ if (fs.existsSync(projector)) return projector;
381
+ const projectors = projectToFilesystem(path_);
382
+ for (let i = 0; i < projectors.length; i += 1) {
383
+ if (fs.existsSync(projectors[i])) return projectors[i];
384
+ }
385
+ return null;
386
+ }
387
+
388
+ function findNativeAddonSyncUnderRequire(path_) {
389
+ if (!FLAG_ENABLE_PROJECT) return null;
390
+ return findNativeAddonSyncFreeFromRequire(path_);
391
+ }
392
+
393
+ // /////////////////////////////////////////////////////////////////
394
+ // FLOW UTILS //////////////////////////////////////////////////////
395
+ // /////////////////////////////////////////////////////////////////
396
+
397
+ function asap(cb) {
398
+ process.nextTick(cb);
399
+ }
400
+
401
+ function dezalgo(cb) {
402
+ if (!cb) return cb;
403
+
404
+ let sync = true;
405
+ asap(() => {
406
+ sync = false;
407
+ });
408
+
409
+ return function zalgoSafe() {
410
+ const args = arguments;
411
+ if (sync) {
412
+ asap(() => {
413
+ cb.apply(undefined, args);
414
+ });
415
+ } else {
416
+ cb.apply(undefined, args);
417
+ }
418
+ };
419
+ }
420
+
421
+ function rethrow(error, arg) {
422
+ if (error) throw error;
423
+ return arg;
424
+ }
425
+
426
+ // /////////////////////////////////////////////////////////////////
427
+ // PAYLOAD /////////////////////////////////////////////////////////
428
+ // /////////////////////////////////////////////////////////////////
429
+ if (typeof PAYLOAD_POSITION !== 'number' || typeof PAYLOAD_SIZE !== 'number') {
430
+ throw new Error('MUST HAVE PAYLOAD');
431
+ }
432
+
433
+ function readPayload(buffer, offset, length, position, callback) {
434
+ fs.read(
435
+ EXECPATH_FD,
436
+ buffer,
437
+ offset,
438
+ length,
439
+ PAYLOAD_POSITION + position,
440
+ callback,
441
+ );
442
+ }
443
+
444
+ function readPayloadSync(buffer, offset, length, position) {
445
+ return fs.readSync(
446
+ EXECPATH_FD,
447
+ buffer,
448
+ offset,
449
+ length,
450
+ PAYLOAD_POSITION + position,
451
+ );
452
+ }
453
+
454
+ function payloadCopyUni(
455
+ source,
456
+ target,
457
+ targetStart,
458
+ sourceStart,
459
+ sourceEnd,
460
+ cb,
461
+ ) {
462
+ const cb2 = cb || rethrow;
463
+ if (sourceStart >= source[1]) return cb2(null, 0);
464
+ if (sourceEnd >= source[1]) [, sourceEnd] = source;
465
+ const payloadPos = source[0] + sourceStart;
466
+ const targetPos = targetStart;
467
+ const targetEnd = targetStart + sourceEnd - sourceStart;
468
+ if (cb) {
469
+ readPayload(target, targetPos, targetEnd - targetPos, payloadPos, cb);
470
+ } else {
471
+ return readPayloadSync(
472
+ target,
473
+ targetPos,
474
+ targetEnd - targetPos,
475
+ payloadPos,
476
+ );
477
+ }
478
+ }
479
+
480
+ function payloadCopyMany(source, target, targetStart, sourceStart, cb) {
481
+ const payloadPos = source[0] + sourceStart;
482
+ let targetPos = targetStart;
483
+ const targetEnd = targetStart + source[1] - sourceStart;
484
+ readPayload(
485
+ target,
486
+ targetPos,
487
+ targetEnd - targetPos,
488
+ payloadPos,
489
+ (error, chunkSize) => {
490
+ if (error) return cb(error);
491
+ sourceStart += chunkSize;
492
+ targetPos += chunkSize;
493
+ if (chunkSize !== 0 && targetPos < targetEnd) {
494
+ payloadCopyMany(source, target, targetPos, sourceStart, cb);
495
+ } else {
496
+ return cb();
497
+ }
498
+ },
499
+ );
500
+ }
501
+
502
+ function payloadCopyManySync(source, target, targetStart, sourceStart) {
503
+ let payloadPos = source[0] + sourceStart;
504
+ let targetPos = targetStart;
505
+ const targetEnd = targetStart + source[1] - sourceStart;
506
+ while (true) {
507
+ const chunkSize = readPayloadSync(
508
+ target,
509
+ targetPos,
510
+ targetEnd - targetPos,
511
+ payloadPos,
512
+ );
513
+ payloadPos += chunkSize;
514
+ targetPos += chunkSize;
515
+ if (!(chunkSize !== 0 && targetPos < targetEnd)) break;
516
+ }
517
+ }
518
+
519
+ const GZIP = 1;
520
+ const BROTLI = 2;
521
+ function payloadFile(pointer, cb) {
522
+ const target = Buffer.alloc(pointer[1]);
523
+ payloadCopyMany(pointer, target, 0, 0, (error) => {
524
+ if (error) return cb(error);
525
+ if (DOCOMPRESS === GZIP) {
526
+ gunzip(target, (error2, target2) => {
527
+ if (error2) return cb(error2);
528
+ cb(null, target2);
529
+ });
530
+ } else if (DOCOMPRESS === BROTLI) {
531
+ brotliDecompress(target, (error2, target2) => {
532
+ if (error2) return cb(error2);
533
+ cb(null, target2);
534
+ });
535
+ } else {
536
+ return cb(null, target);
537
+ }
538
+ });
539
+ }
540
+
541
+ function payloadFileSync(pointer) {
542
+ const target = Buffer.alloc(pointer[1]);
543
+ payloadCopyManySync(pointer, target, 0, 0);
544
+ if (DOCOMPRESS === GZIP) {
545
+ const target1 = gunzipSync(target);
546
+ return target1;
547
+ }
548
+ if (DOCOMPRESS === BROTLI) {
549
+ const target1 = brotliDecompressSync(target);
550
+ return target1;
551
+ }
552
+ return target;
553
+ }
554
+
555
+ // /////////////////////////////////////////////////////////////////
556
+ // SETUP PROCESS ///////////////////////////////////////////////////
557
+ // /////////////////////////////////////////////////////////////////
558
+
559
+ (() => {
560
+ process.pkg = {};
561
+ process.versions.pkg = '%VERSION%';
562
+ process.pkg.mount = createMountpoint;
563
+ process.pkg.entrypoint = ENTRYPOINT;
564
+ process.pkg.defaultEntrypoint = DEFAULT_ENTRYPOINT;
565
+ })();
566
+
567
+ // /////////////////////////////////////////////////////////////////
568
+ // PATH.RESOLVE REPLACEMENT ////////////////////////////////////////
569
+ // /////////////////////////////////////////////////////////////////
570
+
571
+ (() => {
572
+ process.pkg.path = {};
573
+ process.pkg.path.resolve = function resolve() {
574
+ const args = cloneArgs(arguments);
575
+ args.unshift(path.dirname(ENTRYPOINT));
576
+ return path.resolve.apply(path, args);
577
+ };
578
+ })();
579
+
580
+ // /////////////////////////////////////////////////////////////////
581
+ // PATCH FS ////////////////////////////////////////////////////////
582
+ // /////////////////////////////////////////////////////////////////
583
+
584
+ (() => {
585
+ const ancestor = {
586
+ openSync: fs.openSync,
587
+ open: fs.open,
588
+ readSync: fs.readSync,
589
+ read: fs.read,
590
+ writeSync: fs.writeSync,
591
+ write: fs.write,
592
+ closeSync: fs.closeSync,
593
+ close: fs.close,
594
+ readFileSync: fs.readFileSync,
595
+ readFile: fs.readFile,
596
+ // writeFileSync: fs.writeFileSync, // based on openSync/writeSync/closeSync
597
+ // writeFile: fs.writeFile, // based on open/write/close
598
+ readdirSync: fs.readdirSync,
599
+ readdir: fs.readdir,
600
+ realpathSync: fs.realpathSync,
601
+ realpath: fs.realpath,
602
+ statSync: fs.statSync,
603
+ stat: fs.stat,
604
+ lstatSync: fs.lstatSync,
605
+ lstat: fs.lstat,
606
+ fstatSync: fs.fstatSync,
607
+ fstat: fs.fstat,
608
+ existsSync: fs.existsSync,
609
+ exists: fs.exists,
610
+ accessSync: fs.accessSync,
611
+ access: fs.access,
612
+ mkdirSync: fs.mkdirSync,
613
+ mkdir: fs.mkdir,
614
+ createReadStream: fs.createReadStream,
615
+ copyFileSync: fs.copyFileSync,
616
+ copyFile: fs.copyFile,
617
+ };
618
+
619
+ ancestor.realpathSync.native = fs.realpathSync;
620
+ ancestor.realpath.native = fs.realpath;
621
+
622
+ const windows = process.platform === 'win32';
623
+
624
+ const docks = {};
625
+ const ENOTDIR = windows ? 4052 : 20;
626
+ const ENOENT = windows ? 4058 : 2;
627
+ const EISDIR = windows ? 4068 : 21;
628
+
629
+ function assertEncoding(encoding) {
630
+ if (encoding && !Buffer.isEncoding(encoding)) {
631
+ throw new Error(`Unknown encoding: ${encoding}`);
632
+ }
633
+ }
634
+
635
+ function maybeCallback(args) {
636
+ const cb = args[args.length - 1];
637
+ return typeof cb === 'function' ? cb : rethrow;
638
+ }
639
+
640
+ function error_ENOENT(fileOrDirectory, path_) {
641
+ const error = new Error(
642
+ `${fileOrDirectory} '${stripSnapshot(path_)}' ` +
643
+ `was not included into executable at compilation stage. ` +
644
+ `Please recompile adding it as asset or script.`,
645
+ );
646
+ error.errno = -ENOENT;
647
+ error.code = 'ENOENT';
648
+ error.path = path_;
649
+ error.pkg = true;
650
+ return error;
651
+ }
652
+
653
+ function error_EISDIR(path_) {
654
+ const error = new Error('EISDIR: illegal operation on a directory, read');
655
+ error.errno = -EISDIR;
656
+ error.code = 'EISDIR';
657
+ error.path = path_;
658
+ error.pkg = true;
659
+ return error;
660
+ }
661
+
662
+ function error_ENOTDIR(path_) {
663
+ const error = new Error(`ENOTDIR: not a directory, scandir '${path_}'`);
664
+ error.errno = -ENOTDIR;
665
+ error.code = 'ENOTDIR';
666
+ error.path = path_;
667
+ error.pkg = true;
668
+ return error;
669
+ }
670
+
671
+ // ///////////////////////////////////////////////////////////////
672
+ // open //////////////////////////////////////////////////////////
673
+ // ///////////////////////////////////////////////////////////////
674
+
675
+ function removeTemporaryFolderAndContent(folder) {
676
+ if (!folder) return;
677
+ try {
678
+ fs.rmSync(folder, { recursive: true, force: true });
679
+ } catch {
680
+ // Best-effort cleanup — may fail if another process holds a lock
681
+ }
682
+ }
683
+ const temporaryFiles = {};
684
+ const os = require('os');
685
+ let tmpFolder = '';
686
+ // Use 'exit' instead of 'beforeExit' — 'beforeExit' does NOT fire
687
+ // on process.exit(), which leaves temp files behind.
688
+ // 'exit' fires on both normal completion and explicit process.exit().
689
+ // The handler must be synchronous (fs.rmSync is fine).
690
+ process.on('exit', () => {
691
+ removeTemporaryFolderAndContent(tmpFolder);
692
+ });
693
+ function deflateSync(snapshotFilename) {
694
+ if (!tmpFolder) {
695
+ tmpFolder = fs.mkdtempSync(path.join(os.tmpdir(), 'pkg-'));
696
+ }
697
+ const content = fs.readFileSync(snapshotFilename, { encoding: 'binary' });
698
+ // content is already unzipped !
699
+
700
+ const hash = createHash('sha256').update(content).digest('hex');
701
+ const fName = path.join(tmpFolder, hash);
702
+ fs.writeFileSync(fName, content, 'binary');
703
+ return fName;
704
+ }
705
+
706
+ const uncompressExternally = function uncompressExternally(dock) {
707
+ if (!dock.externalFilename) {
708
+ const snapshotFilename = dock.path;
709
+ let t = temporaryFiles[snapshotFilename];
710
+ if (!t) {
711
+ const tmpFile = deflateSync(snapshotFilename);
712
+ t = { tmpFile };
713
+ temporaryFiles[snapshotFilename] = t;
714
+ }
715
+ dock.externalFilename = t.tmpFile;
716
+ }
717
+ return dock.externalFilename;
718
+ };
719
+
720
+ function uncompressExternallyPath(path_) {
721
+ const entity = findVirtualFileSystemEntry(path_);
722
+ const dock = { path: path_, entity, position: 0 };
723
+ return uncompressExternally(dock);
724
+ }
725
+
726
+ function uncompressExternallyAndOpen(dock) {
727
+ const externalFile = uncompressExternally(dock);
728
+ const fd = fs.openSync(externalFile, 'r');
729
+ return fd;
730
+ }
731
+
732
+ function openFromSnapshot(path_, uncompress, cb) {
733
+ const cb2 = cb || rethrow;
734
+ const entity = findVirtualFileSystemEntry(path_);
735
+ if (!entity) return cb2(error_ENOENT('File or directory', path_));
736
+ const dock = { path: path_, entity, position: 0 };
737
+
738
+ const nullDevice = windows ? '\\\\.\\NUL' : '/dev/null';
739
+ if (cb) {
740
+ ancestor.open.call(fs, nullDevice, 'r', (error, fd) => {
741
+ if (error) return cb(error);
742
+ if (DOCOMPRESS) {
743
+ dock._externalFile = uncompressExternallyAndOpen(dock);
744
+ }
745
+ docks[fd] = dock;
746
+ cb(null, fd);
747
+ });
748
+ } else {
749
+ const fd = ancestor.openSync.call(fs, nullDevice, 'r');
750
+ if (DOCOMPRESS) {
751
+ dock._externalFile = uncompressExternallyAndOpen(dock);
752
+ }
753
+ docks[fd] = dock;
754
+ return fd;
755
+ }
756
+ }
757
+
758
+ fs.createReadStream = function createReadStream(path_) {
759
+ if (!insideSnapshot(path_)) {
760
+ return ancestor.createReadStream.apply(fs, arguments);
761
+ }
762
+ if (insideMountpoint(path_)) {
763
+ return ancestor.createReadStream.apply(
764
+ fs,
765
+ translateNth(arguments, 0, path_),
766
+ );
767
+ }
768
+ const stream = ancestor.createReadStream.apply(fs, arguments);
769
+ return stream;
770
+ };
771
+ fs.openSync = function openSync(path_) {
772
+ if (!insideSnapshot(path_)) {
773
+ return ancestor.openSync.apply(fs, arguments);
774
+ }
775
+ if (insideMountpoint(path_)) {
776
+ return ancestor.openSync.apply(fs, translateNth(arguments, 0, path_));
777
+ }
778
+ return openFromSnapshot(path_, DOCOMPRESS);
779
+ };
780
+
781
+ fs.open = function open(path_) {
782
+ if (!insideSnapshot(path_)) {
783
+ return ancestor.open.apply(fs, arguments);
784
+ }
785
+ if (insideMountpoint(path_)) {
786
+ return ancestor.open.apply(fs, translateNth(arguments, 0, path_));
787
+ }
788
+ const callback = dezalgo(maybeCallback(arguments));
789
+ openFromSnapshot(path_, DOCOMPRESS, callback);
790
+ };
791
+
792
+ // ///////////////////////////////////////////////////////////////
793
+ // read //////////////////////////////////////////////////////////
794
+ // ///////////////////////////////////////////////////////////////
795
+
796
+ function readFromSnapshotSub(
797
+ entityContent,
798
+ dock,
799
+ buffer,
800
+ offset,
801
+ length,
802
+ position,
803
+ cb,
804
+ ) {
805
+ if (DOCOMPRESS) {
806
+ // note: source contains info about a compressed file and source[1] does not reflect
807
+ // the actual size of the file.
808
+ // so random access reading of a compressed virtual file, requires read from
809
+ // an externally decompressed file
810
+ if (!dock._externalFile) {
811
+ dock._externalFile = uncompressExternallyAndOpen(dock);
812
+ } else {
813
+ position = position === undefined ? 0 : position;
814
+ }
815
+ return fs.read(dock._externalFile, buffer, offset, length, position, cb);
816
+ }
817
+ let p;
818
+ if (position !== null && position !== undefined) {
819
+ p = position;
820
+ } else {
821
+ p = dock.position;
822
+ }
823
+ if (cb) {
824
+ payloadCopyUni(
825
+ entityContent,
826
+ buffer,
827
+ offset,
828
+ p,
829
+ p + length,
830
+ (error, bytesRead, buffer2) => {
831
+ if (error) return cb(error);
832
+ dock.position = p + bytesRead;
833
+ cb(null, bytesRead, buffer2);
834
+ },
835
+ );
836
+ } else {
837
+ const bytesRead = payloadCopyUni(
838
+ entityContent,
839
+ buffer,
840
+ offset,
841
+ p,
842
+ p + length,
843
+ );
844
+ dock.position = p + bytesRead;
845
+ return bytesRead;
846
+ }
847
+ }
848
+
849
+ function readFromSnapshot(fd, buffer, offset, length, position, cb) {
850
+ const dock = docks[fd];
851
+
852
+ if (dock && dock._externalFile) {
853
+ if (cb) {
854
+ return ancestor.read(
855
+ dock._externalFile,
856
+ buffer,
857
+ offset,
858
+ length,
859
+ position,
860
+ cb,
861
+ );
862
+ }
863
+ return ancestor.readSync(
864
+ dock._externalFile,
865
+ buffer,
866
+ offset,
867
+ length,
868
+ position,
869
+ );
870
+ }
871
+ const cb2 = cb || rethrow;
872
+ if (offset < 0 && NODE_VERSION_MAJOR >= 14)
873
+ return cb2(
874
+ new Error(
875
+ `The value of "offset" is out of range. It must be >= 0. Received ${offset}`,
876
+ ),
877
+ );
878
+ if (offset < 0 && NODE_VERSION_MAJOR >= 10)
879
+ return cb2(
880
+ new Error(
881
+ `The value of "offset" is out of range. It must be >= 0 && <= ${buffer.length.toString()}. Received ${offset}`,
882
+ ),
883
+ );
884
+ if (offset < 0) return cb2(new Error('Offset is out of bounds'));
885
+ if (offset >= buffer.length) return cb2(null, 0);
886
+ if (offset + length > buffer.length && NODE_VERSION_MAJOR >= 14)
887
+ return cb2(
888
+ new Error(
889
+ `The value of "length" is out of range. It must be <= ${(
890
+ buffer.length - offset
891
+ ).toString()}. Received ${length.toString()}`,
892
+ ),
893
+ );
894
+ if (offset + length > buffer.length && NODE_VERSION_MAJOR >= 10)
895
+ return cb2(
896
+ new Error(
897
+ `The value of "length" is out of range. It must be >= 0 && <= ${(
898
+ buffer.length - offset
899
+ ).toString()}. Received ${length.toString()}`,
900
+ ),
901
+ );
902
+ if (offset + length > buffer.length)
903
+ return cb2(new Error('Length extends beyond buffer'));
904
+
905
+ const { entity } = dock;
906
+ const entityLinks = entity[STORE_LINKS];
907
+ if (entityLinks) return cb2(error_EISDIR(dock.path));
908
+ const entityContent = entity[STORE_CONTENT];
909
+ if (entityContent)
910
+ return readFromSnapshotSub(
911
+ entityContent,
912
+ dock,
913
+ buffer,
914
+ offset,
915
+ length,
916
+ position,
917
+ cb,
918
+ );
919
+ return cb2(new Error('UNEXPECTED-15'));
920
+ }
921
+
922
+ fs.readSync = function readSync(fd, buffer, offset, length, position) {
923
+ if (!docks[fd]) {
924
+ return ancestor.readSync.apply(fs, arguments);
925
+ }
926
+ return readFromSnapshot(fd, buffer, offset, length, position);
927
+ };
928
+
929
+ fs.read = function read(fd, buffer, offset, length, position) {
930
+ if (!docks[fd]) {
931
+ return ancestor.read.apply(fs, arguments);
932
+ }
933
+
934
+ const callback = dezalgo(maybeCallback(arguments));
935
+ readFromSnapshot(fd, buffer, offset, length, position, callback);
936
+ };
937
+
938
+ // ///////////////////////////////////////////////////////////////
939
+ // write /////////////////////////////////////////////////////////
940
+ // ///////////////////////////////////////////////////////////////
941
+
942
+ function writeToSnapshot(cb) {
943
+ const cb2 = cb || rethrow;
944
+ return cb2(new Error('Cannot write to packaged file'));
945
+ }
946
+
947
+ fs.writeSync = function writeSync(fd) {
948
+ if (!docks[fd]) {
949
+ return ancestor.writeSync.apply(fs, arguments);
950
+ }
951
+
952
+ return writeToSnapshot();
953
+ };
954
+
955
+ fs.write = function write(fd) {
956
+ if (!docks[fd]) {
957
+ return ancestor.write.apply(fs, arguments);
958
+ }
959
+ const callback = dezalgo(maybeCallback(arguments));
960
+ return writeToSnapshot(callback);
961
+ };
962
+
963
+ // ///////////////////////////////////////////////////////////////
964
+ // close /////////////////////////////////////////////////////////
965
+ // ///////////////////////////////////////////////////////////////
966
+
967
+ const closeFromSnapshot = (fd, cb) => {
968
+ const dock = docks[fd];
969
+ if (dock._externalFile) {
970
+ ancestor.closeSync(dock._externalFile);
971
+ dock._externalFile = undefined;
972
+ }
973
+ delete docks[fd];
974
+ if (cb) {
975
+ ancestor.close.call(fs, fd, cb);
976
+ } else {
977
+ return ancestor.closeSync.call(fs, fd);
978
+ }
979
+ };
980
+
981
+ fs.closeSync = function closeSync(fd) {
982
+ if (!docks[fd]) {
983
+ return ancestor.closeSync.apply(fs, arguments);
984
+ }
985
+ return closeFromSnapshot(fd);
986
+ };
987
+
988
+ fs.close = function close(fd) {
989
+ if (!docks[fd]) {
990
+ return ancestor.close.apply(fs, arguments);
991
+ }
992
+
993
+ const callback = dezalgo(maybeCallback(arguments));
994
+ closeFromSnapshot(fd, callback);
995
+ };
996
+
997
+ // ///////////////////////////////////////////////////////////////
998
+ // readFile //////////////////////////////////////////////////////
999
+ // ///////////////////////////////////////////////////////////////
1000
+
1001
+ function readFileOptions(options, hasCallback) {
1002
+ if (!options || (hasCallback && typeof options === 'function')) {
1003
+ return { encoding: null, flag: 'r' };
1004
+ }
1005
+ if (typeof options === 'string') {
1006
+ return { encoding: options, flag: 'r' };
1007
+ }
1008
+ if (typeof options === 'object') {
1009
+ return options;
1010
+ }
1011
+ return null;
1012
+ }
1013
+
1014
+ function readFileFromSnapshotSub(entityContent, cb) {
1015
+ if (cb) {
1016
+ payloadFile(entityContent, cb);
1017
+ } else {
1018
+ return payloadFileSync(entityContent);
1019
+ }
1020
+ }
1021
+
1022
+ function readFileFromSnapshot(path_, cb) {
1023
+ const cb2 = cb || rethrow;
1024
+
1025
+ const entity = findVirtualFileSystemEntry(path_);
1026
+ if (!entity) return cb2(error_ENOENT('File', path_));
1027
+
1028
+ const entityLinks = entity[STORE_LINKS];
1029
+ if (entityLinks) return cb2(error_EISDIR(path_));
1030
+
1031
+ const entityContent = entity[STORE_CONTENT];
1032
+ if (entityContent) return readFileFromSnapshotSub(entityContent, cb);
1033
+
1034
+ const entityBlob = entity[STORE_BLOB];
1035
+ if (entityBlob) {
1036
+ return cb2(null, Buffer.from('source-code-not-available'));
1037
+ }
1038
+ // why return empty buffer?
1039
+ // otherwise this error will arise:
1040
+ // Error: UNEXPECTED-20
1041
+ // at readFileFromSnapshot (e:0)
1042
+ // at Object.fs.readFileSync (e:0)
1043
+ // at Object.Module._extensions..js (module.js:421:20)
1044
+ // at Module.load (module.js:357:32)
1045
+ // at Function.Module._load (module.js:314:12)
1046
+ // at Function.Module.runMain (e:0)
1047
+ // at startup (node.js:140:18)
1048
+ // at node.js:1001:3
1049
+
1050
+ return cb2(new Error('UNEXPECTED-20'));
1051
+ }
1052
+
1053
+ fs.readFileSync = function readFileSync(path_, options_) {
1054
+ if (path_ === 'dirty-hack-for-testing-purposes') {
1055
+ return path_;
1056
+ }
1057
+
1058
+ if (!insideSnapshot(path_)) {
1059
+ return ancestor.readFileSync.apply(fs, arguments);
1060
+ }
1061
+ if (insideMountpoint(path_)) {
1062
+ return ancestor.readFileSync.apply(fs, translateNth(arguments, 0, path_));
1063
+ }
1064
+
1065
+ const options = readFileOptions(options_, false);
1066
+
1067
+ if (!options) {
1068
+ return ancestor.readFileSync.apply(fs, arguments);
1069
+ }
1070
+
1071
+ const { encoding } = options;
1072
+ assertEncoding(encoding);
1073
+
1074
+ let buffer = readFileFromSnapshot(path_);
1075
+ if (encoding) buffer = buffer.toString(encoding);
1076
+ return buffer;
1077
+ };
1078
+
1079
+ fs.readFile = function readFile(path_, options_) {
1080
+ if (!insideSnapshot(path_)) {
1081
+ return ancestor.readFile.apply(fs, arguments);
1082
+ }
1083
+ if (insideMountpoint(path_)) {
1084
+ return ancestor.readFile.apply(fs, translateNth(arguments, 0, path_));
1085
+ }
1086
+
1087
+ const options = readFileOptions(options_, true);
1088
+
1089
+ if (!options) {
1090
+ return ancestor.readFile.apply(fs, arguments);
1091
+ }
1092
+
1093
+ const { encoding } = options;
1094
+ assertEncoding(encoding);
1095
+
1096
+ const callback = dezalgo(maybeCallback(arguments));
1097
+ readFileFromSnapshot(path_, (error, buffer) => {
1098
+ if (error) return callback(error);
1099
+ if (encoding) buffer = buffer.toString(encoding);
1100
+ callback(null, buffer);
1101
+ });
1102
+ };
1103
+
1104
+ fs.copyFile = function copyFile(src, dest, flags, callback) {
1105
+ if (!insideSnapshot(path.resolve(src))) {
1106
+ ancestor.copyFile(src, dest, flags, callback);
1107
+ return;
1108
+ }
1109
+ if (typeof flags === 'function') {
1110
+ callback = flags;
1111
+ flags = 0;
1112
+ } else if (typeof callback !== 'function') {
1113
+ throw new TypeError('Callback must be a function');
1114
+ }
1115
+
1116
+ function _streamCopy() {
1117
+ fs.createReadStream(src)
1118
+ .on('error', callback)
1119
+ .pipe(fs.createWriteStream(dest))
1120
+ .on('error', callback)
1121
+ .on('finish', callback);
1122
+ }
1123
+
1124
+ if (flags & fs.constants.COPYFILE_EXCL) {
1125
+ fs.stat(dest, (statError) => {
1126
+ if (!statError) {
1127
+ callback(
1128
+ Object.assign(new Error('File already exists'), {
1129
+ code: 'EEXIST',
1130
+ }),
1131
+ );
1132
+ return;
1133
+ }
1134
+ if (statError.code !== 'ENOENT') {
1135
+ callback(statError);
1136
+ return;
1137
+ }
1138
+ _streamCopy();
1139
+ });
1140
+ } else {
1141
+ _streamCopy();
1142
+ }
1143
+ };
1144
+
1145
+ fs.copyFileSync = function copyFileSync(src, dest, flags) {
1146
+ if (!insideSnapshot(path.resolve(src))) {
1147
+ ancestor.copyFileSync(src, dest, flags);
1148
+ return;
1149
+ }
1150
+
1151
+ if (flags & fs.constants.COPYFILE_EXCL) {
1152
+ try {
1153
+ fs.statSync(dest);
1154
+ } catch (statError) {
1155
+ if (statError.code !== 'ENOENT') throw statError;
1156
+ copyInChunks(src, dest, DEFAULT_COPY_CHUNK_SIZE, fs);
1157
+ return;
1158
+ }
1159
+
1160
+ throw Object.assign(new Error('File already exists'), { code: 'EEXIST' });
1161
+ }
1162
+ copyInChunks(src, dest, DEFAULT_COPY_CHUNK_SIZE, fs);
1163
+ };
1164
+
1165
+ // ///////////////////////////////////////////////////////////////
1166
+ // writeFile /////////////////////////////////////////////////////
1167
+ // ///////////////////////////////////////////////////////////////
1168
+
1169
+ // writeFileSync based on openSync/writeSync/closeSync
1170
+ // writeFile based on open/write/close
1171
+
1172
+ // ///////////////////////////////////////////////////////////////
1173
+ // readdir ///////////////////////////////////////////////////////
1174
+ // ///////////////////////////////////////////////////////////////
1175
+
1176
+ function readdirOptions(options, hasCallback) {
1177
+ if (!options || (hasCallback && typeof options === 'function')) {
1178
+ return { encoding: null };
1179
+ }
1180
+ if (typeof options === 'string') {
1181
+ return { encoding: options };
1182
+ }
1183
+ if (typeof options === 'object') {
1184
+ return options;
1185
+ }
1186
+ return null;
1187
+ }
1188
+
1189
+ function Dirent(name, type) {
1190
+ this.name = name;
1191
+ this.type = type;
1192
+ }
1193
+
1194
+ Dirent.prototype.isDirectory = function isDirectory() {
1195
+ return this.type === 2;
1196
+ };
1197
+
1198
+ Dirent.prototype.isFile = function isFile() {
1199
+ return this.type === 1;
1200
+ };
1201
+
1202
+ const noop = () => false;
1203
+ Dirent.prototype.isBlockDevice = noop;
1204
+ Dirent.prototype.isCharacterDevice = noop;
1205
+ Dirent.prototype.isSocket = noop;
1206
+ Dirent.prototype.isFIFO = noop;
1207
+
1208
+ Dirent.prototype.isSymbolicLink = (fileOrFolderName) =>
1209
+ Boolean(SYMLINKS[fileOrFolderName]);
1210
+
1211
+ function getFileTypes(path_, entries) {
1212
+ return entries.map((entry) => {
1213
+ const ff = path.join(path_, entry);
1214
+ const entity = findVirtualFileSystemEntry(ff);
1215
+ if (!entity) return undefined;
1216
+ if (entity[STORE_BLOB] || entity[STORE_CONTENT])
1217
+ return new Dirent(entry, 1);
1218
+ if (entity[STORE_LINKS]) return new Dirent(entry, 2);
1219
+ throw new Error('UNEXPECTED-24');
1220
+ });
1221
+ }
1222
+
1223
+ function readdirRoot(path_, options, cb) {
1224
+ function addSnapshot(entries) {
1225
+ if (options && options.withFileTypes) {
1226
+ entries.push(new Dirent('snapshot', 2));
1227
+ } else {
1228
+ entries.push('snapshot');
1229
+ }
1230
+ }
1231
+
1232
+ if (cb) {
1233
+ ancestor.readdir(path_, options, (error, entries) => {
1234
+ if (error) return cb(error);
1235
+ addSnapshot(entries);
1236
+ cb(null, entries);
1237
+ });
1238
+ } else {
1239
+ const entries = ancestor.readdirSync(path_, options);
1240
+ addSnapshot(entries);
1241
+ return entries;
1242
+ }
1243
+ }
1244
+
1245
+ function readdirFromSnapshotSub(entityLinks, path_, cb) {
1246
+ if (cb) {
1247
+ payloadFile(entityLinks, (error, buffer) => {
1248
+ if (error) return cb(error);
1249
+ cb(null, JSON.parse(buffer).concat(readdirMountpoints(path_)));
1250
+ });
1251
+ } else {
1252
+ const buffer = payloadFileSync(entityLinks);
1253
+ return JSON.parse(buffer).concat(readdirMountpoints(path_));
1254
+ }
1255
+ }
1256
+
1257
+ function readdirFromSnapshot(path_, cb) {
1258
+ const cb2 = cb || rethrow;
1259
+ const entity = findVirtualFileSystemEntry(path_);
1260
+
1261
+ if (!entity) {
1262
+ return cb2(error_ENOENT('Directory', path_));
1263
+ }
1264
+
1265
+ const entityBlob = entity[STORE_BLOB];
1266
+ if (entityBlob) {
1267
+ return cb2(error_ENOTDIR(path_));
1268
+ }
1269
+
1270
+ const entityContent = entity[STORE_CONTENT];
1271
+ if (entityContent) {
1272
+ return cb2(error_ENOTDIR(path_));
1273
+ }
1274
+
1275
+ const entityLinks = entity[STORE_LINKS];
1276
+ if (entityLinks) {
1277
+ return readdirFromSnapshotSub(entityLinks, path_, cb);
1278
+ }
1279
+ return cb2(new Error('UNEXPECTED-25'));
1280
+ }
1281
+
1282
+ fs.readdirSync = function readdirSync(path_, options_) {
1283
+ const isRoot = isRootPath(path_);
1284
+
1285
+ if (!insideSnapshot(path_) && !isRoot) {
1286
+ return ancestor.readdirSync.apply(fs, arguments);
1287
+ }
1288
+
1289
+ if (insideMountpoint(path_)) {
1290
+ return ancestor.readdirSync.apply(fs, translateNth(arguments, 0, path_));
1291
+ }
1292
+
1293
+ const options = readdirOptions(options_, false);
1294
+
1295
+ if (isRoot) {
1296
+ return readdirRoot(path_, options);
1297
+ }
1298
+
1299
+ if (!options) {
1300
+ return ancestor.readdirSync.apply(fs, arguments);
1301
+ }
1302
+
1303
+ let entries = readdirFromSnapshot(path_);
1304
+ if (options.withFileTypes) entries = getFileTypes(path_, entries);
1305
+ return entries;
1306
+ };
1307
+
1308
+ fs.readdir = function readdir(path_, options_) {
1309
+ const isRoot = isRootPath(path_);
1310
+
1311
+ if (!insideSnapshot(path_) && !isRoot) {
1312
+ return ancestor.readdir.apply(fs, arguments);
1313
+ }
1314
+ if (insideMountpoint(path_)) {
1315
+ return ancestor.readdir.apply(fs, translateNth(arguments, 0, path_));
1316
+ }
1317
+
1318
+ const options = readdirOptions(options_, true);
1319
+ const callback = dezalgo(maybeCallback(arguments));
1320
+
1321
+ if (isRoot) {
1322
+ return readdirRoot(path_, options, callback);
1323
+ }
1324
+
1325
+ if (!options) {
1326
+ return ancestor.readdir.apply(fs, arguments);
1327
+ }
1328
+
1329
+ readdirFromSnapshot(path_, (error, entries) => {
1330
+ if (error) return callback(error);
1331
+ if (options.withFileTypes) entries = getFileTypes(path_, entries);
1332
+ callback(null, entries);
1333
+ });
1334
+ };
1335
+
1336
+ // ///////////////////////////////////////////////////////////////
1337
+ // realpath //////////////////////////////////////////////////////
1338
+ // ///////////////////////////////////////////////////////////////
1339
+
1340
+ fs.realpathSync = function realpathSync(path_) {
1341
+ if (!insideSnapshot(path_)) {
1342
+ return ancestor.realpathSync.apply(fs, arguments);
1343
+ }
1344
+ if (insideMountpoint(path_)) {
1345
+ // app should not know real file name
1346
+ return path_;
1347
+ }
1348
+
1349
+ const realPath = realpathFromSnapshot(path_);
1350
+ return realPath;
1351
+ };
1352
+
1353
+ fs.realpath = function realpath(path_) {
1354
+ if (!insideSnapshot(path_)) {
1355
+ return ancestor.realpath.apply(fs, arguments);
1356
+ }
1357
+ if (insideMountpoint(path_)) {
1358
+ // app should not know real file name
1359
+ return path_;
1360
+ }
1361
+
1362
+ const callback = dezalgo(maybeCallback(arguments));
1363
+ callback(null, realpathFromSnapshot(path_));
1364
+ };
1365
+
1366
+ fs.realpathSync.native = fs.realpathSync;
1367
+ fs.realpath.native = fs.realpath;
1368
+
1369
+ // ///////////////////////////////////////////////////////////////
1370
+ // stat //////////////////////////////////////////////////////////
1371
+ // ///////////////////////////////////////////////////////////////
1372
+
1373
+ function restore(s) {
1374
+ s.blksize = 4096;
1375
+ s.blocks = 0;
1376
+ s.dev = 0;
1377
+ s.gid = 20;
1378
+ s.ino = 0;
1379
+ s.nlink = 0;
1380
+ s.rdev = 0;
1381
+ s.uid = 500;
1382
+
1383
+ s.atime = new Date(EXECSTAT.atime);
1384
+ s.mtime = new Date(EXECSTAT.mtime);
1385
+ s.ctime = new Date(EXECSTAT.ctime);
1386
+ s.birthtime = new Date(EXECSTAT.birthtime);
1387
+
1388
+ s.atimeMs = EXECSTAT.atimeMs;
1389
+ s.mtimeMs = EXECSTAT.mtimeMs;
1390
+ s.ctimeMs = EXECSTAT.ctimeMs;
1391
+ s.birthtimeMs = EXECSTAT.birthtimeMs;
1392
+
1393
+ const { isFileValue } = s;
1394
+ const { isDirectoryValue } = s;
1395
+ const { isSocketValue } = s;
1396
+ const { isSymbolicLinkValue } = s;
1397
+
1398
+ delete s.isFileValue;
1399
+ delete s.isDirectoryValue;
1400
+ delete s.isSocketValue;
1401
+ delete s.isSymbolicLinkValue;
1402
+
1403
+ s.isBlockDevice = noop;
1404
+ s.isCharacterDevice = noop;
1405
+ s.isFile = function isFile() {
1406
+ return isFileValue;
1407
+ };
1408
+ s.isDirectory = function isDirectory() {
1409
+ return isDirectoryValue;
1410
+ };
1411
+ s.isSocket = function isSocket() {
1412
+ return isSocketValue;
1413
+ };
1414
+ s.isSymbolicLink = function isSymbolicLink() {
1415
+ return isSymbolicLinkValue;
1416
+ };
1417
+ s.isFIFO = noop;
1418
+
1419
+ return s;
1420
+ }
1421
+
1422
+ function findNativeAddonForStat(path_, cb) {
1423
+ const cb2 = cb || rethrow;
1424
+ const foundPath = findNativeAddonSyncUnderRequire(path_);
1425
+ if (!foundPath) return cb2(error_ENOENT('File or directory', path_));
1426
+ if (cb) {
1427
+ ancestor.stat.call(fs, foundPath, cb);
1428
+ } else {
1429
+ return ancestor.statSync.call(fs, foundPath);
1430
+ }
1431
+ }
1432
+
1433
+ function statFromSnapshotSub(entityStat, cb) {
1434
+ if (cb) {
1435
+ payloadFile(entityStat, (error, buffer) => {
1436
+ if (error) return cb(error);
1437
+ cb(null, restore(JSON.parse(buffer)));
1438
+ });
1439
+ } else {
1440
+ const buffer = payloadFileSync(entityStat);
1441
+ return restore(JSON.parse(buffer));
1442
+ }
1443
+ }
1444
+
1445
+ function statFromSnapshot(path_, cb) {
1446
+ const cb2 = cb || rethrow;
1447
+ const entity = findVirtualFileSystemEntry(path_);
1448
+ if (!entity) return findNativeAddonForStat(path_, cb);
1449
+ const entityStat = entity[STORE_STAT];
1450
+ if (entityStat) return statFromSnapshotSub(entityStat, cb);
1451
+ return cb2(new Error('UNEXPECTED-35'));
1452
+ }
1453
+
1454
+ fs.statSync = function statSync(path_) {
1455
+ if (!insideSnapshot(path_)) {
1456
+ return ancestor.statSync.apply(fs, arguments);
1457
+ }
1458
+ if (insideMountpoint(path_)) {
1459
+ return ancestor.statSync.apply(fs, translateNth(arguments, 0, path_));
1460
+ }
1461
+
1462
+ return statFromSnapshot(path_);
1463
+ };
1464
+
1465
+ fs.stat = function stat(path_) {
1466
+ if (!insideSnapshot(path_)) {
1467
+ return ancestor.stat.apply(fs, arguments);
1468
+ }
1469
+ if (insideMountpoint(path_)) {
1470
+ return ancestor.stat.apply(fs, translateNth(arguments, 0, path_));
1471
+ }
1472
+
1473
+ const callback = dezalgo(maybeCallback(arguments));
1474
+ statFromSnapshot(path_, callback);
1475
+ };
1476
+
1477
+ // ///////////////////////////////////////////////////////////////
1478
+ // lstat /////////////////////////////////////////////////////////
1479
+ // ///////////////////////////////////////////////////////////////
1480
+
1481
+ fs.lstatSync = function lstatSync(path_) {
1482
+ if (!insideSnapshot(path_)) {
1483
+ return ancestor.lstatSync.apply(fs, arguments);
1484
+ }
1485
+ if (insideMountpoint(path_)) {
1486
+ return ancestor.lstatSync.apply(fs, translateNth(arguments, 0, path_));
1487
+ }
1488
+
1489
+ return statFromSnapshot(path_);
1490
+ };
1491
+
1492
+ fs.lstat = function lstat(path_) {
1493
+ if (!insideSnapshot(path_)) {
1494
+ return ancestor.lstat.apply(fs, arguments);
1495
+ }
1496
+ if (insideMountpoint(path_)) {
1497
+ return ancestor.lstat.apply(fs, translateNth(arguments, 0, path_));
1498
+ }
1499
+
1500
+ const callback = dezalgo(maybeCallback(arguments));
1501
+ statFromSnapshot(path_, callback);
1502
+ };
1503
+
1504
+ // ///////////////////////////////////////////////////////////////
1505
+ // fstat /////////////////////////////////////////////////////////
1506
+ // ///////////////////////////////////////////////////////////////
1507
+
1508
+ function fstatFromSnapshot(fd, cb) {
1509
+ const cb2 = cb || rethrow;
1510
+ const { entity } = docks[fd];
1511
+ const entityStat = entity[STORE_STAT];
1512
+ if (entityStat) return statFromSnapshotSub(entityStat, cb);
1513
+ return cb2(new Error('UNEXPECTED-40'));
1514
+ }
1515
+
1516
+ fs.fstatSync = function fstatSync(fd) {
1517
+ if (!docks[fd]) {
1518
+ return ancestor.fstatSync.apply(fs, arguments);
1519
+ }
1520
+
1521
+ return fstatFromSnapshot(fd);
1522
+ };
1523
+
1524
+ fs.fstat = function fstat(fd) {
1525
+ if (!docks[fd]) {
1526
+ return ancestor.fstat.apply(fs, arguments);
1527
+ }
1528
+
1529
+ const callback = dezalgo(maybeCallback(arguments));
1530
+ fstatFromSnapshot(fd, callback);
1531
+ };
1532
+
1533
+ // ///////////////////////////////////////////////////////////////
1534
+ // exists ////////////////////////////////////////////////////////
1535
+ // ///////////////////////////////////////////////////////////////
1536
+
1537
+ function findNativeAddonForExists(path_) {
1538
+ const foundPath = findNativeAddonSyncFreeFromRequire(path_);
1539
+ if (!foundPath) return false;
1540
+ return ancestor.existsSync.call(fs, foundPath);
1541
+ }
1542
+
1543
+ function existsFromSnapshot(path_) {
1544
+ const entity = findVirtualFileSystemEntry(path_);
1545
+ if (!entity) return findNativeAddonForExists(path_);
1546
+ return true;
1547
+ }
1548
+
1549
+ fs.existsSync = function existsSync(path_) {
1550
+ if (!insideSnapshot(path_)) {
1551
+ return ancestor.existsSync.apply(fs, arguments);
1552
+ }
1553
+ if (insideMountpoint(path_)) {
1554
+ return ancestor.existsSync.apply(fs, translateNth(arguments, 0, path_));
1555
+ }
1556
+
1557
+ return existsFromSnapshot(path_);
1558
+ };
1559
+
1560
+ fs.exists = function exists(path_) {
1561
+ if (!insideSnapshot(path_)) {
1562
+ return ancestor.exists.apply(fs, arguments);
1563
+ }
1564
+ if (insideMountpoint(path_)) {
1565
+ return ancestor.exists.apply(fs, translateNth(arguments, 0, path_));
1566
+ }
1567
+
1568
+ const callback = dezalgo(maybeCallback(arguments));
1569
+ callback(existsFromSnapshot(path_));
1570
+ };
1571
+
1572
+ // ///////////////////////////////////////////////////////////////
1573
+ // access ////////////////////////////////////////////////////////
1574
+ // ///////////////////////////////////////////////////////////////
1575
+
1576
+ function accessFromSnapshot(path_, cb) {
1577
+ const cb2 = cb || rethrow;
1578
+ const entity = findVirtualFileSystemEntry(path_);
1579
+ if (!entity) return cb2(error_ENOENT('File or directory', path_));
1580
+ return cb2(null, undefined);
1581
+ }
1582
+
1583
+ fs.accessSync = function accessSync(path_) {
1584
+ if (!insideSnapshot(path_)) {
1585
+ return ancestor.accessSync.apply(fs, arguments);
1586
+ }
1587
+ if (insideMountpoint(path_)) {
1588
+ return ancestor.accessSync.apply(fs, translateNth(arguments, 0, path_));
1589
+ }
1590
+
1591
+ return accessFromSnapshot(path_);
1592
+ };
1593
+
1594
+ fs.access = function access(path_) {
1595
+ if (!insideSnapshot(path_)) {
1596
+ return ancestor.access.apply(fs, arguments);
1597
+ }
1598
+ if (insideMountpoint(path_)) {
1599
+ return ancestor.access.apply(fs, translateNth(arguments, 0, path_));
1600
+ }
1601
+
1602
+ const callback = dezalgo(maybeCallback(arguments));
1603
+ accessFromSnapshot(path_, callback);
1604
+ };
1605
+
1606
+ // ///////////////////////////////////////////////////////////////
1607
+ // mkdir /////////////////////////////////////////////////////////
1608
+ // ///////////////////////////////////////////////////////////////
1609
+
1610
+ function mkdirFailInSnapshot(path_, cb) {
1611
+ const cb2 = cb || rethrow;
1612
+ return cb2(
1613
+ new Error('Cannot mkdir in a snapshot. Try mountpoints instead.'),
1614
+ );
1615
+ }
1616
+
1617
+ fs.mkdirSync = function mkdirSync(path_) {
1618
+ if (!insideSnapshot(path_)) {
1619
+ return ancestor.mkdirSync.apply(fs, arguments);
1620
+ }
1621
+ if (insideMountpoint(path_)) {
1622
+ return ancestor.mkdirSync.apply(fs, translateNth(arguments, 0, path_));
1623
+ }
1624
+
1625
+ return mkdirFailInSnapshot(path_);
1626
+ };
1627
+
1628
+ fs.mkdir = function mkdir(path_) {
1629
+ if (!insideSnapshot(path_)) {
1630
+ return ancestor.mkdir.apply(fs, arguments);
1631
+ }
1632
+ if (insideMountpoint(path_)) {
1633
+ return ancestor.mkdir.apply(fs, translateNth(arguments, 0, path_));
1634
+ }
1635
+
1636
+ mkdirFailInSnapshot(path_, dezalgo(maybeCallback(arguments)));
1637
+ };
1638
+
1639
+ // ///////////////////////////////////////////////////////////////
1640
+ // promises ////////////////////////////////////////////////////////
1641
+ // ///////////////////////////////////////////////////////////////
1642
+
1643
+ if (fs.promises !== undefined) {
1644
+ const ancestor_promises = {
1645
+ open: fs.promises.open,
1646
+ read: fs.promises.read,
1647
+ write: fs.promises.write,
1648
+ readFile: fs.promises.readFile,
1649
+ readdir: fs.promises.readdir,
1650
+ realpath: fs.promises.realpath,
1651
+ stat: fs.promises.stat,
1652
+ lstat: fs.promises.lstat,
1653
+ fstat: fs.promises.fstat,
1654
+ access: fs.promises.access,
1655
+ copyFile: fs.promises.copyFile,
1656
+ };
1657
+
1658
+ fs.promises.open = async function open(path_) {
1659
+ if (!insideSnapshot(path_)) {
1660
+ return ancestor_promises.open.apply(this, arguments);
1661
+ }
1662
+ if (insideMountpoint(path_)) {
1663
+ return ancestor_promises.open.apply(
1664
+ this,
1665
+ translateNth(arguments, 0, path_),
1666
+ );
1667
+ }
1668
+ const externalFile = uncompressExternallyPath(path_);
1669
+ arguments[0] = externalFile;
1670
+ const fd = await ancestor_promises.open.apply(this, arguments);
1671
+ if (typeof fd === 'object') {
1672
+ fd._pkg = { externalFile, file: path_ };
1673
+ }
1674
+ return fd;
1675
+ };
1676
+ fs.promises.readFile = async function readFile(path_) {
1677
+ if (!insideSnapshot(path_)) {
1678
+ return ancestor_promises.readFile.apply(this, arguments);
1679
+ }
1680
+ if (insideMountpoint(path_)) {
1681
+ return ancestor_promises.readFile.apply(
1682
+ this,
1683
+ translateNth(arguments, 0, path_),
1684
+ );
1685
+ }
1686
+ const externalFile = uncompressExternallyPath(path_);
1687
+ arguments[0] = externalFile;
1688
+ return ancestor_promises.readFile.apply(this, arguments);
1689
+ };
1690
+
1691
+ fs.promises.write = async function write(fd) {
1692
+ if (fd._pkg) {
1693
+ throw new Error(
1694
+ `[PKG] Cannot write into Snapshot file : ${fd._pkg.file}`,
1695
+ );
1696
+ }
1697
+ return ancestor_promises.write.apply(this, arguments);
1698
+ };
1699
+
1700
+ // this one use promisify on purpose
1701
+ fs.promises.readdir = util.promisify(fs.readdir);
1702
+ fs.promises.copyFile = util.promisify(fs.copyFile);
1703
+ fs.promises.stat = util.promisify(fs.stat);
1704
+ fs.promises.lstat = util.promisify(fs.lstat);
1705
+
1706
+ fs.promises.read = util.promisify(fs.read);
1707
+ fs.promises.realpath = util.promisify(fs.realpath);
1708
+ fs.promises.fstat = util.promisify(fs.fstat);
1709
+ fs.promises.statfs = util.promisify(fs.statfs);
1710
+ fs.promises.access = util.promisify(fs.access);
1711
+
1712
+ // TODO: all promises methods that try to edit files in snapshot should throw
1713
+ // TODO implement missing methods
1714
+ // fs.promises.readlink ?
1715
+ // fs.promises.opendir ?
1716
+ }
1717
+
1718
+ // ///////////////////////////////////////////////////////////////
1719
+ // INTERNAL //////////////////////////////////////////////////////
1720
+ // ///////////////////////////////////////////////////////////////
1721
+
1722
+ function makeLong(f) {
1723
+ return path._makeLong(f);
1724
+ }
1725
+
1726
+ function revertMakingLong(f) {
1727
+ if (/^\\\\\?\\/.test(f)) return f.slice(4);
1728
+ return f;
1729
+ }
1730
+
1731
+ function findNativeAddonForInternalModuleStat(path_) {
1732
+ const fNative = findNativeAddonSyncUnderRequire(path_);
1733
+ if (!fNative) return -ENOENT;
1734
+ return process.binding('fs').internalModuleStat(makeLong(fNative));
1735
+ }
1736
+
1737
+ fs.internalModuleStat = function internalModuleStat(long) {
1738
+ // from node comments:
1739
+ // Used to speed up module loading. Returns 0 if the path refers to
1740
+ // a file, 1 when it's a directory or < 0 on error (usually -ENOENT).
1741
+ // The speedup comes from not creating thousands of Stat and Error objects.
1742
+
1743
+ const path_ = revertMakingLong(long);
1744
+
1745
+ if (!insideSnapshot(path_)) {
1746
+ return process.binding('fs').internalModuleStat(long);
1747
+ }
1748
+ if (insideMountpoint(path_)) {
1749
+ return process
1750
+ .binding('fs')
1751
+ .internalModuleStat(makeLong(translate(path_)));
1752
+ }
1753
+
1754
+ const entity = findVirtualFileSystemEntry(path_);
1755
+
1756
+ if (!entity) {
1757
+ return findNativeAddonForInternalModuleStat(path_);
1758
+ }
1759
+
1760
+ const entityBlob = entity[STORE_BLOB];
1761
+ if (entityBlob) {
1762
+ return 0;
1763
+ }
1764
+
1765
+ const entityContent = entity[STORE_CONTENT];
1766
+ if (entityContent) {
1767
+ return 0;
1768
+ }
1769
+
1770
+ const entityLinks = entity[STORE_LINKS];
1771
+ if (entityLinks) {
1772
+ return 1;
1773
+ }
1774
+
1775
+ return -ENOENT;
1776
+ };
1777
+
1778
+ fs.internalModuleReadJSON = function internalModuleReadJSON(long) {
1779
+ // from node comments:
1780
+ // Used to speed up module loading. Returns the contents of the file as
1781
+ // a string or undefined when the file cannot be opened. The speedup
1782
+ // comes from not creating Error objects on failure.
1783
+ // For newer node versions (after https://github.com/nodejs/node/pull/33229 ):
1784
+ // Returns an array [string, boolean].
1785
+ //
1786
+ const returnArray =
1787
+ (NODE_VERSION_MAJOR === 12 && NODE_VERSION_MINOR >= 19) ||
1788
+ (NODE_VERSION_MAJOR === 14 && NODE_VERSION_MINOR >= 5) ||
1789
+ NODE_VERSION_MAJOR >= 15;
1790
+
1791
+ const path_ = revertMakingLong(long);
1792
+ const bindingFs = process.binding('fs');
1793
+ const readFile = (
1794
+ bindingFs.internalModuleReadFile || bindingFs.internalModuleReadJSON
1795
+ ).bind(bindingFs);
1796
+ if (!insideSnapshot(path_)) {
1797
+ return readFile(long);
1798
+ }
1799
+ if (insideMountpoint(path_)) {
1800
+ return readFile(makeLong(translate(path_)));
1801
+ }
1802
+
1803
+ const entity = findVirtualFileSystemEntry(path_);
1804
+
1805
+ if (!entity) {
1806
+ return returnArray ? [undefined, false] : undefined;
1807
+ }
1808
+
1809
+ const entityContent = entity[STORE_CONTENT];
1810
+ if (!entityContent) {
1811
+ return returnArray ? [undefined, false] : undefined;
1812
+ }
1813
+ return returnArray
1814
+ ? [payloadFileSync(entityContent).toString(), true]
1815
+ : payloadFileSync(entityContent).toString();
1816
+ };
1817
+
1818
+ fs.internalModuleReadFile = fs.internalModuleReadJSON;
1819
+ })();
1820
+
1821
+ // /////////////////////////////////////////////////////////////////
1822
+ // PATCH MODULE ////////////////////////////////////////////////////
1823
+ // /////////////////////////////////////////////////////////////////
1824
+
1825
+ (() => {
1826
+ const ancestor = {
1827
+ require: Module.prototype.require,
1828
+ _compile: Module.prototype._compile,
1829
+ _resolveFilename: Module._resolveFilename,
1830
+ runMain: Module.runMain,
1831
+ };
1832
+
1833
+ Module.prototype.require = function require(path_) {
1834
+ try {
1835
+ return ancestor.require.apply(this, arguments);
1836
+ } catch (error) {
1837
+ if (
1838
+ (error.code === 'ENOENT' || error.code === 'MODULE_NOT_FOUND') &&
1839
+ !insideSnapshot(path_) &&
1840
+ !path.isAbsolute(path_)
1841
+ ) {
1842
+ if (!error.pkg) {
1843
+ error.pkg = true;
1844
+ error.message +=
1845
+ '\n' +
1846
+ '1) If you want to compile the package/file into ' +
1847
+ 'executable, please pay attention to compilation ' +
1848
+ "warnings and specify a literal in 'require' call. " +
1849
+ "2) If you don't want to compile the package/file " +
1850
+ "into executable and want to 'require' it from " +
1851
+ 'filesystem (likely plugin), specify an absolute ' +
1852
+ "path in 'require' call using process.cwd() or " +
1853
+ 'process.execPath.';
1854
+ }
1855
+ }
1856
+ throw error;
1857
+ }
1858
+ };
1859
+
1860
+ let im;
1861
+ let makeRequireFunction;
1862
+
1863
+ if (NODE_VERSION_MAJOR <= 9) {
1864
+ im = require('internal/module');
1865
+ makeRequireFunction = im.makeRequireFunction;
1866
+ } else {
1867
+ if (NODE_VERSION_MAJOR < 18) {
1868
+ im = require('internal/modules/cjs/helpers');
1869
+ } else {
1870
+ im = require('internal/modules/helpers');
1871
+ }
1872
+ makeRequireFunction = im.makeRequireFunction;
1873
+ // TODO esm modules along with cjs
1874
+ }
1875
+
1876
+ Module.prototype._compile = function _compile(content, filename_) {
1877
+ if (!insideSnapshot(filename_)) {
1878
+ return ancestor._compile.apply(this, arguments);
1879
+ }
1880
+ if (insideMountpoint(filename_)) {
1881
+ // DON'T TRANSLATE! otherwise __dirname gets real name
1882
+ return ancestor._compile.apply(this, arguments);
1883
+ }
1884
+
1885
+ const entity = findVirtualFileSystemEntry(filename_);
1886
+
1887
+ if (!entity) {
1888
+ // let user try to "_compile" a packaged file
1889
+ return ancestor._compile.apply(this, arguments);
1890
+ }
1891
+
1892
+ const entityBlob = entity[STORE_BLOB];
1893
+ const entityContent = entity[STORE_CONTENT];
1894
+
1895
+ if (entityBlob) {
1896
+ const options = {
1897
+ filename: filename_,
1898
+ lineOffset: 0,
1899
+ displayErrors: true,
1900
+ cachedData: payloadFileSync(entityBlob),
1901
+ sourceless: !entityContent,
1902
+ };
1903
+
1904
+ const code = entityContent
1905
+ ? Module.wrap(payloadFileSync(entityContent))
1906
+ : undefined;
1907
+
1908
+ const script = new Script(code, options);
1909
+ const wrapper = script.runInThisContext(options);
1910
+ if (!wrapper) process.exit(4); // for example VERSION_MISMATCH
1911
+ const dirname = path.dirname(filename_);
1912
+ const rqfn = makeRequireFunction(this);
1913
+ const args = [this.exports, rqfn, this, filename_, dirname];
1914
+ return wrapper.apply(this.exports, args);
1915
+ }
1916
+
1917
+ if (entityContent) {
1918
+ if (entityBlob) throw new Error('UNEXPECTED-50');
1919
+ // content is already in utf8 and without BOM (that is expected
1920
+ // by stock _compile), but entityContent is still a Buffer
1921
+ return ancestor._compile.apply(this, arguments);
1922
+ }
1923
+
1924
+ throw new Error('UNEXPECTED-55');
1925
+ };
1926
+
1927
+ Module._resolveFilename = function _resolveFilename() {
1928
+ let filename;
1929
+ let flagWasOn = false;
1930
+ try {
1931
+ filename = ancestor._resolveFilename.apply(this, arguments);
1932
+ } catch (error) {
1933
+ if (error.code !== 'MODULE_NOT_FOUND') throw error;
1934
+
1935
+ FLAG_ENABLE_PROJECT = true;
1936
+ const savePathCache = Module._pathCache;
1937
+ Module._pathCache = Object.create(null);
1938
+ try {
1939
+ filename = ancestor._resolveFilename.apply(this, arguments);
1940
+ flagWasOn = true;
1941
+ } finally {
1942
+ Module._pathCache = savePathCache;
1943
+ FLAG_ENABLE_PROJECT = false;
1944
+ }
1945
+ }
1946
+ if (!insideSnapshot(filename)) {
1947
+ return filename;
1948
+ }
1949
+ if (insideMountpoint(filename)) {
1950
+ return filename;
1951
+ }
1952
+
1953
+ if (flagWasOn) {
1954
+ FLAG_ENABLE_PROJECT = true;
1955
+ try {
1956
+ const found = findNativeAddonSyncUnderRequire(filename);
1957
+ if (found) filename = found;
1958
+ } finally {
1959
+ FLAG_ENABLE_PROJECT = false;
1960
+ }
1961
+ }
1962
+
1963
+ return filename;
1964
+ };
1965
+
1966
+ Module.runMain = function runMain() {
1967
+ Module._load(ENTRYPOINT, null, true);
1968
+ process._tickCallback();
1969
+ };
1970
+ })();
1971
+
1972
+ // /////////////////////////////////////////////////////////////////
1973
+ // PATCH CHILD_PROCESS /////////////////////////////////////////////
1974
+ // /////////////////////////////////////////////////////////////////
1975
+ (() => {
1976
+ const ancestor = {
1977
+ spawn: childProcess.spawn,
1978
+ spawnSync: childProcess.spawnSync,
1979
+ execFile: childProcess.execFile,
1980
+ execFileSync: childProcess.execFileSync,
1981
+ exec: childProcess.exec,
1982
+ execSync: childProcess.execSync,
1983
+ };
1984
+
1985
+ function setOptsEnv(args) {
1986
+ let pos = args.length - 1;
1987
+ if (typeof args[pos] === 'function') pos -= 1;
1988
+ if (typeof args[pos] !== 'object' || Array.isArray(args[pos])) {
1989
+ pos += 1;
1990
+ args.splice(pos, 0, {});
1991
+ }
1992
+ const opts = args[pos];
1993
+ if (!opts.env) opts.env = { ...process.env };
1994
+ // see https://github.com/vercel/pkg/issues/897#issuecomment-1049370335
1995
+ if (opts.env.PKG_EXECPATH !== undefined) return;
1996
+ opts.env.PKG_EXECPATH = EXECPATH;
1997
+ }
1998
+
1999
+ function startsWith2(args, index, name, impostor) {
2000
+ const qsName = `"${name} `;
2001
+ if (args[index].slice(0, qsName.length) === qsName) {
2002
+ args[index] = `"${impostor} ${args[index].slice(qsName.length)}`;
2003
+ return true;
2004
+ }
2005
+ const sName = `${name} `;
2006
+ if (args[index].slice(0, sName.length) === sName) {
2007
+ args[index] = `${impostor} ${args[index].slice(sName.length)}`;
2008
+ return true;
2009
+ }
2010
+ if (args[index] === name) {
2011
+ args[index] = impostor;
2012
+ return true;
2013
+ }
2014
+ return false;
2015
+ }
2016
+
2017
+ function startsWith(args, index, name) {
2018
+ const qName = `"${name}"`;
2019
+ const qEXECPATH = `"${EXECPATH}"`;
2020
+ const jsName = JSON.stringify(name);
2021
+ const jsEXECPATH = JSON.stringify(EXECPATH);
2022
+ return (
2023
+ startsWith2(args, index, name, EXECPATH) ||
2024
+ startsWith2(args, index, qName, qEXECPATH) ||
2025
+ startsWith2(args, index, jsName, jsEXECPATH)
2026
+ );
2027
+ }
2028
+
2029
+ function modifyLong(args, index) {
2030
+ if (!args[index]) return;
2031
+ return (
2032
+ startsWith(args, index, 'node') ||
2033
+ startsWith(args, index, ARGV0) ||
2034
+ startsWith(args, index, ENTRYPOINT) ||
2035
+ startsWith(args, index, EXECPATH)
2036
+ );
2037
+ }
2038
+
2039
+ function modifyShort(args) {
2040
+ if (!args[0]) return;
2041
+ if (!Array.isArray(args[1])) {
2042
+ args.splice(1, 0, []);
2043
+ }
2044
+ if (
2045
+ args[0] === 'node' ||
2046
+ args[0] === ARGV0 ||
2047
+ args[0] === ENTRYPOINT ||
2048
+ args[0] === EXECPATH
2049
+ ) {
2050
+ args[0] = EXECPATH;
2051
+ } else {
2052
+ for (let i = 1; i < args[1].length; i += 1) {
2053
+ const mbc = args[1][i - 1];
2054
+ if (mbc === '-c' || mbc === '/c') {
2055
+ modifyLong(args[1], i);
2056
+ }
2057
+ }
2058
+ }
2059
+ }
2060
+
2061
+ childProcess.spawn = function spawn() {
2062
+ const args = cloneArgs(arguments);
2063
+ setOptsEnv(args);
2064
+ modifyShort(args);
2065
+ return ancestor.spawn.apply(childProcess, args);
2066
+ };
2067
+
2068
+ childProcess.spawnSync = function spawnSync() {
2069
+ const args = cloneArgs(arguments);
2070
+ setOptsEnv(args);
2071
+ modifyShort(args);
2072
+ return ancestor.spawnSync.apply(childProcess, args);
2073
+ };
2074
+
2075
+ childProcess.execFile = function execFile() {
2076
+ const args = cloneArgs(arguments);
2077
+ setOptsEnv(args);
2078
+ modifyShort(args);
2079
+ return ancestor.execFile.apply(childProcess, args);
2080
+ };
2081
+
2082
+ childProcess.execFileSync = function execFileSync() {
2083
+ const args = cloneArgs(arguments);
2084
+ setOptsEnv(args);
2085
+ modifyShort(args);
2086
+ return ancestor.execFileSync.apply(childProcess, args);
2087
+ };
2088
+
2089
+ childProcess.exec = function exec() {
2090
+ const args = cloneArgs(arguments);
2091
+ setOptsEnv(args);
2092
+ modifyLong(args, 0);
2093
+ return ancestor.exec.apply(childProcess, args);
2094
+ };
2095
+
2096
+ childProcess.execSync = function execSync() {
2097
+ const args = cloneArgs(arguments);
2098
+ setOptsEnv(args);
2099
+ modifyLong(args, 0);
2100
+ return ancestor.execSync.apply(childProcess, args);
2101
+ };
2102
+ })();
2103
+
2104
+ // /////////////////////////////////////////////////////////////////
2105
+ // PROMISIFY ///////////////////////////////////////////////////////
2106
+ // /////////////////////////////////////////////////////////////////
2107
+ (() => {
2108
+ const { custom } = promisify;
2109
+ const { customPromisifyArgs } = require('internal/util');
2110
+
2111
+ // /////////////////////////////////////////////////////////////
2112
+ // FS //////////////////////////////////////////////////////////
2113
+ // /////////////////////////////////////////////////////////////
2114
+
2115
+ Object.defineProperty(fs.exists, custom, {
2116
+ value(path_) {
2117
+ return new Promise((resolve) => {
2118
+ fs.exists(path_, (exists) => {
2119
+ resolve(exists);
2120
+ });
2121
+ });
2122
+ },
2123
+ });
2124
+
2125
+ Object.defineProperty(fs.read, customPromisifyArgs, {
2126
+ value: ['bytesRead', 'buffer'],
2127
+ });
2128
+
2129
+ Object.defineProperty(fs.write, customPromisifyArgs, {
2130
+ value: ['bytesWritten', 'buffer'],
2131
+ });
2132
+
2133
+ // /////////////////////////////////////////////////////////////
2134
+ // CHILD_PROCESS ///////////////////////////////////////////////
2135
+ // /////////////////////////////////////////////////////////////
2136
+
2137
+ const customPromiseExecFunction =
2138
+ (o) =>
2139
+ (...args) => {
2140
+ let resolve;
2141
+ let reject;
2142
+ const p = new Promise((res, rej) => {
2143
+ resolve = res;
2144
+ reject = rej;
2145
+ });
2146
+
2147
+ p.child = o.apply(
2148
+ undefined,
2149
+ args.concat((error, stdout, stderr) => {
2150
+ if (error !== null) {
2151
+ error.stdout = stdout;
2152
+ error.stderr = stderr;
2153
+ reject(error);
2154
+ } else {
2155
+ resolve({ stdout, stderr });
2156
+ }
2157
+ }),
2158
+ );
2159
+
2160
+ return p;
2161
+ };
2162
+
2163
+ Object.defineProperty(childProcess.exec, custom, {
2164
+ value: customPromiseExecFunction(childProcess.exec),
2165
+ });
2166
+
2167
+ Object.defineProperty(childProcess.execFile, custom, {
2168
+ value: customPromiseExecFunction(childProcess.execFile),
2169
+ });
2170
+ })();
2171
+
2172
+ // /////////////////////////////////////////////////////////////////
2173
+ // PATCH PROCESS ///////////////////////////////////////////////////
2174
+ // /////////////////////////////////////////////////////////////////
2175
+ (() => {
2176
+ const ancestor = {
2177
+ dlopen: process.dlopen,
2178
+ };
2179
+
2180
+ // Native addon cache base directory.
2181
+ // Resolution order:
2182
+ // 1. HAKOBU_ADDON_CACHE env var (modern)
2183
+ // 2. PKG_NATIVE_CACHE_PATH env var (legacy compat)
2184
+ // 3. $HOME/.cache (default)
2185
+ // 4. os.tmpdir() (fallback when home is unavailable/unwritable)
2186
+ // Native addons will be extracted to: <base>/pkg/<hash>
2187
+ function resolveNativeCacheBase() {
2188
+ if (process.env.HAKOBU_ADDON_CACHE) return process.env.HAKOBU_ADDON_CACHE;
2189
+ if (process.env.PKG_NATIVE_CACHE_PATH) return process.env.PKG_NATIVE_CACHE_PATH;
2190
+ try {
2191
+ var home = homedir();
2192
+ if (home) {
2193
+ var cachePath = path.join(home, '.cache');
2194
+ fs.mkdirSync(cachePath, { recursive: true });
2195
+ return cachePath;
2196
+ }
2197
+ } catch (e) { /* home unavailable or unwritable */ }
2198
+ return os.tmpdir();
2199
+ }
2200
+ const PKG_NATIVE_CACHE_BASE = resolveNativeCacheBase();
2201
+
2202
+ function revertMakingLong(f) {
2203
+ if (/^\\\\\?\\/.test(f)) return f.slice(4);
2204
+ return f;
2205
+ }
2206
+
2207
+ process.dlopen = function dlopen() {
2208
+ const args = cloneArgs(arguments);
2209
+ const modulePath = revertMakingLong(args[1]);
2210
+ const moduleBaseName = path.basename(modulePath);
2211
+ const moduleFolder = path.dirname(modulePath);
2212
+
2213
+ if (insideSnapshot(modulePath)) {
2214
+ const moduleContent = fs.readFileSync(modulePath);
2215
+
2216
+ // Node addon files and .so cannot be read with fs directly, they are loaded with process.dlopen which needs a filesystem path
2217
+ // we need to write the file somewhere on disk first and then load it
2218
+ // the hash is needed to be sure we reload the module in case it changes
2219
+ const hash = createHash('sha256').update(moduleContent).digest('hex');
2220
+
2221
+ const tmpFolder = path.join(PKG_NATIVE_CACHE_BASE, 'pkg', hash);
2222
+
2223
+ fs.mkdirSync(tmpFolder, { recursive: true });
2224
+
2225
+ // Example: moduleFolder = /snapshot/appname/node_modules/sharp/build/Release
2226
+ const parts = moduleFolder.split(path.sep);
2227
+ const mIndex = parts.lastIndexOf('node_modules') + 1;
2228
+
2229
+ let newPath;
2230
+
2231
+ // it's a node addon file contained in node_modules folder
2232
+ // we copy the entire module folder in tmp folder
2233
+ if (mIndex > 0) {
2234
+ // Example: modulePackagePath = sharp/build/Release
2235
+ const modulePackagePath = parts.slice(mIndex).join(path.sep);
2236
+ // Example: modulePkgFolder = /snapshot/appname/node_modules/sharp
2237
+ const modulePkgFolder = parts.slice(0, mIndex + 1).join(path.sep);
2238
+
2239
+ // here we copy all files from the snapshot module folder to temporary folder
2240
+ // we keep the module folder structure to prevent issues with modules that are statically
2241
+ // linked using relative paths (Fix #1075)
2242
+ copyFolderRecursiveSync(modulePkgFolder, tmpFolder);
2243
+
2244
+ // Example: /tmp/pkg/<hash>/sharp/build/Release/sharp.node
2245
+ newPath = path.join(tmpFolder, modulePackagePath, moduleBaseName);
2246
+ } else {
2247
+ const tmpModulePath = path.join(tmpFolder, moduleBaseName);
2248
+
2249
+ if (!fs.existsSync(tmpModulePath)) {
2250
+ fs.copyFileSync(modulePath, tmpModulePath);
2251
+ }
2252
+
2253
+ // load the copied file in the temporary folder
2254
+ newPath = tmpModulePath;
2255
+ }
2256
+
2257
+ // replace the path with the new module path
2258
+ args[1] = newPath;
2259
+ }
2260
+
2261
+ return ancestor.dlopen.apply(process, args);
2262
+ };
2263
+ })();