git ssb

0+

cel-desktop / ssb-pkg



Tree: c5c7a8ffadbd51aa28a5f3f096fe43f69405da44

Files: c5c7a8ffadbd51aa28a5f3f096fe43f69405da44 / prelude / bootstrap.js

52601 bytesRaw
1/* eslint-disable curly */
2/* eslint-disable new-cap */
3/* eslint-disable no-buffer-constructor */
4/* eslint-disable no-multi-spaces */
5/* eslint-disable no-underscore-dangle */
6/* eslint-disable prefer-rest-params */
7/* eslint-disable prefer-spread */
8
9/* global EXECPATH_FD */
10/* global PAYLOAD_POSITION */
11/* global PAYLOAD_SIZE */
12/* global REQUIRE_COMMON */
13/* global VIRTUAL_FILESYSTEM */
14/* global DEFAULT_ENTRYPOINT */
15
16'use strict';
17
18var common = {};
19REQUIRE_COMMON(common);
20
21var STORE_BLOB = common.STORE_BLOB;
22var STORE_CONTENT = common.STORE_CONTENT;
23var STORE_LINKS = common.STORE_LINKS;
24var STORE_STAT = common.STORE_STAT;
25
26var isRootPath = common.isRootPath;
27var normalizePath = common.normalizePath;
28var insideSnapshot = common.insideSnapshot;
29var stripSnapshot = common.stripSnapshot;
30var removeUplevels = common.removeUplevels;
31
32var FLAG_ENABLE_PROJECT = false;
33var NODE_VERSION_MAJOR = process.version.match(/^v(\d+)/)[1] | 0;
34
35// /////////////////////////////////////////////////////////////////
36// ENTRYPOINT //////////////////////////////////////////////////////
37// /////////////////////////////////////////////////////////////////
38
39// set ENTRYPOINT and ARGV0 here because
40// they can be altered during process run
41var ARGV0 = process.argv[0];
42var EXECPATH = process.execPath;
43var ENTRYPOINT = process.argv[1];
44
45if (process.env.PKG_EXECPATH === 'PKG_INVOKE_NODEJS') {
46 return { undoPatch: true };
47}
48
49if (NODE_VERSION_MAJOR < 12 || require('worker_threads').isMainThread) {
50 if (process.argv[1] !== 'PKG_DUMMY_ENTRYPOINT') {
51 // expand once patchless is introduced, that
52 // will obviously lack any work in node_main.cc
53 throw new Error('PKG_DUMMY_ENTRYPOINT EXPECTED');
54 }
55}
56
57if (process.env.PKG_EXECPATH === EXECPATH) {
58 process.argv.splice(1, 1);
59
60 if (process.argv[1] && process.argv[1] !== '-') {
61 // https://github.com/nodejs/node/blob/1a96d83a223ff9f05f7d942fb84440d323f7b596/lib/internal/bootstrap/node.js#L269
62 process.argv[1] = require('path').resolve(process.argv[1]);
63 }
64} else {
65 process.argv[1] = DEFAULT_ENTRYPOINT;
66}
67
68ENTRYPOINT = process.argv[1];
69delete process.env.PKG_EXECPATH;
70
71if (process.env.PKG_ENTRYPOINT) {
72 ENTRYPOINT = process.env.PKG_ENTRYPOINT;
73 delete process.env.PKG_ENTRYPOINT;
74}
75
76// /////////////////////////////////////////////////////////////////
77// EXECSTAT ////////////////////////////////////////////////////////
78// /////////////////////////////////////////////////////////////////
79
80var EXECSTAT = require('fs').statSync(EXECPATH);
81EXECSTAT.atimeMs = EXECSTAT.atime.getTime();
82EXECSTAT.mtimeMs = EXECSTAT.mtime.getTime();
83EXECSTAT.ctimeMs = EXECSTAT.ctime.getTime();
84EXECSTAT.birthtimeMs = EXECSTAT.birthtime.getTime();
85
86// /////////////////////////////////////////////////////////////////
87// MOUNTPOINTS /////////////////////////////////////////////////////
88// /////////////////////////////////////////////////////////////////
89
90var mountpoints = [];
91
92function insideMountpoint (f) {
93 if (!insideSnapshot(f)) return null;
94 var file = normalizePath(f);
95 var found = mountpoints.map(function (mountpoint) {
96 var interior = mountpoint.interior;
97 var exterior = mountpoint.exterior;
98 if (interior === file) return exterior;
99 var left = interior + require('path').sep;
100 if (file.slice(0, left.length) !== left) return null;
101 return exterior + file.slice(left.length - 1);
102 }).filter(function (result) {
103 return result;
104 });
105 if (found.length >= 2) throw new Error('UNEXPECTED-00');
106 if (found.length === 0) return null;
107 return found[0];
108}
109
110function readdirMountpoints (path) {
111 return mountpoints.map(function (mountpoint) {
112 return mountpoint.interior;
113 }).filter(function (interior) {
114 return require('path').dirname(interior) === path;
115 }).map(function (interior) {
116 return require('path').basename(interior);
117 });
118}
119
120function translate (f) {
121 var result = insideMountpoint(f);
122 if (!result) throw new Error('UNEXPECTED-05');
123 return result;
124}
125
126function cloneArgs (args_) {
127 return Array.prototype.slice.call(args_);
128}
129
130function translateNth (args_, index, f) {
131 var args = cloneArgs(args_);
132 args[index] = translate(f);
133 return args;
134}
135
136function createMountpoint (interior, exterior) {
137 // TODO validate
138 mountpoints.push({ interior: interior, exterior: exterior });
139}
140
141/*
142
143// TODO move to some test
144
145createMountpoint("d:\\snapshot\\countly\\plugins-ext", "d:\\deploy\\countly\\v16.02\\plugins-ext");
146
147console.log(insideMountpoint("d:\\snapshot"));
148console.log(insideMountpoint("d:\\snapshot\\"));
149console.log(insideMountpoint("d:\\snapshot\\countly"));
150console.log(insideMountpoint("d:\\snapshot\\countly\\"));
151console.log(insideMountpoint("d:\\snapshot\\countly\\plugins-ext"));
152console.log(insideMountpoint("d:\\snapshot\\countly\\plugins-ext\\"));
153console.log(insideMountpoint("d:\\snapshot\\countly\\plugins-ext\\1234"));
154
155console.log(translate("d:\\snapshot\\countly\\plugins-ext"));
156console.log(translate("d:\\snapshot\\countly\\plugins-ext\\"));
157console.log(translate("d:\\snapshot\\countly\\plugins-ext\\1234"));
158
159console.log(translateNth([], 0, "d:\\snapshot\\countly\\plugins-ext"));
160console.log(translateNth([], 0, "d:\\snapshot\\countly\\plugins-ext\\"));
161console.log(translateNth([], 0, "d:\\snapshot\\countly\\plugins-ext\\1234"));
162
163console.log(translateNth(["", "r+"], 0, "d:\\snapshot\\countly\\plugins-ext"));
164console.log(translateNth(["", "rw"], 0, "d:\\snapshot\\countly\\plugins-ext\\"));
165console.log(translateNth(["", "a+"], 0, "d:\\snapshot\\countly\\plugins-ext\\1234"));
166*/
167
168// /////////////////////////////////////////////////////////////////
169// PROJECT /////////////////////////////////////////////////////////
170// /////////////////////////////////////////////////////////////////
171
172function projectToFilesystem (f) {
173 var xpdn = require('path').dirname(
174 EXECPATH
175 );
176
177 var relatives = [];
178 relatives.push(
179 removeUplevels(
180 require('path').relative(
181 require('path').dirname(
182 DEFAULT_ENTRYPOINT
183 ), f
184 )
185 )
186 );
187
188 if (relatives[0].slice(0, 'node_modules'.length) === 'node_modules') {
189 // one more relative without starting 'node_modules'
190 relatives.push(relatives[0].slice('node_modules'.length + 1));
191 }
192
193 var uplevels = [];
194 var maxUplevels = xpdn.split(require('path').sep).length;
195 for (var i = 0, u = ''; i < maxUplevels; i += 1) {
196 uplevels.push(u);
197 u += '/..';
198 }
199
200 var results = [];
201 uplevels.forEach(function (uplevel) {
202 relatives.forEach(function (relative) {
203 results.push(require('path').join(
204 xpdn,
205 uplevel,
206 relative
207 ));
208 });
209 });
210 return results;
211}
212
213function projectToNearby (f) {
214 return require('path').join(
215 require('path').dirname(
216 EXECPATH
217 ),
218 require('path').basename(
219 f
220 )
221 );
222}
223
224function findNativeAddonSyncFreeFromRequire (path) {
225 if (!insideSnapshot(path)) throw new Error('UNEXPECTED-10');
226 if (path.slice(-5) !== '.node') return null; // leveldown.node.js
227 // check mearby first to prevent .node tampering
228 var projector = projectToNearby(path);
229 if (require('fs').existsSync(projector)) return projector;
230 var projectors = projectToFilesystem(path);
231 for (var i = 0; i < projectors.length; i += 1) {
232 if (require('fs').existsSync(projectors[i])) return projectors[i];
233 }
234 return null;
235}
236
237function findNativeAddonSyncUnderRequire (path) {
238 if (!FLAG_ENABLE_PROJECT) return null;
239 return findNativeAddonSyncFreeFromRequire(path);
240}
241
242// /////////////////////////////////////////////////////////////////
243// FLOW UTILS //////////////////////////////////////////////////////
244// /////////////////////////////////////////////////////////////////
245
246function asap (cb) {
247 process.nextTick(cb);
248}
249
250function dezalgo (cb) {
251 if (!cb) return cb;
252
253 var sync = true;
254 asap(function () {
255 sync = false;
256 });
257
258 return function zalgoSafe () {
259 var args = arguments;
260 if (sync) {
261 asap(function () {
262 cb.apply(undefined, args);
263 });
264 } else {
265 cb.apply(undefined, args);
266 }
267 };
268}
269
270function rethrow (error, arg) {
271 if (error) throw error;
272 return arg;
273}
274
275// /////////////////////////////////////////////////////////////////
276// PAYLOAD /////////////////////////////////////////////////////////
277// /////////////////////////////////////////////////////////////////
278
279if (typeof PAYLOAD_POSITION !== 'number' ||
280 typeof PAYLOAD_SIZE !== 'number') {
281 throw new Error('MUST HAVE PAYLOAD');
282}
283
284var readPayload = function (buffer, offset, length, position, callback) {
285 require('fs').read(EXECPATH_FD,
286 buffer, offset, length, PAYLOAD_POSITION + position, callback);
287};
288
289var readPayloadSync = function (buffer, offset, length, position) {
290 return require('fs').readSync(EXECPATH_FD,
291 buffer, offset, length, PAYLOAD_POSITION + position);
292};
293
294function payloadCopyUni (source, target, targetStart, sourceStart, sourceEnd, cb) {
295 var cb2 = cb || rethrow;
296 if (sourceStart >= source[1]) return cb2(null, 0);
297 if (sourceEnd >= source[1]) sourceEnd = source[1];
298 var payloadPos = source[0] + sourceStart;
299 var targetPos = targetStart;
300 var targetEnd = targetStart + sourceEnd - sourceStart;
301 if (cb) {
302 readPayload(target, targetPos, targetEnd - targetPos, payloadPos, cb);
303 } else {
304 return readPayloadSync(target, targetPos, targetEnd - targetPos, payloadPos);
305 }
306}
307
308function payloadCopyMany (source, target, targetStart, sourceStart, cb) {
309 var payloadPos = source[0] + sourceStart;
310 var targetPos = targetStart;
311 var targetEnd = targetStart + source[1] - sourceStart;
312 readPayload(target, targetPos, targetEnd - targetPos, payloadPos, function (error, chunkSize) {
313 if (error) return cb(error);
314 sourceStart += chunkSize;
315 targetPos += chunkSize;
316 if (chunkSize !== 0 && targetPos < targetEnd) {
317 payloadCopyMany(source, target, targetPos, sourceStart, cb);
318 } else {
319 return cb();
320 }
321 });
322}
323
324function payloadCopyManySync (source, target, targetStart, sourceStart) {
325 var payloadPos = source[0] + sourceStart;
326 var targetPos = targetStart;
327 var targetEnd = targetStart + source[1] - sourceStart;
328 var chunkSize;
329 while (true) {
330 chunkSize = readPayloadSync(target, targetPos, targetEnd - targetPos, payloadPos);
331 payloadPos += chunkSize;
332 targetPos += chunkSize;
333 if (!(chunkSize !== 0 && targetPos < targetEnd)) break;
334 }
335}
336
337function payloadFile (pointer, cb) {
338 var target = Buffer.alloc(pointer[1]);
339 payloadCopyMany(pointer, target, 0, 0, function (error) {
340 if (error) return cb(error);
341 cb(null, target);
342 });
343}
344
345function payloadFileSync (pointer) {
346 var target = Buffer.alloc(pointer[1]);
347 payloadCopyManySync(pointer, target, 0, 0);
348 return target;
349}
350
351// /////////////////////////////////////////////////////////////////
352// SETUP PROCESS ///////////////////////////////////////////////////
353// /////////////////////////////////////////////////////////////////
354
355(function () {
356 process.pkg = {};
357 process.versions.pkg = '%VERSION%';
358 process.pkg.mount = createMountpoint;
359 process.pkg.entrypoint = ENTRYPOINT;
360 process.pkg.defaultEntrypoint = DEFAULT_ENTRYPOINT;
361}());
362
363// /////////////////////////////////////////////////////////////////
364// PATH.RESOLVE REPLACEMENT ////////////////////////////////////////
365// /////////////////////////////////////////////////////////////////
366
367(function () {
368 var path = require('path');
369
370 process.pkg.path = {};
371 process.pkg.path.resolve = function () {
372 var args = cloneArgs(arguments);
373 args.unshift(path.dirname(ENTRYPOINT));
374 return path.resolve.apply(path, args); // eslint-disable-line prefer-spread
375 };
376}());
377
378// /////////////////////////////////////////////////////////////////
379// PATCH FS ////////////////////////////////////////////////////////
380// /////////////////////////////////////////////////////////////////
381
382(function () {
383 var fs = require('fs');
384 var ancestor = {};
385 ancestor.openSync = fs.openSync;
386 ancestor.open = fs.open;
387 ancestor.readSync = fs.readSync;
388 ancestor.read = fs.read;
389 ancestor.writeSync = fs.writeSync;
390 ancestor.write = fs.write;
391 ancestor.closeSync = fs.closeSync;
392 ancestor.close = fs.close;
393 ancestor.readFileSync = fs.readFileSync;
394 ancestor.readFile = fs.readFile;
395 // ancestor.writeFileSync = fs.writeFileSync; // based on openSync/writeSync/closeSync
396 // ancestor.writeFile = fs.writeFile; // based on open/write/close
397 ancestor.readdirSync = fs.readdirSync;
398 ancestor.readdir = fs.readdir;
399 ancestor.realpathSync = fs.realpathSync;
400 ancestor.realpath = fs.realpath;
401 ancestor.statSync = fs.statSync;
402 ancestor.stat = fs.stat;
403 ancestor.lstatSync = fs.lstatSync;
404 ancestor.lstat = fs.lstat;
405 ancestor.fstatSync = fs.fstatSync;
406 ancestor.fstat = fs.fstat;
407 ancestor.existsSync = fs.existsSync;
408 ancestor.exists = fs.exists;
409 ancestor.accessSync = fs.accessSync;
410 ancestor.access = fs.access;
411
412 var windows = process.platform === 'win32';
413
414 var docks = {};
415 var ENOTDIR = windows ? 4052 : 20;
416 var ENOENT = windows ? 4058 : 2;
417 var EISDIR = windows ? 4068 : 21;
418
419 function assertEncoding (encoding) {
420 if (encoding && !Buffer.isEncoding(encoding)) {
421 throw new Error('Unknown encoding: ' + encoding);
422 }
423 }
424
425 function maybeCallback (args) {
426 var cb = args[args.length - 1];
427 return typeof cb === 'function' ? cb : rethrow;
428 }
429
430 function error_ENOENT (fileOrDirectory, path) { // eslint-disable-line camelcase
431 var error = new Error(
432 fileOrDirectory + ' \'' + stripSnapshot(path) + '\' ' +
433 'was not included into executable at compilation stage. ' +
434 'Please recompile adding it as asset or script.'
435 );
436 error.errno = -ENOENT;
437 error.code = 'ENOENT';
438 error.path = path;
439 error.pkg = true;
440 return error;
441 }
442
443 function error_EISDIR (path) { // eslint-disable-line camelcase
444 var error = new Error(
445 'EISDIR: illegal operation on a directory, read'
446 );
447 error.errno = -EISDIR;
448 error.code = 'EISDIR';
449 error.path = path;
450 error.pkg = true;
451 return error;
452 }
453
454 function error_ENOTDIR (path) { // eslint-disable-line camelcase
455 var error = new Error(
456 'ENOTDIR: not a directory, scandir \'' + path + '\''
457 );
458 error.errno = -ENOTDIR;
459 error.code = 'ENOTDIR';
460 error.path = path;
461 error.pkg = true;
462 return error;
463 }
464
465 // ///////////////////////////////////////////////////////////////
466 // open //////////////////////////////////////////////////////////
467 // ///////////////////////////////////////////////////////////////
468
469 function openFromSnapshot (path_, cb) {
470 var cb2 = cb || rethrow;
471 var path = normalizePath(path_);
472 // console.log("openFromSnapshot", path);
473 var entity = VIRTUAL_FILESYSTEM[path];
474 if (!entity) return cb2(error_ENOENT('File or directory', path));
475 var dock = { path: path, entity: entity, position: 0 };
476 var nullDevice = windows ? '\\\\.\\NUL' : '/dev/null';
477 if (cb) {
478 ancestor.open.call(fs, nullDevice, 'r', function (error, fd) {
479 if (error) return cb(error);
480 docks[fd] = dock;
481 cb(null, fd);
482 });
483 } else {
484 var fd = ancestor.openSync.call(fs, nullDevice, 'r');
485 docks[fd] = dock;
486 return fd;
487 }
488 }
489
490 fs.openSync = function (path) {
491 if (!insideSnapshot(path)) {
492 return ancestor.openSync.apply(fs, arguments);
493 }
494 if (insideMountpoint(path)) {
495 return ancestor.openSync.apply(fs, translateNth(arguments, 0, path));
496 }
497
498 return openFromSnapshot(path);
499 };
500
501 fs.open = function (path) {
502 if (!insideSnapshot(path)) {
503 return ancestor.open.apply(fs, arguments);
504 }
505 if (insideMountpoint(path)) {
506 return ancestor.open.apply(fs, translateNth(arguments, 0, path));
507 }
508
509 var callback = dezalgo(maybeCallback(arguments));
510 openFromSnapshot(path, callback);
511 };
512
513 // ///////////////////////////////////////////////////////////////
514 // read //////////////////////////////////////////////////////////
515 // ///////////////////////////////////////////////////////////////
516
517 function readFromSnapshotSub (entityContent, dock, buffer, offset, length, position, cb) {
518 var p;
519 if ((position !== null) && (position !== undefined)) {
520 p = position;
521 } else {
522 p = dock.position;
523 }
524 if (cb) {
525 payloadCopyUni(entityContent, buffer, offset, p, p + length, function (error, bytesRead, buffer2) {
526 if (error) return cb(error);
527 dock.position = p + bytesRead;
528 cb(null, bytesRead, buffer2);
529 });
530 } else {
531 var bytesRead = payloadCopyUni(entityContent, buffer, offset, p, p + length);
532 dock.position = p + bytesRead;
533 return bytesRead;
534 }
535 }
536
537 function readFromSnapshot (fd, buffer, offset, length, position, cb) {
538 var cb2 = cb || rethrow;
539 if ((offset < 0) && (NODE_VERSION_MAJOR >= 10)) return cb2(new Error(
540 'The value of "offset" is out of range. It must be >= 0 && <= ' + buffer.length.toString() + '. Received ' + offset));
541 if (offset < 0) return cb2(new Error('Offset is out of bounds'));
542 if ((offset >= buffer.length) && (NODE_VERSION_MAJOR >= 6)) return cb2(null, 0);
543 if (offset >= buffer.length) return cb2(new Error('Offset is out of bounds'));
544 if ((offset + length > buffer.length) && (NODE_VERSION_MAJOR >= 10)) return cb2(new Error(
545 'The value of "length" is out of range. It must be >= 0 && <= ' + (buffer.length - offset).toString() + '. Received ' + length.toString()));
546 if (offset + length > buffer.length) return cb2(new Error('Length extends beyond buffer'));
547
548 var dock = docks[fd];
549 var entity = dock.entity;
550 var entityLinks = entity[STORE_LINKS];
551 if (entityLinks) return cb2(error_EISDIR(dock.path));
552 var entityContent = entity[STORE_CONTENT];
553 if (entityContent) return readFromSnapshotSub(entityContent, dock, buffer, offset, length, position, cb);
554 return cb2(new Error('UNEXPECTED-15'));
555 }
556
557 fs.readSync = function (fd, buffer, offset, length, position) {
558 if (!docks[fd]) {
559 return ancestor.readSync.apply(fs, arguments);
560 }
561
562 return readFromSnapshot(fd, buffer, offset, length, position);
563 };
564
565 fs.read = function (fd, buffer, offset, length, position) {
566 if (!docks[fd]) {
567 return ancestor.read.apply(fs, arguments);
568 }
569
570 var callback = dezalgo(maybeCallback(arguments));
571 readFromSnapshot(fd, buffer, offset, length, position, callback);
572 };
573
574 // ///////////////////////////////////////////////////////////////
575 // write /////////////////////////////////////////////////////////
576 // ///////////////////////////////////////////////////////////////
577
578 function writeToSnapshot (cb) {
579 var cb2 = cb || rethrow;
580 return cb2(new Error('Cannot write to packaged file'));
581 }
582
583 fs.writeSync = function (fd) {
584 if (!docks[fd]) {
585 return ancestor.writeSync.apply(fs, arguments);
586 }
587
588 return writeToSnapshot();
589 };
590
591 fs.write = function (fd) {
592 if (!docks[fd]) {
593 return ancestor.write.apply(fs, arguments);
594 }
595
596 var callback = dezalgo(maybeCallback(arguments));
597 writeToSnapshot(callback);
598 };
599
600 // ///////////////////////////////////////////////////////////////
601 // close /////////////////////////////////////////////////////////
602 // ///////////////////////////////////////////////////////////////
603
604 function closeFromSnapshot (fd, cb) {
605 delete docks[fd];
606 if (cb) {
607 ancestor.close.call(fs, fd, cb);
608 } else {
609 return ancestor.closeSync.call(fs, fd);
610 }
611 }
612
613 fs.closeSync = function (fd) {
614 if (!docks[fd]) {
615 return ancestor.closeSync.apply(fs, arguments);
616 }
617
618 return closeFromSnapshot(fd);
619 };
620
621 fs.close = function (fd) {
622 if (!docks[fd]) {
623 return ancestor.close.apply(fs, arguments);
624 }
625
626 var callback = dezalgo(maybeCallback(arguments));
627 closeFromSnapshot(fd, callback);
628 };
629
630 // ///////////////////////////////////////////////////////////////
631 // readFile //////////////////////////////////////////////////////
632 // ///////////////////////////////////////////////////////////////
633
634 function readFileOptions (options, hasCallback) {
635 if (!options || (hasCallback && typeof options === 'function')) {
636 return { encoding: null, flag: 'r' };
637 } else if (typeof options === 'string') {
638 return { encoding: options, flag: 'r' };
639 } else if (typeof options === 'object') {
640 return options;
641 } else {
642 return null;
643 }
644 }
645
646 function readFileFromSnapshotSub (entityContent, cb) {
647 if (cb) {
648 payloadFile(entityContent, cb);
649 } else {
650 return payloadFileSync(entityContent);
651 }
652 }
653
654 function readFileFromSnapshot (path_, cb) {
655 var cb2 = cb || rethrow;
656 var path = normalizePath(path_);
657 // console.log("readFileFromSnapshot", path);
658 var entity = VIRTUAL_FILESYSTEM[path];
659 if (!entity) return cb2(error_ENOENT('File', path));
660 var entityLinks = entity[STORE_LINKS];
661 if (entityLinks) return cb2(error_EISDIR(path));
662 var entityContent = entity[STORE_CONTENT];
663 if (entityContent) return readFileFromSnapshotSub(entityContent, cb);
664 var entityBlob = entity[STORE_BLOB];
665 if (entityBlob) return cb2(null, Buffer.from('source-code-not-available'));
666
667 // why return empty buffer?
668 // otherwise this error will arise:
669 // Error: UNEXPECTED-20
670 // at readFileFromSnapshot (e:0)
671 // at Object.fs.readFileSync (e:0)
672 // at Object.Module._extensions..js (module.js:421:20)
673 // at Module.load (module.js:357:32)
674 // at Function.Module._load (module.js:314:12)
675 // at Function.Module.runMain (e:0)
676 // at startup (node.js:140:18)
677 // at node.js:1001:3
678
679 return cb2(new Error('UNEXPECTED-20'));
680 }
681
682 fs.readFileSync = function (path, options_) {
683 if (path === 'dirty-hack-for-testing-purposes') {
684 return path;
685 }
686
687 if (!insideSnapshot(path)) {
688 return ancestor.readFileSync.apply(fs, arguments);
689 }
690 if (insideMountpoint(path)) {
691 return ancestor.readFileSync.apply(fs, translateNth(arguments, 0, path));
692 }
693
694 var options = readFileOptions(options_, false);
695
696 if (!options) {
697 return ancestor.readFileSync.apply(fs, arguments);
698 }
699
700 var encoding = options.encoding;
701 assertEncoding(encoding);
702
703 var buffer = readFileFromSnapshot(path);
704 if (encoding) buffer = buffer.toString(encoding);
705 return buffer;
706 };
707
708 fs.readFile = function (path, options_) {
709 if (!insideSnapshot(path)) {
710 return ancestor.readFile.apply(fs, arguments);
711 }
712 if (insideMountpoint(path)) {
713 return ancestor.readFile.apply(fs, translateNth(arguments, 0, path));
714 }
715
716 var options = readFileOptions(options_, true);
717
718 if (!options) {
719 return ancestor.readFile.apply(fs, arguments);
720 }
721
722 var encoding = options.encoding;
723 assertEncoding(encoding);
724
725 var callback = dezalgo(maybeCallback(arguments));
726 readFileFromSnapshot(path, function (error, buffer) {
727 if (error) return callback(error);
728 if (encoding) buffer = buffer.toString(encoding);
729 callback(null, buffer);
730 });
731 };
732
733 // ///////////////////////////////////////////////////////////////
734 // writeFile /////////////////////////////////////////////////////
735 // ///////////////////////////////////////////////////////////////
736
737 // writeFileSync based on openSync/writeSync/closeSync
738 // writeFile based on open/write/close
739
740 // ///////////////////////////////////////////////////////////////
741 // readdir ///////////////////////////////////////////////////////
742 // ///////////////////////////////////////////////////////////////
743
744 function readdirOptions (options, hasCallback) {
745 if (!options || (hasCallback && typeof options === 'function')) {
746 return { encoding: null };
747 } else if (typeof options === 'string') {
748 return { encoding: options };
749 } else if (typeof options === 'object') {
750 return options;
751 } else {
752 return null;
753 }
754 }
755
756 function Dirent (name, type) {
757 this.name = name;
758 this.type = type;
759 }
760
761 Dirent.prototype.isDirectory = function () {
762 return this.type === 2;
763 };
764
765 Dirent.prototype.isFile = function () {
766 return this.type === 1;
767 };
768
769 Dirent.prototype.isBlockDevice =
770 Dirent.prototype.isCharacterDevice =
771 Dirent.prototype.isSymbolicLink =
772 Dirent.prototype.isFIFO =
773 Dirent.prototype.isSocket = function () {
774 return false;
775 };
776
777 function getFileTypes (path_, entries) {
778 return entries.map(function (entry) {
779 var path = require('path').join(path_, entry);
780 var entity = VIRTUAL_FILESYSTEM[path];
781 if (entity[STORE_BLOB] || entity[STORE_CONTENT]) return new Dirent(entry, 1);
782 if (entity[STORE_LINKS]) return new Dirent(entry, 2);
783 throw new Error('UNEXPECTED-24');
784 });
785 }
786
787 function readdirRoot (path, cb) {
788 if (cb) {
789 ancestor.readdir(path, function (error, entries) {
790 if (error) return cb(error);
791 entries.push('snapshot');
792 cb(null, entries);
793 });
794 } else {
795 var entries = ancestor.readdirSync(path);
796 entries.push('snapshot');
797 return entries;
798 }
799 }
800
801 function readdirFromSnapshotSub (entityLinks, path, cb) {
802 if (cb) {
803 payloadFile(entityLinks, function (error, buffer) {
804 if (error) return cb(error);
805 cb(null, JSON.parse(buffer).concat(readdirMountpoints(path)));
806 });
807 } else {
808 var buffer = payloadFileSync(entityLinks);
809 return JSON.parse(buffer).concat(readdirMountpoints(path));
810 }
811 }
812
813 function readdirFromSnapshot (path_, isRoot, cb) {
814 var cb2 = cb || rethrow;
815 if (isRoot) return readdirRoot(path_, cb);
816 var path = normalizePath(path_);
817 // console.log("readdirFromSnapshot", path);
818 var entity = VIRTUAL_FILESYSTEM[path];
819 if (!entity) return cb2(error_ENOENT('Directory', path));
820 var entityBlob = entity[STORE_BLOB];
821 if (entityBlob) return cb2(error_ENOTDIR(path));
822 var entityContent = entity[STORE_CONTENT];
823 if (entityContent) return cb2(error_ENOTDIR(path));
824 var entityLinks = entity[STORE_LINKS];
825 if (entityLinks) return readdirFromSnapshotSub(entityLinks, path, cb);
826 return cb2(new Error('UNEXPECTED-25'));
827 }
828
829 fs.readdirSync = function (path, options_) {
830 var isRoot = isRootPath(path);
831
832 if (!insideSnapshot(path) && !isRoot) {
833 return ancestor.readdirSync.apply(fs, arguments);
834 }
835 if (insideMountpoint(path)) {
836 return ancestor.readdirSync.apply(fs, translateNth(arguments, 0, path));
837 }
838
839 var options = readdirOptions(options_, false);
840
841 if (!options) {
842 return ancestor.readdirSync.apply(fs, arguments);
843 }
844
845 var entries = readdirFromSnapshot(path, isRoot);
846 if (options.withFileTypes) entries = getFileTypes(path, entries);
847 return entries;
848 };
849
850 fs.readdir = function (path, options_) {
851 var isRoot = isRootPath(path);
852
853 if (!insideSnapshot(path) && !isRoot) {
854 return ancestor.readdir.apply(fs, arguments);
855 }
856 if (insideMountpoint(path)) {
857 return ancestor.readdir.apply(fs, translateNth(arguments, 0, path));
858 }
859
860 var options = readdirOptions(options_, true);
861
862 if (!options) {
863 return ancestor.readdir.apply(fs, arguments);
864 }
865
866 var callback = dezalgo(maybeCallback(arguments));
867 readdirFromSnapshot(path, isRoot, function (error, entries) {
868 if (error) return callback(error);
869 if (options.withFileTypes) entries = getFileTypes(path, entries);
870 callback(null, entries);
871 });
872 };
873
874 // ///////////////////////////////////////////////////////////////
875 // realpath //////////////////////////////////////////////////////
876 // ///////////////////////////////////////////////////////////////
877
878 function realpathFromSnapshot (path_) {
879 var path = normalizePath(path_);
880 // console.log("realpathFromSnapshot", path);
881 return path;
882 }
883
884 fs.realpathSync = function (path) {
885 if (!insideSnapshot(path)) {
886 return ancestor.realpathSync.apply(fs, arguments);
887 }
888 if (insideMountpoint(path)) {
889 // app should not know real file name
890 }
891
892 return realpathFromSnapshot(path);
893 };
894
895 fs.realpath = function (path) {
896 if (!insideSnapshot(path)) {
897 return ancestor.realpath.apply(fs, arguments);
898 }
899 if (insideMountpoint(path)) {
900 // app should not know real file name
901 }
902
903 var callback = dezalgo(maybeCallback(arguments));
904 callback(null, realpathFromSnapshot(path));
905 };
906
907 // ///////////////////////////////////////////////////////////////
908 // stat //////////////////////////////////////////////////////////
909 // ///////////////////////////////////////////////////////////////
910
911 function restore (s) {
912 s.blksize = 4096;
913 s.blocks = 0;
914 s.dev = 0;
915 s.gid = 20;
916 s.ino = 0;
917 s.nlink = 0;
918 s.rdev = 0;
919 s.uid = 500;
920
921 s.atime = new Date(EXECSTAT.atime);
922 s.mtime = new Date(EXECSTAT.mtime);
923 s.ctime = new Date(EXECSTAT.ctime);
924 s.birthtime = new Date(EXECSTAT.birthtime);
925
926 s.atimeMs = EXECSTAT.atimeMs;
927 s.mtimeMs = EXECSTAT.mtimeMs;
928 s.ctimeMs = EXECSTAT.ctimeMs;
929 s.birthtimeMs = EXECSTAT.birthtimeMs;
930
931 var isFileValue = s.isFileValue;
932 var isDirectoryValue = s.isDirectoryValue;
933 delete s.isFileValue;
934 delete s.isDirectoryValue;
935
936 s.isFile = function () {
937 return isFileValue;
938 };
939 s.isDirectory = function () {
940 return isDirectoryValue;
941 };
942 s.isSymbolicLink = function () {
943 return false;
944 };
945 s.isFIFO = function () {
946 return false;
947 };
948
949 return s;
950 }
951
952 function findNativeAddonForStat (path, cb) {
953 var cb2 = cb || rethrow;
954 var foundPath = findNativeAddonSyncUnderRequire(path);
955 if (!foundPath) return cb2(error_ENOENT('File or directory', path));
956 if (cb) {
957 ancestor.stat.call(fs, foundPath, cb);
958 } else {
959 return ancestor.statSync.call(fs, foundPath);
960 }
961 }
962
963 function statFromSnapshotSub (entityStat, cb) {
964 if (cb) {
965 payloadFile(entityStat, function (error, buffer) {
966 if (error) return cb(error);
967 cb(null, restore(JSON.parse(buffer)));
968 });
969 } else {
970 var buffer = payloadFileSync(entityStat);
971 return restore(JSON.parse(buffer));
972 }
973 }
974
975 function statFromSnapshot (path_, cb) {
976 var cb2 = cb || rethrow;
977 var path = normalizePath(path_);
978 // console.log("statFromSnapshot", path);
979 var entity = VIRTUAL_FILESYSTEM[path];
980 if (!entity) return findNativeAddonForStat(path, cb);
981 var entityStat = entity[STORE_STAT];
982 if (entityStat) return statFromSnapshotSub(entityStat, cb);
983 return cb2(new Error('UNEXPECTED-35'));
984 }
985
986 fs.statSync = function (path) {
987 if (!insideSnapshot(path)) {
988 return ancestor.statSync.apply(fs, arguments);
989 }
990 if (insideMountpoint(path)) {
991 return ancestor.statSync.apply(fs, translateNth(arguments, 0, path));
992 }
993
994 return statFromSnapshot(path);
995 };
996
997 fs.stat = function (path) {
998 if (!insideSnapshot(path)) {
999 return ancestor.stat.apply(fs, arguments);
1000 }
1001 if (insideMountpoint(path)) {
1002 return ancestor.stat.apply(fs, translateNth(arguments, 0, path));
1003 }
1004
1005 var callback = dezalgo(maybeCallback(arguments));
1006 statFromSnapshot(path, callback);
1007 };
1008
1009 // ///////////////////////////////////////////////////////////////
1010 // lstat /////////////////////////////////////////////////////////
1011 // ///////////////////////////////////////////////////////////////
1012
1013 fs.lstatSync = function (path) {
1014 if (!insideSnapshot(path)) {
1015 return ancestor.lstatSync.apply(fs, arguments);
1016 }
1017 if (insideMountpoint(path)) {
1018 return ancestor.lstatSync.apply(fs, translateNth(arguments, 0, path));
1019 }
1020
1021 return statFromSnapshot(path);
1022 };
1023
1024 fs.lstat = function (path) {
1025 if (!insideSnapshot(path)) {
1026 return ancestor.lstat.apply(fs, arguments);
1027 }
1028 if (insideMountpoint(path)) {
1029 return ancestor.lstat.apply(fs, translateNth(arguments, 0, path));
1030 }
1031
1032 var callback = dezalgo(maybeCallback(arguments));
1033 statFromSnapshot(path, callback);
1034 };
1035
1036 // ///////////////////////////////////////////////////////////////
1037 // fstat /////////////////////////////////////////////////////////
1038 // ///////////////////////////////////////////////////////////////
1039
1040 function fstatFromSnapshot (fd, cb) {
1041 var cb2 = cb || rethrow;
1042 var entity = docks[fd].entity;
1043 var entityStat = entity[STORE_STAT];
1044 if (entityStat) return statFromSnapshotSub(entityStat, cb);
1045 return cb2(new Error('UNEXPECTED-40'));
1046 }
1047
1048 fs.fstatSync = function (fd) {
1049 if (!docks[fd]) {
1050 return ancestor.fstatSync.apply(fs, arguments);
1051 }
1052
1053 return fstatFromSnapshot(fd);
1054 };
1055
1056 fs.fstat = function (fd) {
1057 if (!docks[fd]) {
1058 return ancestor.fstat.apply(fs, arguments);
1059 }
1060
1061 var callback = dezalgo(maybeCallback(arguments));
1062 fstatFromSnapshot(fd, callback);
1063 };
1064
1065 // ///////////////////////////////////////////////////////////////
1066 // exists ////////////////////////////////////////////////////////
1067 // ///////////////////////////////////////////////////////////////
1068
1069 function findNativeAddonForExists (path) {
1070 var foundPath = findNativeAddonSyncFreeFromRequire(path);
1071 if (!foundPath) return false;
1072 return ancestor.existsSync.call(fs, foundPath);
1073 }
1074
1075 function existsFromSnapshot (path_) {
1076 var path = normalizePath(path_);
1077 // console.log("existsFromSnapshot", path);
1078 var entity = VIRTUAL_FILESYSTEM[path];
1079 if (!entity) return findNativeAddonForExists(path);
1080 return true;
1081 }
1082
1083 fs.existsSync = function (path) {
1084 if (!insideSnapshot(path)) {
1085 return ancestor.existsSync.apply(fs, arguments);
1086 }
1087 if (insideMountpoint(path)) {
1088 return ancestor.existsSync.apply(fs, translateNth(arguments, 0, path));
1089 }
1090
1091 return existsFromSnapshot(path);
1092 };
1093
1094 fs.exists = function (path) {
1095 if (!insideSnapshot(path)) {
1096 return ancestor.exists.apply(fs, arguments);
1097 }
1098 if (insideMountpoint(path)) {
1099 return ancestor.exists.apply(fs, translateNth(arguments, 0, path));
1100 }
1101
1102 var callback = dezalgo(maybeCallback(arguments));
1103 callback(existsFromSnapshot(path));
1104 };
1105
1106 // ///////////////////////////////////////////////////////////////
1107 // access ////////////////////////////////////////////////////////
1108 // ///////////////////////////////////////////////////////////////
1109
1110 function accessFromSnapshot (path_, cb) {
1111 var cb2 = cb || rethrow;
1112 var path = normalizePath(path_);
1113 // console.log("accessFromSnapshot", path);
1114 var entity = VIRTUAL_FILESYSTEM[path];
1115 if (!entity) return cb2(error_ENOENT('File or directory', path));
1116 return cb2(null, undefined);
1117 }
1118
1119 fs.accessSync = function (path) {
1120 if (!insideSnapshot(path)) {
1121 return ancestor.accessSync.apply(fs, arguments);
1122 }
1123 if (insideMountpoint(path)) {
1124 return ancestor.accessSync.apply(fs, translateNth(arguments, 0, path));
1125 }
1126
1127 return accessFromSnapshot(path);
1128 };
1129
1130 fs.access = function (path) {
1131 if (!insideSnapshot(path)) {
1132 return ancestor.access.apply(fs, arguments);
1133 }
1134 if (insideMountpoint(path)) {
1135 return ancestor.access.apply(fs, translateNth(arguments, 0, path));
1136 }
1137
1138 var callback = dezalgo(maybeCallback(arguments));
1139 accessFromSnapshot(path, callback);
1140 };
1141
1142 // ///////////////////////////////////////////////////////////////
1143 // INTERNAL //////////////////////////////////////////////////////
1144 // ///////////////////////////////////////////////////////////////
1145
1146 function makeLong (f) {
1147 return require('path')._makeLong(f);
1148 }
1149
1150 function revertMakingLong (f) {
1151 if (/^\\\\\?\\/.test(f)) return f.slice(4);
1152 return f;
1153 }
1154
1155 function findNativeAddonForInternalModuleStat (path_) {
1156 var path = findNativeAddonSyncUnderRequire(path_);
1157 if (!path) return -ENOENT;
1158 return process.binding('fs').internalModuleStat(makeLong(path));
1159 }
1160
1161 fs.internalModuleStat = function (long) {
1162 // from node comments:
1163 // Used to speed up module loading. Returns 0 if the path refers to
1164 // a file, 1 when it's a directory or < 0 on error (usually -ENOENT).
1165 // The speedup comes from not creating thousands of Stat and Error objects.
1166
1167 var path = revertMakingLong(long);
1168
1169 if (!insideSnapshot(path)) {
1170 return process.binding('fs').internalModuleStat(long);
1171 }
1172 if (insideMountpoint(path)) {
1173 return process.binding('fs').internalModuleStat(makeLong(translate(path)));
1174 }
1175
1176 path = normalizePath(path);
1177 // console.log("internalModuleStat", path);
1178 var entity = VIRTUAL_FILESYSTEM[path];
1179 if (!entity) return findNativeAddonForInternalModuleStat(path);
1180 var entityBlob = entity[STORE_BLOB];
1181 if (entityBlob) return 0;
1182 var entityContent = entity[STORE_CONTENT];
1183 if (entityContent) return 0;
1184 var entityLinks = entity[STORE_LINKS];
1185 if (entityLinks) return 1;
1186 return -ENOENT;
1187 };
1188
1189 fs.internalModuleReadFile = fs.internalModuleReadJSON = function (long) {
1190 // from node comments:
1191 // Used to speed up module loading. Returns the contents of the file as
1192 // a string or undefined when the file cannot be opened. The speedup
1193 // comes from not creating Error objects on failure.
1194
1195 var path = revertMakingLong(long);
1196 var bindingFs = process.binding('fs');
1197 var readFile = (bindingFs.internalModuleReadFile ||
1198 bindingFs.internalModuleReadJSON).bind(bindingFs);
1199 if (!insideSnapshot(path)) {
1200 return readFile(long);
1201 }
1202 if (insideMountpoint(path)) {
1203 return readFile(makeLong(translate(path)));
1204 }
1205
1206 path = normalizePath(path);
1207 // console.log("internalModuleReadFile", path);
1208 var entity = VIRTUAL_FILESYSTEM[path];
1209 if (!entity) return undefined;
1210 var entityContent = entity[STORE_CONTENT];
1211 if (!entityContent) return undefined;
1212 return payloadFileSync(entityContent).toString();
1213 };
1214}());
1215
1216// /////////////////////////////////////////////////////////////////
1217// PATCH MODULE ////////////////////////////////////////////////////
1218// /////////////////////////////////////////////////////////////////
1219
1220(function () {
1221 var Module = require('module');
1222 var ancestor = {};
1223 ancestor.require = Module.prototype.require;
1224 ancestor._compile = Module.prototype._compile;
1225 ancestor._resolveFilename = Module._resolveFilename;
1226 ancestor.runMain = Module.runMain;
1227
1228 Module.prototype.require = function (path) {
1229 try {
1230 return ancestor.require.apply(this, arguments);
1231 } catch (error) {
1232 if (((error.code === 'ENOENT') ||
1233 (error.code === 'MODULE_NOT_FOUND')) &&
1234 (!insideSnapshot(path)) &&
1235 (!require('path').isAbsolute(path))) {
1236 if (!error.pkg) {
1237 error.pkg = true;
1238 error.message += '\n' +
1239 '1) If you want to compile the package/file into ' +
1240 'executable, please pay attention to compilation ' +
1241 'warnings and specify a literal in \'require\' call. ' +
1242 '2) If you don\'t want to compile the package/file ' +
1243 'into executable and want to \'require\' it from ' +
1244 'filesystem (likely plugin), specify an absolute ' +
1245 'path in \'require\' call using process.cwd() or ' +
1246 'process.execPath.';
1247 }
1248 }
1249 throw error;
1250 }
1251 };
1252
1253 var im, makeRequireFunction;
1254
1255 if (NODE_VERSION_MAJOR === 0) {
1256 makeRequireFunction = function (self) {
1257 function rqfn (path) {
1258 return self.require(path);
1259 }
1260 rqfn.resolve = function (request) {
1261 return Module._resolveFilename(request, self);
1262 };
1263 rqfn.main = process.mainModule;
1264 rqfn.extensions = Module._extensions;
1265 rqfn.cache = Module._cache;
1266 return rqfn;
1267 };
1268 } else
1269 if (NODE_VERSION_MAJOR <= 9) {
1270 im = require('internal/module');
1271 if (NODE_VERSION_MAJOR <= 7) {
1272 makeRequireFunction = function (m) {
1273 return im.makeRequireFunction.call(m);
1274 };
1275 } else {
1276 makeRequireFunction = im.makeRequireFunction;
1277 }
1278 } else {
1279 im = require('internal/modules/cjs/helpers');
1280 makeRequireFunction = im.makeRequireFunction;
1281 // TODO esm modules along with cjs
1282 }
1283
1284 Module.prototype._compile = function (content, filename_) {
1285 if (!insideSnapshot(filename_)) {
1286 return ancestor._compile.apply(this, arguments);
1287 }
1288 if (insideMountpoint(filename_)) {
1289 // DONT TRANSLATE! otherwise __dirname gets real name
1290 return ancestor._compile.apply(this, arguments);
1291 }
1292
1293 var filename = normalizePath(filename_);
1294 // console.log("_compile", filename);
1295 var entity = VIRTUAL_FILESYSTEM[filename];
1296
1297 if (!entity) {
1298 // let user try to "_compile" a packaged file
1299 return ancestor._compile.apply(this, arguments);
1300 }
1301
1302 var entityBlob = entity[STORE_BLOB];
1303 var entityContent = entity[STORE_CONTENT];
1304
1305 if (entityBlob) {
1306 var options = {
1307 filename: filename,
1308 lineOffset: 0,
1309 displayErrors: true,
1310 cachedData: payloadFileSync(entityBlob),
1311 sourceless: !entityContent
1312 };
1313
1314 var Script = require('vm').Script;
1315 var code = entityContent
1316 ? require('module').wrap(payloadFileSync(entityContent))
1317 : undefined;
1318
1319 var script = new Script(code, options);
1320 var wrapper = script.runInThisContext(options);
1321 if (!wrapper) process.exit(4); // for example VERSION_MISMATCH
1322 var dirname = require('path').dirname(filename);
1323 var rqfn = makeRequireFunction(this);
1324 var args = [ this.exports, rqfn, this, filename, dirname ];
1325 return wrapper.apply(this.exports, args);
1326 }
1327
1328 if (entityContent) {
1329 if (entityBlob) throw new Error('UNEXPECTED-50');
1330 // content is already in utf8 and without BOM (that is expected
1331 // by stock _compile), but entityContent is still a Buffer
1332 return ancestor._compile.apply(this, arguments);
1333 }
1334
1335 throw new Error('UNEXPECTED-55');
1336 };
1337
1338 Module._resolveFilename = function () {
1339 var filename;
1340 var flagWasOn = false;
1341
1342 try {
1343 filename = ancestor._resolveFilename.apply(this, arguments);
1344 } catch (error) {
1345 if (error.code !== 'MODULE_NOT_FOUND') throw error;
1346
1347 FLAG_ENABLE_PROJECT = true;
1348 var savePathCache = Module._pathCache;
1349 Module._pathCache = Object.create(null);
1350 try {
1351 filename = ancestor._resolveFilename.apply(this, arguments);
1352 flagWasOn = true;
1353 } finally {
1354 Module._pathCache = savePathCache;
1355 FLAG_ENABLE_PROJECT = false;
1356 }
1357 }
1358
1359 if (!insideSnapshot(filename)) {
1360 return filename;
1361 }
1362 if (insideMountpoint(filename)) {
1363 return filename;
1364 }
1365
1366 if (flagWasOn) {
1367 FLAG_ENABLE_PROJECT = true;
1368 try {
1369 var found = findNativeAddonSyncUnderRequire(filename);
1370 if (found) filename = found;
1371 } finally {
1372 FLAG_ENABLE_PROJECT = false;
1373 }
1374 }
1375
1376 return filename;
1377 };
1378
1379 Module.runMain = function () {
1380 Module._load(ENTRYPOINT, null, true);
1381 process._tickCallback();
1382 };
1383}());
1384
1385// /////////////////////////////////////////////////////////////////
1386// PATCH CHILD_PROCESS /////////////////////////////////////////////
1387// /////////////////////////////////////////////////////////////////
1388
1389(function () {
1390 var childProcess = require('child_process');
1391 var ancestor = {};
1392 ancestor.spawn = childProcess.spawn;
1393 ancestor.spawnSync = childProcess.spawnSync;
1394 ancestor.execFile = childProcess.execFile;
1395 ancestor.execFileSync = childProcess.execFileSync;
1396 ancestor.exec = childProcess.exec;
1397 ancestor.execSync = childProcess.execSync;
1398
1399 function setOptsEnv (args) {
1400 var pos = args.length - 1;
1401 if (typeof args[pos] === 'function') pos -= 1;
1402 if (typeof args[pos] !== 'object' || Array.isArray(args[pos])) {
1403 pos += 1;
1404 args.splice(pos, 0, {});
1405 }
1406 var opts = args[pos];
1407 if (!opts.env) opts.env = require('util')._extend({}, process.env);
1408 if (opts.env.PKG_EXECPATH === 'PKG_INVOKE_NODEJS') return;
1409 opts.env.PKG_EXECPATH = EXECPATH;
1410 }
1411
1412 function startsWith2 (args, index, name, impostor) {
1413 var qsName = '"' + name + ' ';
1414 if (args[index].slice(0, qsName.length) === qsName) {
1415 args[index] = '"' + impostor + ' ' + args[index].slice(qsName.length);
1416 return true;
1417 }
1418 var sName = name + ' ';
1419 if (args[index].slice(0, sName.length) === sName) {
1420 args[index] = impostor + ' ' + args[index].slice(sName.length);
1421 return true;
1422 }
1423 if (args[index] === name) {
1424 args[index] = impostor;
1425 return true;
1426 }
1427 return false;
1428 }
1429
1430 function startsWith (args, index, name) {
1431 var qName = '"' + name + '"';
1432 var qEXECPATH = '"' + EXECPATH + '"';
1433 var jsName = JSON.stringify(name);
1434 var jsEXECPATH = JSON.stringify(EXECPATH);
1435 return startsWith2(args, index, name, EXECPATH) ||
1436 startsWith2(args, index, qName, qEXECPATH) ||
1437 startsWith2(args, index, jsName, jsEXECPATH);
1438 }
1439
1440 function modifyLong (args, index) {
1441 if (!args[index]) return;
1442 return (startsWith(args, index, 'node') ||
1443 startsWith(args, index, ARGV0) ||
1444 startsWith(args, index, ENTRYPOINT) ||
1445 startsWith(args, index, EXECPATH));
1446 }
1447
1448 function modifyShort (args) {
1449 if (!args[0]) return;
1450 if (!Array.isArray(args[1])) {
1451 args.splice(1, 0, []);
1452 }
1453 if (args[0] === 'node' ||
1454 args[0] === ARGV0 ||
1455 args[0] === ENTRYPOINT ||
1456 args[0] === EXECPATH) {
1457 args[0] = EXECPATH;
1458 if (NODE_VERSION_MAJOR === 0) {
1459 args[1] = args[1].filter(function (a) {
1460 return (a.slice(0, 13) !== '--debug-port=');
1461 });
1462 }
1463 } else {
1464 for (var i = 1; i < args[1].length; i += 1) {
1465 var mbc = args[1][i - 1];
1466 if (mbc === '-c' || mbc === '/c') {
1467 modifyLong(args[1], i);
1468 }
1469 }
1470 }
1471 }
1472
1473 childProcess.spawn = function () {
1474 var args = cloneArgs(arguments);
1475 setOptsEnv(args);
1476 modifyShort(args);
1477 return ancestor.spawn.apply(childProcess, args);
1478 };
1479
1480 childProcess.spawnSync = function () {
1481 var args = cloneArgs(arguments);
1482 setOptsEnv(args);
1483 modifyShort(args);
1484 return ancestor.spawnSync.apply(childProcess, args);
1485 };
1486
1487 childProcess.execFile = function () {
1488 var args = cloneArgs(arguments);
1489 setOptsEnv(args);
1490 modifyShort(args);
1491 return ancestor.execFile.apply(childProcess, args);
1492 };
1493
1494 childProcess.execFileSync = function () {
1495 var args = cloneArgs(arguments);
1496 setOptsEnv(args);
1497 modifyShort(args);
1498 return ancestor.execFileSync.apply(childProcess, args);
1499 };
1500
1501 childProcess.exec = function () {
1502 var args = cloneArgs(arguments);
1503 setOptsEnv(args);
1504 modifyLong(args, 0);
1505 return ancestor.exec.apply(childProcess, args);
1506 };
1507
1508 childProcess.execSync = function () {
1509 var args = cloneArgs(arguments);
1510 setOptsEnv(args);
1511 modifyLong(args, 0);
1512 return ancestor.execSync.apply(childProcess, args);
1513 };
1514}());
1515
1516// /////////////////////////////////////////////////////////////////
1517// PROMISIFY ///////////////////////////////////////////////////////
1518// /////////////////////////////////////////////////////////////////
1519
1520(function () {
1521 var util = require('util');
1522 var promisify = util.promisify;
1523 if (promisify) {
1524 var custom = promisify.custom;
1525 var customPromisifyArgs = require('internal/util').customPromisifyArgs;
1526
1527 // /////////////////////////////////////////////////////////////
1528 // FS //////////////////////////////////////////////////////////
1529 // /////////////////////////////////////////////////////////////
1530
1531 Object.defineProperty(require('fs').exists, custom, {
1532 value: function (path) {
1533 return new Promise(function (resolve) {
1534 require('fs').exists(path, function (exists) {
1535 resolve(exists);
1536 });
1537 });
1538 }
1539 });
1540
1541 Object.defineProperty(require('fs').read, customPromisifyArgs, {
1542 value: [ 'bytesRead', 'buffer' ]
1543 });
1544
1545 Object.defineProperty(require('fs').write, customPromisifyArgs, {
1546 value: [ 'bytesWritten', 'buffer' ]
1547 });
1548
1549 // /////////////////////////////////////////////////////////////
1550 // CHILD_PROCESS ///////////////////////////////////////////////
1551 // /////////////////////////////////////////////////////////////
1552
1553 var customPromiseExecFunction = function (o) {
1554 return function () {
1555 var args = Array.from(arguments);
1556 return new Promise(function (resolve, reject) {
1557 o.apply(undefined, args.concat(function (error, stdout, stderr) {
1558 if (error !== null) {
1559 error.stdout = stdout;
1560 error.stderr = stderr;
1561 reject(error);
1562 } else {
1563 resolve({ stdout: stdout, stderr: stderr });
1564 }
1565 }));
1566 });
1567 };
1568 };
1569
1570 Object.defineProperty(require('child_process').exec, custom, {
1571 value: customPromiseExecFunction(require('child_process').exec)
1572 });
1573
1574 Object.defineProperty(require('child_process').execFile, custom, {
1575 value: customPromiseExecFunction(require('child_process').execFile)
1576 });
1577 }
1578}());
1579
1580// /////////////////////////////////////////////////////////////////
1581// PATCH PROCESS ///////////////////////////////////////////////////
1582// /////////////////////////////////////////////////////////////////
1583
1584(function() {
1585 const fs = require('fs');
1586 var ancestor = {};
1587 ancestor.dlopen = process.dlopen;
1588
1589 function getLibCacheDir() {
1590 var path = require('path')
1591 var os = require('os')
1592 var cacheDir = process.env.SSB_PKG_CACHE_DIR
1593 || path.join(os.homedir(), '.cache', 'ssb-pkg',
1594 os.platform() + '-' + os.arch())
1595 try {
1596 fs.accessSync(cacheDir)
1597 } catch(e) {
1598 try { fs.mkdirSync(path.dirname(path.dirname(cacheDir))) } catch(e) {}
1599 try { fs.mkdirSync(path.dirname(cacheDir)) } catch(e) {}
1600 fs.mkdirSync(cacheDir)
1601 }
1602 return cacheDir
1603 }
1604
1605 process.dlopen = function () {
1606 const args = cloneArgs(arguments);
1607 const modulePath = args[1];
1608 const path = require('path')
1609 const moduleDirname = path.dirname(modulePath);
1610 if (insideSnapshot(modulePath)) {
1611 // Node addon files and .so cannot be read with fs directly, they are loaded with process.dlopen which needs a filesystem path
1612 // we need to write the file somewhere on disk first and then load it
1613 const moduleContent = fs.readFileSync(modulePath);
1614 const moduleBaseName = path.basename(modulePath);
1615 const hash = require('crypto').createHash('sha256').update(moduleContent).digest('hex');
1616 const tmpModulePath = path.join(getLibCacheDir(),
1617 hash + '_' + moduleBaseName);
1618 try {
1619 fs.statSync(tmpModulePath);
1620 } catch (e) {
1621 // Most likely this means the module is not on disk yet
1622 fs.writeFileSync(tmpModulePath, moduleContent, { mode: 0o444 });
1623 }
1624 args[1] = tmpModulePath;
1625 }
1626
1627 const unknownModuleErrorRegex = /([^:]+): cannot open shared object file: No such file or directory|Library not loaded: @loader_path\/(\S+)/;
1628 const tryImporting = function (previousErrorMessage) {
1629 try {
1630 const res = ancestor.dlopen.apply(process, args);
1631 return res;
1632 } catch (e) {
1633 if (e.message === previousErrorMessage) {
1634 // we already tried to fix this and it didn't work, give up
1635 throw e;
1636 }
1637 if (e.message.match(unknownModuleErrorRegex)) {
1638 // some modules are packaged with dynamic linking and needs to open other files that should be in
1639 // the same directory, in this case, we write this file in the same /tmp directory and try to
1640 // import the module again
1641 const m = e.message.match(unknownModuleErrorRegex)
1642 const moduleName = m[1] || m[2];
1643 const modulePath = `${moduleDirname}/${moduleName}`;
1644 const moduleContent = fs.readFileSync(modulePath);
1645 const moduleBaseName = path.basename(modulePath);
1646 const tmpModulePath = path.join(getLibCacheDir(), moduleBaseName);
1647 try {
1648 fs.statSync(tmpModulePath);
1649 } catch (e) {
1650 fs.writeFileSync(tmpModulePath, moduleContent, { mode: 0o444 });
1651 }
1652 return tryImporting(e.message);
1653 }
1654 throw e;
1655 }
1656 }
1657 tryImporting();
1658 }
1659}());
1660

Built with git-ssb-web