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