Initial commit

This commit is contained in:
robert committed 2025-05-30 18:13:30 +08:00
commit e49726988c
5445 files changed
+1089914

No files matched your search

+49
View File
@@ -0,0 +1,49 @@
A utility to fetch or build patched Node binaries used by [pkg](https://github.com/vercel/pkg) to generate executables. This repo hosts prebuilt binaries in [Releases](https://github.com/vercel/pkg-fetch/releases).
## Binary Compatibility
| Node | Platform | Architectures | Minimum OS version |
| --------------------------------------------------------------------------------- | ----------- | ------------------------- | --------------------------------------------------------------------------------- |
| 8<sup>[1](#fn1)</sup>, 10<sup>[1](#fn1)</sup>, 12<sup>[1](#fn1)</sup>, 14, 16, 18 | alpine | x64, arm64 | 3.7.3, other distros with musl libc >= 1.1.18 |
| 8<sup>[1](#fn1)</sup>, 10<sup>[1](#fn1)</sup>, 12<sup>[1](#fn1)</sup>, 14, 16, 18 | linux | x64 | Enterprise Linux 7, Ubuntu 14.04, Debian jessie, other distros with glibc >= 2.17 |
| 8<sup>[1](#fn1)</sup>, 10<sup>[1](#fn1)</sup>, 12<sup>[1](#fn1)</sup>, 14, 16, 18 | linux | arm64 | Enterprise Linux 8, Ubuntu 18.04, Debian buster, other distros with glibc >= 2.27 |
| 8<sup>[1](#fn1)</sup>, 10<sup>[1](#fn1)</sup>, 12<sup>[1](#fn1)</sup>, 14, 16, 18 | linuxstatic | x64, arm64 | Any distro with Linux Kernel >= 2.6.32 (>= 3.10 strongly recommended) |
| 16, 18 | linuxstatic | armv7<sup>[2](#fn2)</sup> | Any distro with Linux Kernel >= 2.6.32 (>= 3.10 strongly recommended) |
| 8<sup>[1](#fn1)</sup>, 10<sup>[1](#fn1)</sup>, 12<sup>[1](#fn1)</sup>, 14, 16, 18 | macos | x64 | 10.13 |
| 14, 16, 18 | macos | arm64<sup>[3](#fn3)</sup> | 11.0 |
| 8<sup>[1](#fn1)</sup>, 10<sup>[1](#fn1)</sup>, 12<sup>[1](#fn1)</sup>, 14, 16, 18 | win | x64 | 8.1 |
| 14, 16, 18 | win | arm64 | 10 |
<em id="fn1">[1]</em>: end-of-life, may be removed in the next major release.
<em id="fn2">[2]</em>: best-effort basis, not semver-protected.
<em id="fn3">[3]</em>: [mandatory code signing](https://developer.apple.com/documentation/macos-release-notes/macos-big-sur-11_0_1-universal-apps-release-notes) is enforced by Apple.
## Security
We do not expect this project to have vulnerabilities of its own. Nonetheless, as this project distributes prebuilt Node.js binaries,
**Node.js security vulnerabilities affect binaries distributed by this project, as well.**
Like most of you, this project does not have access to advance/private disclosures of Node.js security vulnerabilities. We can only closely monitor the **public** security advisories from the Node.js team. It takes time to build and release a new set of binaries, once a new Node.js version has been released.
We aim to complete the full cycle within a day, when there is a security update. Please [open an issue](https://github.com/vercel/pkg-fetch/issues/new) if there is no action for a while.
**It is possible for this project to fall victim to a supply chain attack.**
This project deploys multiple defense measures to ensure that the safe binaries are delivered to users:
- Binaries are compiled by [Github Actions](https://github.com/vercel/pkg-fetch/actions)
- Workflows and build logs are transparent and auditable.
- Artifacts are the source of truth. Even repository/organization administrators can't tamper them.
- Hashes of binaries are hardcoded in [source](https://github.com/vercel/pkg-fetch/blob/HEAD/lib/expected.ts)
- Origins of the binaries are documented.
- Changes to the binaries are logged by VCS (Git) and are publicly visible.
- `pkg-fetch` rejects the binary if it does not match the hardcoded hash.
- GPG-signed hashes are available in [Releases](https://github.com/vercel/pkg-fetch/releases)
- Easy to spot a compromise.
- `pkg-fetch` package on npm is strictly permission-controlled
- Only authorized Vercel employees can push new revisions to npm.
Report to [security@vercel.com](mailto:security@vercel.com), if you noticed a disparity between (hashes of) binaries.
+3
View File
@@ -0,0 +1,3 @@
#!/usr/bin/env node
export {};
//# sourceMappingURL=bin.d.ts.map
Generated Vendored Executable
+102
View File
@@ -0,0 +1,102 @@
#!/usr/bin/env node
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var yargs_1 = __importDefault(require("yargs"));
var system_1 = require("./system");
var log_1 = require("./log");
var index_1 = require("./index");
var verify_1 = require("./verify");
var package_json_1 = require("../package.json");
function main() {
return __awaiter(this, void 0, void 0, function () {
var argv, nodeRange, platform, arch, test, forceFetch, forceBuild, output, local;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
argv = yargs_1.default
.env('PKG_FETCH_OPTION_')
.option('node-range', { alias: 'n', default: 'latest', type: 'string' })
.option('platform', { alias: 'p', default: system_1.hostPlatform, type: 'string' })
.option('arch', { alias: 'a', default: system_1.hostArch, type: 'string' })
.option('test', { alias: 't', type: 'boolean' })
.option('force-fetch', {
alias: 'f',
type: 'boolean',
})
.option('force-build', {
alias: 'b',
type: 'boolean',
})
.conflicts('force-fetch', 'force-build')
.option('output', { alias: 'o', type: 'string' })
.version(package_json_1.version)
.alias('v', 'version')
.help()
.alias('h', 'help').argv;
nodeRange = argv["node-range"], platform = argv.platform, arch = argv.arch, test = argv.test, forceFetch = argv["force-fetch"], forceBuild = argv["force-build"], output = argv.output;
return [4 /*yield*/, (0, index_1.need)({
nodeRange: nodeRange,
platform: platform,
arch: arch,
forceFetch: forceFetch,
forceBuild: forceBuild,
output: output,
})];
case 1:
local = _a.sent();
log_1.log.info(local);
if (!test) return [3 /*break*/, 3];
return [4 /*yield*/, (0, verify_1.verify)(local)];
case 2:
_a.sent();
_a.label = 3;
case 3: return [2 /*return*/];
}
});
});
}
main().catch(function (error) {
if (!error.wasReported)
log_1.log.error(error);
process.exit(2);
});
//# sourceMappingURL=bin.js.map
+2
View File
@@ -0,0 +1,2 @@
export default function build(nodeVersion: string, targetArch: string, targetPlatform: string, local: string): Promise<void>;
//# sourceMappingURL=build.d.ts.map
+394
View File
@@ -0,0 +1,394 @@
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var zlib_1 = require("zlib");
var crypto_1 = __importDefault(require("crypto"));
var fs_extra_1 = __importDefault(require("fs-extra"));
var os_1 = __importDefault(require("os"));
var path_1 = __importDefault(require("path"));
var stream_1 = require("stream");
var util_1 = require("util");
var tar_fs_1 = __importDefault(require("tar-fs"));
var places_1 = require("./places");
var utils_1 = require("./utils");
var system_1 = require("./system");
var log_1 = require("./log");
var patches_json_1 = __importDefault(require("../patches/patches.json"));
var buildPath = path_1.default.resolve(process.env.PKG_BUILD_PATH ||
path_1.default.join(os_1.default.tmpdir(), "pkg." + crypto_1.default.randomBytes(12).toString('hex')));
var nodePath = path_1.default.join(buildPath, 'node');
var patchesPath = path_1.default.resolve(__dirname, '../patches');
var nodeRepo = 'https://nodejs.org/dist';
var nodeArchivePath = path_1.default.join(places_1.cachePath, 'node');
function getMajor(nodeVersion) {
var _a = nodeVersion.match(/^v?(\d+)/) || ['', 0], version = _a[1];
return Number(version) | 0;
}
function getConfigureArgs(major, targetPlatform) {
var args = [];
// first of all v8_inspector introduces the use
// of `prime_rehash_policy` symbol that requires
// GLIBCXX_3.4.18 on some systems
// also we don't support any kind of debugging
// against packaged apps, hence v8_inspector is useless
args.push('--without-inspector');
if (system_1.hostPlatform === 'alpine') {
// Statically Link against libgcc and libstdc++ libraries. See vercel/pkg#555.
// libgcc and libstdc++ grant GCC Runtime Library Exception of GPL
args.push('--partly-static');
}
if (targetPlatform === 'linuxstatic') {
args.push('--fully-static');
}
// Link Time Optimization
if (major >= 12) {
if (system_1.hostPlatform !== 'win') {
args.push('--enable-lto');
}
}
// production binaries do NOT take NODE_OPTIONS from end-users
args.push('--without-node-options');
// DTrace
args.push('--without-dtrace');
// bundled npm package manager
args.push('--without-npm');
// Small ICU
args.push('--with-intl=small-icu');
// Workaround for nodejs/node#39313
// All supported macOS versions have zlib as a system library
if (targetPlatform === 'macos') {
args.push('--shared-zlib');
}
return args;
}
function tarFetch(nodeVersion) {
return __awaiter(this, void 0, void 0, function () {
var distUrl, tarName, archivePath, hashPath, _a, _b, _c;
return __generator(this, function (_d) {
switch (_d.label) {
case 0:
log_1.log.info('Fetching Node.js source archive from nodejs.org...');
distUrl = nodeRepo + "/" + nodeVersion;
tarName = "node-" + nodeVersion + ".tar.gz";
archivePath = path_1.default.join(nodeArchivePath, tarName);
hashPath = path_1.default.join(nodeArchivePath, tarName + ".sha256sum");
if (fs_extra_1.default.existsSync(hashPath) && fs_extra_1.default.existsSync(archivePath)) {
return [2 /*return*/];
}
return [4 /*yield*/, fs_extra_1.default.remove(hashPath).catch(function () { return undefined; })];
case 1:
_d.sent();
return [4 /*yield*/, fs_extra_1.default.remove(archivePath).catch(function () { return undefined; })];
case 2:
_d.sent();
return [4 /*yield*/, (0, utils_1.downloadUrl)(distUrl + "/SHASUMS256.txt", hashPath)];
case 3:
_d.sent();
_b = (_a = fs_extra_1.default).writeFile;
_c = [hashPath];
return [4 /*yield*/, fs_extra_1.default.readFile(hashPath, 'utf8')];
case 4: return [4 /*yield*/, _b.apply(_a, _c.concat([(_d.sent())
.split('\n')
.filter(function (l) { return l.includes(tarName); })[0]]))];
case 5:
_d.sent();
return [4 /*yield*/, (0, utils_1.downloadUrl)(distUrl + "/" + tarName, archivePath)];
case 6:
_d.sent();
return [2 /*return*/];
}
});
});
}
function tarExtract(nodeVersion) {
return __awaiter(this, void 0, void 0, function () {
var tarName, expectedHash, actualHash, pipe, source, gunzip, extract;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
log_1.log.info('Extracting Node.js source archive...');
tarName = "node-" + nodeVersion + ".tar.gz";
return [4 /*yield*/, fs_extra_1.default.readFile(path_1.default.join(nodeArchivePath, tarName + ".sha256sum"), 'utf8')];
case 1:
expectedHash = (_a.sent()).split(' ')[0];
return [4 /*yield*/, (0, utils_1.hash)(path_1.default.join(nodeArchivePath, tarName))];
case 2:
actualHash = _a.sent();
if (!(expectedHash !== actualHash)) return [3 /*break*/, 5];
return [4 /*yield*/, fs_extra_1.default.remove(path_1.default.join(nodeArchivePath, tarName))];
case 3:
_a.sent();
return [4 /*yield*/, fs_extra_1.default.remove(path_1.default.join(nodeArchivePath, tarName + ".sha256sum"))];
case 4:
_a.sent();
throw (0, log_1.wasReported)("Hash mismatch for " + tarName);
case 5:
pipe = (0, util_1.promisify)(stream_1.pipeline);
source = fs_extra_1.default.createReadStream(path_1.default.join(nodeArchivePath, tarName));
gunzip = (0, zlib_1.createGunzip)();
extract = tar_fs_1.default.extract(nodePath, {
strip: 1,
map: function (header) {
log_1.log.info(header.name);
return header;
},
});
return [4 /*yield*/, pipe(source, gunzip, extract)];
case 6:
_a.sent();
return [2 /*return*/];
}
});
});
}
function applyPatches(nodeVersion) {
return __awaiter(this, void 0, void 0, function () {
var storedPatches, storedPatch, patches, _i, patches_1, patch, patchPath, args;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
log_1.log.info('Applying patches');
storedPatches = patches_json_1.default[nodeVersion];
storedPatch = 'patches' in storedPatches ? storedPatches.patches : storedPatches;
patches = 'sameAs' in storedPatch
? patches_json_1.default[storedPatch.sameAs]
: storedPatch;
_i = 0, patches_1 = patches;
_a.label = 1;
case 1:
if (!(_i < patches_1.length)) return [3 /*break*/, 4];
patch = patches_1[_i];
patchPath = path_1.default.join(patchesPath, patch);
args = ['-p1', '-i', patchPath];
return [4 /*yield*/, (0, utils_1.spawn)('patch', args, { cwd: nodePath, stdio: 'inherit' })];
case 2:
_a.sent();
_a.label = 3;
case 3:
_i++;
return [3 /*break*/, 1];
case 4: return [2 /*return*/];
}
});
});
}
function compileOnWindows(nodeVersion, targetArch, targetPlatform) {
return __awaiter(this, void 0, void 0, function () {
var args, major, config_flags;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
args = ['/c', 'vcbuild.bat', targetArch];
major = getMajor(nodeVersion);
config_flags = getConfigureArgs(major, targetPlatform);
// Event Tracing for Windows
args.push('noetw');
// Performance counters on Windows
if (major <= 10) {
args.push('noperfctr');
}
// Link Time Code Generation
if (major >= 12) {
args.push('ltcg');
}
// Can't cross compile for arm64 with small-icu
if (system_1.hostArch !== targetArch &&
!config_flags.includes('--with-intl=full-icu')) {
config_flags.push('--without-intl');
}
return [4 /*yield*/, (0, utils_1.spawn)('cmd', args, {
cwd: nodePath,
env: __assign(__assign({}, process.env), { config_flags: config_flags.join(' ') }),
stdio: 'inherit',
})];
case 1:
_a.sent();
if (major <= 10) {
return [2 /*return*/, path_1.default.join(nodePath, 'Release/node.exe')];
}
return [2 /*return*/, path_1.default.join(nodePath, 'out/Release/node.exe')];
}
});
});
}
var _a = process.env.MAKE_JOB_COUNT, MAKE_JOB_COUNT = _a === void 0 ? os_1.default.cpus().length : _a;
function compileOnUnix(nodeVersion, targetArch, targetPlatform) {
return __awaiter(this, void 0, void 0, function () {
var args, cpu, output;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
args = [];
cpu = {
x86: 'ia32',
x64: 'x64',
armv6: 'arm',
armv7: 'arm',
arm64: 'arm64',
ppc64: 'ppc64',
s390x: 's390x',
}[targetArch];
if (cpu) {
args.push('--dest-cpu', cpu);
}
if (system_1.hostArch !== targetArch) {
log_1.log.warn('Cross compiling!');
log_1.log.warn('You are responsible for appropriate env like CC, CC_host, etc.');
args.push('--cross-compiling');
}
args.push.apply(args, getConfigureArgs(getMajor(nodeVersion), targetPlatform));
// TODO same for windows?
return [4 /*yield*/, (0, utils_1.spawn)('/bin/sh', __spreadArray(['./configure'], args, true), {
cwd: nodePath,
stdio: 'inherit',
})];
case 1:
// TODO same for windows?
_a.sent();
return [4 /*yield*/, (0, utils_1.spawn)(system_1.hostPlatform === 'freebsd' ? 'gmake' : 'make', ['-j', String(MAKE_JOB_COUNT)], {
cwd: nodePath,
stdio: 'inherit',
})];
case 2:
_a.sent();
output = path_1.default.join(nodePath, 'out/Release/node');
return [4 /*yield*/, (0, utils_1.spawn)(process.env.STRIP || 'strip', __spreadArray(__spreadArray([], (targetPlatform === 'macos' ? ['-x'] : []), true), [output], false), {
stdio: 'inherit',
})];
case 3:
_a.sent();
if (!(targetPlatform === 'macos')) return [3 /*break*/, 5];
// Newer versions of Apple Clang automatically ad-hoc sign the compiled executable.
// However, for final executable to be signable, base binary MUST NOT have an existing signature.
return [4 /*yield*/, (0, utils_1.spawn)('codesign', ['--remove-signature', output], {
stdio: 'inherit',
})];
case 4:
// Newer versions of Apple Clang automatically ad-hoc sign the compiled executable.
// However, for final executable to be signable, base binary MUST NOT have an existing signature.
_a.sent();
_a.label = 5;
case 5: return [2 /*return*/, output];
}
});
});
}
function compile(nodeVersion, targetArch, targetPlatform) {
return __awaiter(this, void 0, void 0, function () {
var win;
return __generator(this, function (_a) {
log_1.log.info('Compiling Node.js from sources...');
win = system_1.hostPlatform === 'win';
if (win) {
return [2 /*return*/, compileOnWindows(nodeVersion, targetArch, targetPlatform)];
}
return [2 /*return*/, compileOnUnix(nodeVersion, targetArch, targetPlatform)];
});
});
}
function build(nodeVersion, targetArch, targetPlatform, local) {
return __awaiter(this, void 0, void 0, function () {
var output, outputHash;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, fs_extra_1.default.remove(buildPath)];
case 1:
_a.sent();
return [4 /*yield*/, fs_extra_1.default.mkdirp(nodePath)];
case 2:
_a.sent();
return [4 /*yield*/, fs_extra_1.default.mkdirp(nodeArchivePath)];
case 3:
_a.sent();
return [4 /*yield*/, tarFetch(nodeVersion)];
case 4:
_a.sent();
return [4 /*yield*/, tarExtract(nodeVersion)];
case 5:
_a.sent();
return [4 /*yield*/, applyPatches(nodeVersion)];
case 6:
_a.sent();
return [4 /*yield*/, compile(nodeVersion, targetArch, targetPlatform)];
case 7:
output = _a.sent();
return [4 /*yield*/, (0, utils_1.hash)(output)];
case 8:
outputHash = _a.sent();
return [4 /*yield*/, fs_extra_1.default.mkdirp(path_1.default.dirname(local))];
case 9:
_a.sent();
return [4 /*yield*/, fs_extra_1.default.copy(output, local)];
case 10:
_a.sent();
return [4 /*yield*/, fs_extra_1.default.promises.writeFile(local + ".sha256sum", outputHash + " " + path_1.default.basename(local) + "\n")];
case 11:
_a.sent();
return [4 /*yield*/, fs_extra_1.default.remove(buildPath)];
case 12:
_a.sent();
return [2 /*return*/];
}
});
});
}
exports.default = build;
//# sourceMappingURL=build.js.map
+2
View File
@@ -0,0 +1,2 @@
export declare const EXPECTED_HASHES: Record<string, string>;
//# sourceMappingURL=expected.d.ts.map
+97
View File
@@ -0,0 +1,97 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.EXPECTED_HASHES = void 0;
exports.EXPECTED_HASHES = {
// 2a68741776e74f626c83254941a639ab7dcf6332
// alpine: https://github.com/vercel/pkg-fetch/actions/runs/752615021
// linux: https://github.com/vercel/pkg-fetch/actions/runs/752615173
// linuxstatic: https://github.com/vercel/pkg-fetch/actions/runs/752615423
// macos: https://github.com/vercel/pkg-fetch/actions/runs/752615807
// win: https://github.com/vercel/pkg-fetch/actions/runs/752615557
'node-v10.24.1-alpine-arm64': 'f6a59f1ace2ef1f4bf976ff85d9a74bdc71bda098e8aa018e2a089c590aeedea',
'node-v10.24.1-alpine-x64': '24f862b22a59ac0adb746d5bd3f2226c8eb2f6e1565a1cb4d2418c9cb0f3769e',
'node-v10.24.1-linux-x64': 'c59574f4ea7b1423bd7ef586887ea41c43cfb2a63431126af0de20291a3a94db',
'node-v10.24.1-linuxstatic-arm64': '01bc2cfbf7a7dd1a74201ae34a6cfafc1ad1c6d77039f587111738a81637bc5b',
'node-v10.24.1-linuxstatic-x64': 'a7bbd62b712b3a7ac54953b646f0802e84bc7ecadb0b8a0756323fcffe3310a5',
'node-v10.24.1-win-x64': '958647af177a9089bb4f3495e352d5348a1b42858d0111004ca26c3a2ece3f73',
'node-v8.17.0-alpine-arm64': '807df81524ec8e1e266ac7fbed434c6b2281ae20b9fa7eaa524de90f3330c4d7',
'node-v8.17.0-alpine-x64': '83a3914de57ee6be7d68ebaac8a10c1a2972d554800f1bee218cc4a23650e0fb',
'node-v8.17.0-linux-arm64': 'f06855896bfa10bead1f08fac080305fb6fbfb2cc691168a3f0f0e834e12bfba',
'node-v8.17.0-linux-x64': '14d75d43de1ff86469d354bf42a83b9494e09502fa7bc23a975e2cb82b1608b0',
'node-v8.17.0-linuxstatic-arm64': '84de8fe30b2bd1dcb3615cf1d1b538aa48e1fcf66620ef97dce6b7ae85b45025',
'node-v8.17.0-linuxstatic-x64': '5206878079f160e75a02ad33b7559b4a869e8181ee03d51d7211b52995f9ca7b',
'node-v8.17.0-macos-x64': 'dffa71e39100f4daa57de73fda7b4debecd09f552b15cf11854c8475380d3817',
'node-v8.17.0-win-x64': '4556a06dc59a0196453ba5962ea077ea71fe566e4de1c92f73f057446d422251',
// 27e00d1d72ab4afda203edcd7a4f9601bc1d641c
// linux: https://github.com/vercel/pkg-fetch/actions/runs/888438143
// linuxstatic: https://github.com/vercel/pkg-fetch/actions/runs/888438190
// macos: https://github.com/vercel/pkg-fetch/actions/runs/888438236
'node-v10.24.1-linux-arm64': 'e3a3e5197e3f3d1063e3178786890b29493b8dfc31362f3417cce90ca7eb3e98',
'node-v10.24.1-linuxstatic-armv7': '4933be03e394a82f5aa5fc4600b29392b2ce7eac24bd2ef8759f9a8e8c841990',
// 55a34ad0afe75749a14260c45d39cc9b265995ed
// macos: https://github.com/vercel/pkg-fetch/actions/runs/918633749
'node-v10.24.1-macos-x64': 'f2e4679262a1cc6f3213cc4f0453d662e48c021975b651534fcbf26d6fdab474',
// e34c57f612d4cf56646450f75fe38e029ff2b0d6
// alpine: https://github.com/vercel/pkg-fetch/actions/runs/2068735040
// linux: https://github.com/vercel/pkg-fetch/actions/runs/2068735307
// linuxstatic: https://github.com/vercel/pkg-fetch/actions/runs/2068735697
// macos: https://github.com/vercel/pkg-fetch/actions/runs/2068736404
// win: https://github.com/vercel/pkg-fetch/actions/runs/2068736093
'node-v12.22.11-alpine-x64': '2ec8d7b761f03b2172bcf3b1b56c648e844116ab08a5484d7932138c374cf18c',
'node-v12.22.11-linux-x64': '617d58e81711d3a1d34a737db39e751caa05040a1a586e6dd688241cfb3f3eed',
'node-v12.22.11-linuxstatic-x64': '37714fc3ae8b1d0c92b124f8ab353c77e40494075646e43ce8e20bd4038b5b83',
'node-v12.22.11-macos-x64': '5394093f0fd2bb5ea38ee2a5eaec9e00d3d1da9e3f7c3c99c68eecfe17354286',
'node-v12.22.11-win-x64': '24bedd07eb0cad64d505ec731c438765370bbed32d8e1f47129fe3612fadfcdb',
// e34c57f612d4cf56646450f75fe38e029ff2b0d6
// alpine: https://github.com/jesec/pkg-fetch/actions/runs/2068737927
// linux: https://github.com/jesec/pkg-fetch/actions/runs/2068738228
// linuxstatic: https://github.com/jesec/pkg-fetch/actions/runs/2068738548
// macos: https://github.com/jesec/pkg-fetch/actions/runs/2068742592
'node-v12.22.11-alpine-arm64': '0933ab559bb34c720f0a7e0066f32608960a4d6290977c3af15529f7abfe7265',
'node-v12.22.11-linux-arm64': '3a50d85ebd5ba7e1e62165b9df237925789ef9ed0ed92fd9d0f3a9df7503f751',
'node-v12.22.11-linuxstatic-arm64': '0c5b03cbe32ce50f16dbb35769a2a897b30e8fdb2137c4799edb55898b475622',
// 6ffa969bc037f33cd5c926b8706324740c8818af
// alpine: https://github.com/vercel/pkg-fetch/actions/runs/2638965835
// linux: https://github.com/vercel/pkg-fetch/actions/runs/2638965968
// linuxstatic: https://github.com/vercel/pkg-fetch/actions/runs/2638966056
// macos: https://github.com/vercel/pkg-fetch/actions/runs/2638966552
// win: https://github.com/vercel/pkg-fetch/actions/runs/2638966247
'node-v14.20.0-alpine-x64': 'bd48f87a845825d7321ff436ab0ecf59c71ac53356fed3b6ba2a841e06a75945',
'node-v14.20.0-linux-x64': 'f3149f4772c6bc41180017d325e27b1465213acd684164e26fbc64e1f2f97dcf',
'node-v14.20.0-linuxstatic-x64': 'a23a2fe6f1d75bb6d1faed1221e47fb3ff4789a23018709d919c5d24a3b17ce2',
'node-v14.20.0-macos-x64': 'afda9c14e5f3fc18d40b7cd05c6a8ba42284c28928b29e47b9b99125d41ebce6',
'node-v14.20.0-win-arm64': 'd9911fcdcedd1f5b227bd7d0ac3ef819a411976f6eb9550e2275a3c4fe93b97b',
'node-v14.20.0-win-x64': 'f71330035700705ae39bfaac80b9270c8f75631b06b25f21b06d7359d9cd6c24',
'node-v16.16.0-alpine-x64': '2c4caf90c620f4839277edf8dfb4fd1d259294a2bfbed2b90bb6063a6e0c9d23',
'node-v16.16.0-linux-x64': 'f1a561aadf78e438e73b043a3c5d7b9fe075d7abcaaec6f29d9e2a0ba00d3a69',
'node-v16.16.0-linuxstatic-x64': '8a888553a4855f3b01ea91a398eb3112b0d5f58f5f0112e9fecf6621615201ce',
'node-v16.16.0-macos-x64': '321fcef798383c6e19d7ae242bc73dd1f1c7471499b00ee6b105c764645d9263',
'node-v16.16.0-win-x64': 'b6c5f9a5bce3b451b6d59153eae6db1a87016edc3775ef9eae39f86485735672',
'node-v18.5.0-alpine-x64': '8cdc988b31d52b5c5e8112f82f798aa9c815b7d861e689f40ba2e33b782e0e35',
'node-v18.5.0-linux-x64': '25ea58e212ecac6c36df03281676aca934f4fec6a05fe9f0da8d3e01778df12c',
'node-v18.5.0-linuxstatic-x64': '18f09486dae0ca6ebc48c7bf3f68fa85baeac8279c2b407bb25e8b5941c46556',
'node-v18.5.0-macos-x64': '63c5a7f59ea2d4c04c4d033be8844be894ce018c43b2ea61ed5ccc38b833e435',
'node-v18.5.0-win-arm64': '02e317e399fecc4a21facc365ff51268555b1a347c4f2720956a12e843b99783',
'node-v18.5.0-win-x64': 'e0e9a647d81011612f8cb19c6a41760643eedd27222af548e9ffdff7d8ebb94b',
// 6ffa969bc037f33cd5c926b8706324740c8818af
// alpine: https://github.com/jesec/pkg-fetch/actions/runs/2639071916
// linux: https://github.com/jesec/pkg-fetch/actions/runs/2639072106
// linuxstatic: https://github.com/jesec/pkg-fetch/actions/runs/2639072371
// macos: https://github.com/jesec/pkg-fetch/actions/runs/2639072571
'node-v14.20.0-alpine-arm64': 'b0be3a7904f2c79bdb8e2b61018d9aa7f55e0778c4c768c4d65017931369a762',
'node-v14.20.0-linux-arm64': 'fa26fed989a0710e82eaf09bd727f3501ab80d487da4baa076ab50267e47bbde',
'node-v14.20.0-linuxstatic-arm64': 'b645ee721e1f12d9a45e1a529e28038c0eb757de4bb74ba3b585999e3160a767',
'node-v14.20.0-macos-arm64': 'c101f9378cf40d62400612f57efea3e4b0e9951b110aea6a50dbf3aff84ea45f',
'node-v16.16.0-alpine-arm64': 'c38f270d190fd1f5d8e74800b62408d06f4492720fec1fd46414a7f504114847',
'node-v16.16.0-linux-arm64': 'e3913ecef725f83ccbd2181d7d33043f8b3e72466d09897c338ee328cffc3bfe',
'node-v16.16.0-linuxstatic-arm64': 'aac0039a2b380057085a4b927637c6e5550eabfd55d1ca2f98e022abccfd7390',
'node-v16.16.0-linuxstatic-armv7': 'cbe14ff111fd3d1ecb82cf6aaec5a53588537008fdcfab4bc2c880d651f5580a',
'node-v16.16.0-macos-arm64': 'd9140eebaa88620b9692d6e11cc2d92b2b56f791a6bbeddd771f5e07d042e1bc',
'node-v16.16.0-win-arm64': 'e078fd200f6f0cd2e84ba668711a5cc9c7f0d20d36fae1bfe4bc361f40f5923f',
'node-v18.5.0-alpine-arm64': 'e227164d7a0683b42a1a5659a997d7b8a843ffe293b291f0063a8afb08b657ca',
'node-v18.5.0-linux-arm64': 'e562c0d81643de3b06b9900936ebde263373ca7bdaf42a8eacca8d020b2ce21e',
'node-v18.5.0-linuxstatic-arm64': '073f9252693bd35a4184a24bdc503aa6dc1300def7a96564c83221e4d3272c5a',
'node-v18.5.0-linuxstatic-armv7': 'eb32af2e74028d303933b4fd4d13e1fc3c6854cfa65e962dfe31903cff69ef74',
'node-v18.5.0-macos-arm64': '242917bdb26a1b53726f82483bc68ce0609cc8772df401b2eb163dc6b3d6ddfe',
};
//# sourceMappingURL=expected.js.map
+13
View File
@@ -0,0 +1,13 @@
import * as system from './system';
interface NeedOptions {
forceFetch?: boolean;
forceBuild?: boolean;
dryRun?: boolean;
output?: string;
nodeRange: string;
platform: string;
arch: string;
}
export declare function need(opts: NeedOptions): Promise<string>;
export { system };
//# sourceMappingURL=index.d.ts.map
+244
View File
@@ -0,0 +1,244 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.system = exports.need = void 0;
var fs_extra_1 = __importDefault(require("fs-extra"));
var path_1 = __importDefault(require("path"));
var semver_1 = __importDefault(require("semver"));
var expected_1 = require("./expected");
var system_1 = require("./system");
var system = __importStar(require("./system"));
exports.system = system;
var places_1 = require("./places");
var log_1 = require("./log");
var build_1 = __importDefault(require("./build"));
var utils_1 = require("./utils");
var patches_json_1 = __importDefault(require("../patches/patches.json"));
var package_json_1 = require("../package.json");
function download(_a, local) {
var tag = _a.tag, name = _a.name;
return __awaiter(this, void 0, void 0, function () {
var url, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
url = "https://github.com/vercel/pkg-fetch/releases/download/" + tag + "/" + name;
_c.label = 1;
case 1:
_c.trys.push([1, 4, , 5]);
return [4 /*yield*/, (0, utils_1.downloadUrl)(url, local)];
case 2:
_c.sent();
return [4 /*yield*/, (0, utils_1.plusx)(local)];
case 3:
_c.sent();
return [3 /*break*/, 5];
case 4:
_b = _c.sent();
return [2 /*return*/, false];
case 5: return [2 /*return*/, true];
}
});
});
}
function exists(file) {
return __awaiter(this, void 0, void 0, function () {
var error_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
return [4 /*yield*/, fs_extra_1.default.stat(file)];
case 1:
_a.sent();
return [2 /*return*/, true];
case 2:
error_1 = _a.sent();
return [2 /*return*/, false];
case 3: return [2 /*return*/];
}
});
});
}
function need(opts) {
return __awaiter(this, void 0, void 0, function () {
function satisfyingNodeVersion() {
var versions = Object.keys(patches_json_1.default)
.filter(function (nv) { return semver_1.default.satisfies(nv, nodeRange) || nodeRange === 'latest'; })
.sort(function (nv1, nv2) { return (semver_1.default.gt(nv1, nv2) ? 1 : -1); });
return versions.pop();
}
var _a, forceFetch, forceBuild, dryRun, output, _b, nodeRange, platform, arch, nodeVersion, fetched, built, remote, fetchFailed;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
_a = opts || {}, forceFetch = _a.forceFetch, forceBuild = _a.forceBuild, dryRun = _a.dryRun, output = _a.output;
_b = opts || {}, nodeRange = _b.nodeRange, platform = _b.platform, arch = _b.arch;
if (!nodeRange)
throw (0, log_1.wasReported)('nodeRange not specified');
if (!platform)
throw (0, log_1.wasReported)('platform not specified');
if (!arch)
throw (0, log_1.wasReported)('arch not specified');
nodeRange = (0, system_1.abiToNodeRange)(nodeRange); // 'm48' -> 'node6'
if (!(0, system_1.isValidNodeRange)(nodeRange)) {
throw (0, log_1.wasReported)("nodeRange must start with 'node'");
}
if (nodeRange !== 'latest') {
nodeRange = "v" + nodeRange.slice(4); // 'node6' -> 'v6' for semver
}
platform = (0, system_1.toFancyPlatform)(platform); // win32 -> win
arch = (0, system_1.toFancyArch)(arch); // ia32 -> x86
nodeVersion = satisfyingNodeVersion();
if (!nodeVersion) {
throw (0, log_1.wasReported)("No available node version satisfies '" + opts.nodeRange + "'");
}
fetched = (0, places_1.localPlace)({
from: 'fetched',
arch: arch,
nodeVersion: nodeVersion,
platform: platform,
version: package_json_1.version,
output: output,
});
built = (0, places_1.localPlace)({
from: 'built',
arch: arch,
nodeVersion: nodeVersion,
platform: platform,
version: package_json_1.version,
output: output,
});
remote = (0, places_1.remotePlace)({ arch: arch, nodeVersion: nodeVersion, platform: platform, version: package_json_1.version });
if (!!forceBuild) return [3 /*break*/, 3];
return [4 /*yield*/, exists(fetched)];
case 1:
if (!_c.sent()) return [3 /*break*/, 3];
if (dryRun) {
return [2 /*return*/, 'exists'];
}
return [4 /*yield*/, (0, utils_1.hash)(fetched)];
case 2:
if ((_c.sent()) === expected_1.EXPECTED_HASHES[remote.name]) {
return [2 /*return*/, fetched];
}
log_1.log.info('Binary hash does NOT match. Re-fetching...');
fs_extra_1.default.unlinkSync(fetched);
_c.label = 3;
case 3:
if (!!forceFetch) return [3 /*break*/, 5];
return [4 /*yield*/, exists(built)];
case 4:
if (_c.sent()) {
if (dryRun)
return [2 /*return*/, 'exists'];
if (forceBuild)
log_1.log.info('Reusing base binaries built locally:', built);
return [2 /*return*/, built];
}
_c.label = 5;
case 5:
if (!!forceBuild) return [3 /*break*/, 9];
if (dryRun)
return [2 /*return*/, 'fetched'];
return [4 /*yield*/, download(remote, fetched)];
case 6:
if (!_c.sent()) return [3 /*break*/, 8];
return [4 /*yield*/, (0, utils_1.hash)(fetched)];
case 7:
if ((_c.sent()) === expected_1.EXPECTED_HASHES[remote.name]) {
return [2 /*return*/, fetched];
}
fs_extra_1.default.unlinkSync(fetched);
throw (0, log_1.wasReported)('Binary hash does NOT match.');
case 8:
fetchFailed = true;
_c.label = 9;
case 9:
if (!dryRun && fetchFailed) {
log_1.log.info('Not found in remote cache:', JSON.stringify(remote));
if (forceFetch) {
throw (0, log_1.wasReported)("Failed to fetch.");
}
}
if (!dryRun) {
log_1.log.info('Building base binary from source:', path_1.default.basename(built));
}
if (system_1.hostPlatform !== platform) {
if (system_1.hostPlatform !== 'alpine' || platform !== 'linuxstatic') {
throw (0, log_1.wasReported)("Not able to build for '" + opts.platform + "' here, only for '" + system_1.hostPlatform + "'");
}
}
if (system_1.knownArchs.indexOf(arch) < 0) {
throw (0, log_1.wasReported)("Unknown arch '" + opts.arch + "'. Specify " + system_1.knownArchs.join(', '));
}
if (dryRun) {
return [2 /*return*/, 'built'];
}
return [4 /*yield*/, (0, build_1.default)(nodeVersion, arch, platform, built)];
case 10:
_c.sent();
return [2 /*return*/, built];
}
});
});
}
exports.need = need;
//# sourceMappingURL=index.js.map
+20
View File
@@ -0,0 +1,20 @@
declare class Log {
debugMode: boolean;
private bar?;
private lines;
debug(text: string, lines?: string[] | string): void;
info(text: string, lines?: string[] | string): void;
warn(text: string, lines?: string[] | string): void;
error(text: Error | string, lines?: string[] | string): void;
enableProgress(text: string): void;
showProgress(percentage: number): void;
disableProgress(): void;
}
export declare const log: Log;
declare class ReportedError extends Error {
name: string;
wasReported: boolean;
}
export declare function wasReported(error?: string, lines?: string[] | string | string): ReportedError;
export {};
//# sourceMappingURL=log.d.ts.map
+112
View File
@@ -0,0 +1,112 @@
"use strict";
/* eslint-disable no-underscore-dangle, no-console */
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.wasReported = exports.log = void 0;
var progress_1 = __importDefault(require("progress"));
var assert_1 = __importDefault(require("assert"));
var chalk_1 = __importDefault(require("chalk"));
var Log = /** @class */ (function () {
function Log() {
this.debugMode = false;
}
Log.prototype.lines = function (lines) {
if (lines === undefined) {
return;
}
if (!Array.isArray(lines)) {
console.log(" " + lines);
return;
}
for (var _i = 0, lines_1 = lines; _i < lines_1.length; _i++) {
var line = lines_1[_i];
console.log(" " + line);
}
};
Log.prototype.debug = function (text, lines) {
if (!this.debugMode) {
return;
}
console.log("> " + chalk_1.default.green('[debug]') + " " + text);
this.lines(lines);
};
Log.prototype.info = function (text, lines) {
console.log("> " + text);
this.lines(lines);
};
Log.prototype.warn = function (text, lines) {
console.log("> " + chalk_1.default.blue('Warning') + " " + text);
this.lines(lines);
};
Log.prototype.error = function (text, lines) {
var message = text instanceof Error ? text.stack : text;
console.log("> " + chalk_1.default.red('Error!') + " " + message);
this.lines(lines);
};
Log.prototype.enableProgress = function (text) {
(0, assert_1.default)(!this.bar);
text += ' '.repeat(35 - text.length);
this.bar = new progress_1.default(" " + text + " [:bar] :percent", {
stream: process.stdout,
width: 20,
complete: '=',
incomplete: ' ',
total: 100,
});
};
Log.prototype.showProgress = function (percentage) {
if (!this.bar) {
return;
}
this.bar.update(percentage / 100);
};
Log.prototype.disableProgress = function () {
if (!this.bar) {
return;
}
// avoid empty line
if (!this.bar.complete) {
this.bar.terminate();
}
delete this.bar;
};
return Log;
}());
exports.log = new Log();
var ReportedError = /** @class */ (function (_super) {
__extends(ReportedError, _super);
function ReportedError() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.name = 'ReportedError';
_this.wasReported = true;
return _this;
}
return ReportedError;
}(Error));
function wasReported(error, lines) {
var reportedError = new ReportedError('No message');
if (typeof error === 'string') {
exports.log.error(error, lines);
reportedError = new ReportedError(error);
}
return reportedError;
}
exports.wasReported = wasReported;
//# sourceMappingURL=log.js.map
+19
View File
@@ -0,0 +1,19 @@
export declare const cachePath: string;
interface PlaceOptions {
version: string;
nodeVersion: string;
platform: string;
arch: string;
}
interface LocalPlaceOptions extends PlaceOptions {
from: string;
output?: string;
}
export declare function localPlace({ from, output, version, nodeVersion, platform, arch, }: LocalPlaceOptions): string;
export interface Remote {
tag: string;
name: string;
}
export declare function remotePlace({ version, nodeVersion, platform, arch, }: PlaceOptions): Remote;
export {};
//# sourceMappingURL=places.d.ts.map
+40
View File
@@ -0,0 +1,40 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.remotePlace = exports.localPlace = exports.cachePath = void 0;
var semver_1 = require("semver");
var os_1 = __importDefault(require("os"));
var path_1 = __importDefault(require("path"));
var PKG_CACHE_PATH = process.env.PKG_CACHE_PATH;
var IGNORE_TAG = Boolean(process.env.PKG_IGNORE_TAG);
exports.cachePath = PKG_CACHE_PATH || path_1.default.join(os_1.default.homedir(), '.pkg-cache');
function tagFromVersion(version) {
var mj = (0, semver_1.major)(version);
var mn = (0, semver_1.minor)(version);
return "v" + mj + "." + mn;
}
function localPlace(_a) {
var from = _a.from, output = _a.output, version = _a.version, nodeVersion = _a.nodeVersion, platform = _a.platform, arch = _a.arch;
var binDir;
if (output) {
binDir = path_1.default.resolve(output);
}
else {
binDir = IGNORE_TAG
? path_1.default.join(exports.cachePath)
: path_1.default.join(exports.cachePath, tagFromVersion(version));
}
return path_1.default.resolve(binDir, (output ? 'node' : from) + "-" + nodeVersion + "-" + platform + "-" + arch);
}
exports.localPlace = localPlace;
function remotePlace(_a) {
var version = _a.version, nodeVersion = _a.nodeVersion, platform = _a.platform, arch = _a.arch;
return {
tag: tagFromVersion(version),
name: "node-" + nodeVersion + "-" + platform + "-" + arch,
};
}
exports.remotePlace = remotePlace;
//# sourceMappingURL=places.js.map
+11
View File
@@ -0,0 +1,11 @@
export declare function abiToNodeRange(abi: string): string;
export declare function isValidNodeRange(nodeRange: string): boolean;
export declare function toFancyPlatform(platform: string): string;
export declare function toFancyArch(arch: string): string;
export declare const hostAbi: string;
export declare const hostPlatform: string;
export declare const knownPlatforms: string[];
export declare const hostArch: string;
export declare const targetArchs: string[];
export declare const knownArchs: string[];
//# sourceMappingURL=system.d.ts.map
+121
View File
@@ -0,0 +1,121 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.knownArchs = exports.targetArchs = exports.hostArch = exports.knownPlatforms = exports.hostPlatform = exports.hostAbi = exports.toFancyArch = exports.toFancyPlatform = exports.isValidNodeRange = exports.abiToNodeRange = void 0;
var fs_1 = __importDefault(require("fs"));
var child_process_1 = require("child_process");
function getHostAbi() {
return "m" + process.versions.modules;
}
function abiToNodeRange(abi) {
if (/^m?14/.test(abi))
return 'node0.12';
if (/^m?46/.test(abi))
return 'node4';
if (/^m?47/.test(abi))
return 'node5';
if (/^m?48/.test(abi))
return 'node6';
if (/^m?51/.test(abi))
return 'node7';
if (/^m?57/.test(abi))
return 'node8';
if (/^m?59/.test(abi))
return 'node9';
if (/^m?64/.test(abi))
return 'node10';
if (/^m?67/.test(abi))
return 'node11';
if (/^m?72/.test(abi))
return 'node12';
if (/^m?79/.test(abi))
return 'node13';
if (/^m?83/.test(abi))
return 'node14';
return abi;
}
exports.abiToNodeRange = abiToNodeRange;
function isValidNodeRange(nodeRange) {
if (nodeRange === 'latest')
return true;
if (!/^node/.test(nodeRange))
return false;
return true;
}
exports.isValidNodeRange = isValidNodeRange;
function toFancyPlatform(platform) {
if (platform === 'darwin')
return 'macos';
if (platform === 'lin')
return 'linux';
if (platform === 'mac')
return 'macos';
if (platform === 'osx')
return 'macos';
if (platform === 'win32')
return 'win';
if (platform === 'windows')
return 'win';
return platform;
}
exports.toFancyPlatform = toFancyPlatform;
function detectAlpine() {
var _a;
var platform = process.platform;
if (platform !== 'linux') {
return false;
}
// https://github.com/sass/node-sass/issues/1589#issuecomment-265292579
var ldd = (_a = (0, child_process_1.spawnSync)('ldd').stderr) === null || _a === void 0 ? void 0 : _a.toString();
if (ldd == null) {
return fs_1.default.readdirSync('/lib').some(function (file) { return file.startsWith('libc.musl'); });
}
if (/\bmusl\b/.test(ldd)) {
return true;
}
var lddNode = (0, child_process_1.spawnSync)('ldd', [process.execPath]).stdout.toString();
return /\bmusl\b/.test(lddNode);
}
var isAlpine = detectAlpine();
function getHostPlatform() {
var platform = process.platform;
if (isAlpine) {
return 'alpine';
}
return toFancyPlatform(platform);
}
function getKnownPlatforms() {
return ['alpine', 'freebsd', 'linux', 'linuxstatic', 'macos', 'win'];
}
function toFancyArch(arch) {
if (arch === 'arm')
return 'armv7';
if (arch === 'ia32')
return 'x86';
if (arch === 'x86_64')
return 'x64';
return arch;
}
exports.toFancyArch = toFancyArch;
function getHostArch() {
return toFancyArch(process.arch);
}
function getTargetArchs() {
var arch = getHostArch();
if (arch === 'x64') {
return ['x64', 'x86'];
}
return [arch];
}
function getKnownArchs() {
return ['x64', 'x86', 'armv7', 'arm64', 'ppc64', 's390x'];
}
exports.hostAbi = getHostAbi();
exports.hostPlatform = getHostPlatform();
exports.knownPlatforms = getKnownPlatforms();
exports.hostArch = getHostArch();
exports.targetArchs = getTargetArchs();
exports.knownArchs = getKnownArchs();
//# sourceMappingURL=system.js.map
+7
View File
@@ -0,0 +1,7 @@
/// <reference types="node" />
import { SpawnSyncOptions } from 'child_process';
export declare function downloadUrl(url: string, file: string): Promise<void>;
export declare function hash(filePath: string): Promise<string>;
export declare function plusx(file: string): Promise<void>;
export declare function spawn(command: string, args?: ReadonlyArray<string>, options?: SpawnSyncOptions): Promise<void>;
//# sourceMappingURL=utils.d.ts.map
+157
View File
@@ -0,0 +1,157 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.spawn = exports.plusx = exports.hash = exports.downloadUrl = void 0;
var node_fetch_1 = __importDefault(require("node-fetch"));
var crypto_1 = __importDefault(require("crypto"));
var fs_extra_1 = __importDefault(require("fs-extra"));
var https_proxy_agent_1 = __importDefault(require("https-proxy-agent"));
var path_1 = __importDefault(require("path"));
var child_process_1 = require("child_process");
var stream_1 = __importDefault(require("stream"));
var log_1 = require("./log");
function downloadUrl(url, file) {
var _a, _b, _c;
return __awaiter(this, void 0, void 0, function () {
var proxy, res, tempFile, ws, totalSize, currentSize;
return __generator(this, function (_d) {
switch (_d.label) {
case 0:
log_1.log.enableProgress(path_1.default.basename(file));
log_1.log.showProgress(0);
proxy = (_c = (_b = (_a = process.env.HTTPS_PROXY) !== null && _a !== void 0 ? _a : process.env.https_proxy) !== null && _b !== void 0 ? _b : process.env.HTTP_PROXY) !== null && _c !== void 0 ? _c : process.env.http_proxy;
return [4 /*yield*/, (0, node_fetch_1.default)(url, proxy ? { agent: (0, https_proxy_agent_1.default)(proxy) } : undefined)];
case 1:
res = _d.sent();
if (!res.ok) {
log_1.log.disableProgress();
throw (0, log_1.wasReported)(res.status + ": " + res.statusText);
}
tempFile = file + ".downloading";
fs_extra_1.default.mkdirpSync(path_1.default.dirname(tempFile));
ws = fs_extra_1.default.createWriteStream(tempFile);
totalSize = Number(res.headers.get('content-length'));
currentSize = 0;
res.body.on('data', function (chunk) {
if (totalSize != null && totalSize !== 0) {
currentSize += chunk.length;
log_1.log.showProgress((currentSize / totalSize) * 100);
}
});
res.body.pipe(ws);
return [2 /*return*/, new Promise(function (resolve, reject) {
stream_1.default.finished(ws, function (err) {
if (err) {
log_1.log.disableProgress();
fs_extra_1.default.rmSync(tempFile);
reject((0, log_1.wasReported)(err.name + ": " + err.message));
}
else {
log_1.log.showProgress(100);
log_1.log.disableProgress();
fs_extra_1.default.moveSync(tempFile, file);
resolve();
}
});
})];
}
});
});
}
exports.downloadUrl = downloadUrl;
function hash(filePath) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
return [2 /*return*/, new Promise(function (resolve, reject) {
var resultHash = crypto_1.default.createHash('sha256');
var input = fs_extra_1.default.createReadStream(filePath);
input.on('error', function (e) {
reject(e);
});
input.on('readable', function () {
var data = input.read();
if (data) {
resultHash.update(data);
}
else {
resolve(resultHash.digest('hex'));
}
});
})];
});
});
}
exports.hash = hash;
function plusx(file) {
return __awaiter(this, void 0, void 0, function () {
var s, newMode, base8;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, fs_extra_1.default.stat(file)];
case 1:
s = _a.sent();
newMode = s.mode | 64 | 8 | 1;
if (s.mode === newMode)
return [2 /*return*/];
base8 = newMode.toString(8).slice(-3);
return [4 /*yield*/, fs_extra_1.default.chmod(file, base8)];
case 2:
_a.sent();
return [2 /*return*/];
}
});
});
}
exports.plusx = plusx;
function spawn(command, args, options) {
return __awaiter(this, void 0, void 0, function () {
var error;
return __generator(this, function (_a) {
error = (0, child_process_1.spawnSync)(command, args, options).error;
if (error) {
throw error;
}
return [2 /*return*/];
});
});
}
exports.spawn = spawn;
//# sourceMappingURL=utils.js.map
+2
View File
@@ -0,0 +1,2 @@
export declare function verify(local: string): Promise<void>;
//# sourceMappingURL=verify.d.ts.map
+60
View File
@@ -0,0 +1,60 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.verify = void 0;
var child_process_1 = require("child_process");
var utils_1 = require("./utils");
var script = "\n var vm = require('vm');\n var assert = require('assert');\n var text = '(function () { return 42; })';\n var cd, fn, result;\n var modules = process.versions.modules | 0;\n var v8 = process.versions.v8.split('.').slice(0, 2).join('.');\n\n var s1 = new vm.Script(text, { filename: 's1', produceCachedData: true, sourceless: true });\n assert(s1.cachedDataProduced);\n cd = s1.cachedData;\n\n var kCpuFeaturesOffset, cpuFeatures;\n\n if (modules === 14) {\n } else\n if (modules === 46 || modules === 48 || modules === 51) {\n kCpuFeaturesOffset = 0x0c;\n } else\n if (modules === 57) {\n if (v8 === '6.2') {\n kCpuFeaturesOffset = 0x0c;\n } else\n if (v8 === '5.8') {\n kCpuFeaturesOffset = 0x0c;\n } else {\n kCpuFeaturesOffset = 0x10;\n }\n } else\n if (modules === 59) {\n kCpuFeaturesOffset = 0x0c;\n } else\n if (modules === 64) {\n kCpuFeaturesOffset = 0x0c;\n } else\n if (modules === 72) {\n // no cpu features anymore\n } else\n if (modules === 79) {\n // no cpu features anymore\n } else\n if (modules === 83) {\n // no cpu features anymore\n } else {\n assert(false, modules);\n }\n\n if (modules >= 46 && // no cpu_features field in 0.12\n process.arch !== 'arm' && // non-zero features even in sourceless mode in arm\n modules < 72) { // no cpu_features field in 12+\n cpuFeatures = cd.readUInt32LE(kCpuFeaturesOffset);\n assert(cpuFeatures === 0, 'CPU_FEATURES must be zero');\n }\n\n var s2 = new vm.Script(undefined, { filename: 's2', cachedData: cd, sourceless: true });\n fn = s2.runInThisContext();\n result = fn();\n assert.equal(result, 42);\n\n if (modules === 14) {\n } else\n if (modules === 46 || modules === 48 ||\n modules === 51 || modules === 57 || modules === 59 || modules === 64) {\n var paddedPayloadOffset = 0x48; // see SerializedCodeData::Payload()\n var index = paddedPayloadOffset + 10;\n cd[index] ^= 0xf0;\n var s3 = new vm.Script(undefined, { filename: 's3', cachedData: cd, sourceless: true });\n assert(s3.cachedDataRejected, 's3.cachedDataRejected must be true');\n } else\n if (modules === 72) {\n } else\n if (modules === 79) {\n } else\n if (modules === 83) {\n } else {\n assert(false, modules);\n }\n\n var s4 = new vm.Script(text, { filename: 's4', produceCachedData: true });\n assert(s4.cachedDataProduced, 's4.cachedDataProduced must be true');\n cd = s4.cachedData;\n\n if (modules >= 46 && // no cpu_features field in 0.12\n process.arch !== 'arm' && // zero features even in non-sourceless mode in arm\n modules < 72) { // no cpu_features field in 12+\n cpuFeatures = cd.readUInt32LE(kCpuFeaturesOffset);\n assert(cpuFeatures !== 0, 'CPU_FEATURES must be non-zero');\n }\n\n console.log('ok');\n";
function verify(local) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, (0, utils_1.plusx)(local)];
case 1:
_a.sent();
(0, child_process_1.spawnSync)(local, ['-e', script], {
env: { PKG_EXECPATH: 'PKG_INVOKE_NODEJS' },
stdio: 'inherit',
});
return [2 /*return*/];
}
});
});
}
exports.verify = verify;
//# sourceMappingURL=verify.js.map
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 Zeit, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+1
View File
@@ -0,0 +1 @@
../../../semver/bin/semver.js
+64
View File
@@ -0,0 +1,64 @@
{
"name": "pkg-fetch",
"version": "3.4.2",
"description": "Compiles and stores base binaries for pkg",
"main": "lib-es5/index.js",
"license": "MIT",
"repository": "vercel/pkg-fetch",
"bin": {
"pkg-fetch": "lib-es5/bin.js"
},
"files": [
"lib-es5/*.js",
"lib-es5/*.ts",
"patches/*"
],
"dependencies": {
"chalk": "^4.1.2",
"fs-extra": "^9.1.0",
"https-proxy-agent": "^5.0.0",
"node-fetch": "^2.6.6",
"progress": "^2.0.3",
"semver": "^7.3.5",
"tar-fs": "^2.1.1",
"yargs": "^16.2.0"
},
"devDependencies": {
"@types/fs-extra": "^9.0.13",
"@types/node": "^14.17.32",
"@types/node-fetch": "^2.5.12",
"@types/progress": "^2.0.5",
"@types/semver": "^7.3.9",
"@types/tar-fs": "^2.0.1",
"@types/yargs": "^16.0.4",
"@typescript-eslint/eslint-plugin": "^4.33.0",
"@typescript-eslint/parser": "^4.33.0",
"eslint": "^7.32.0",
"eslint-config-airbnb-base": "^14.2.1",
"eslint-config-prettier": "^8.3.0",
"eslint-import-resolver-typescript": "^2.5.0",
"eslint-plugin-import": "^2.25.2",
"lint-staged": "^10.5.4",
"prettier": "^2.4.1",
"rimraf": "^3.0.2",
"simple-git-hooks": ">=2.7.0",
"typescript": "^4.4.4"
},
"scripts": {
"build": "rimraf lib-es5 && tsc --build lib",
"bin": "node lib-es5/bin.js",
"lint": "eslint lib",
"prepare": "npm run build",
"prepublishOnly": "npm run lint",
"start": "node lib-es5/bin.js"
},
"prettier": {
"singleQuote": true
},
"simple-git-hooks": {
"pre-commit": "npx lint-staged"
},
"lint-staged": {
"*.{js,css,md}": "prettier --write"
}
}
+568
View File
@@ -0,0 +1,568 @@
--- node/deps/v8/include/v8.h
+++ node/deps/v8/include/v8.h
@@ -8137,10 +8137,14 @@
*/
static void SetFlagsFromCommandLine(int* argc,
char** argv,
bool remove_flags);
+ static void EnableCompilationForSourcelessUse();
+ static void DisableCompilationForSourcelessUse();
+ static void FixSourcelessScript(Isolate* v8_isolate, Local<UnboundScript> script);
+
/** Get the version string. */
static const char* GetVersion();
/**
* Initializes V8. This function needs to be called before the first Isolate
--- node/deps/v8/src/api.cc
+++ node/deps/v8/src/api.cc
@@ -914,10 +914,42 @@
void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
}
+bool save_lazy;
+bool save_predictable;
+
+
+void V8::EnableCompilationForSourcelessUse() {
+ save_lazy = i::FLAG_lazy;
+ i::FLAG_lazy = false;
+ save_predictable = i::FLAG_predictable;
+ i::FLAG_predictable = true;
+ i::CpuFeatures::Reinitialize();
+ i::CpuFeatures::Probe(true);
+}
+
+
+void V8::DisableCompilationForSourcelessUse() {
+ i::FLAG_lazy = save_lazy;
+ i::FLAG_predictable = save_predictable;
+ i::CpuFeatures::Reinitialize();
+ i::CpuFeatures::Probe(false);
+}
+
+
+void V8::FixSourcelessScript(Isolate* v8_isolate, Local<UnboundScript> script) {
+ auto isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
+ auto object = i::Handle<i::HeapObject>::cast(Utils::OpenHandle(*script));
+ i::Handle<i::SharedFunctionInfo> function_info(
+ i::SharedFunctionInfo::cast(*object), object->GetIsolate());
+ auto s = reinterpret_cast<i::Script*>(function_info->script());
+ s->set_source(isolate->heap()->undefined_value());
+}
+
+
RegisteredExtension* RegisteredExtension::first_extension_ = nullptr;
RegisteredExtension::RegisteredExtension(Extension* extension)
: extension_(extension) { }
--- node/deps/v8/src/assembler.h
+++ node/deps/v8/src/assembler.h
@@ -302,10 +302,15 @@
}
static void PrintTarget();
static void PrintFeatures();
+ static void Reinitialize() {
+ supported_ = 0;
+ initialized_ = false;
+ }
+
private:
friend class ExternalReference;
friend class AssemblerBase;
// Flush instruction cache.
static void FlushICache(void* start, size_t size);
--- node/deps/v8/src/objects.cc
+++ node/deps/v8/src/objects.cc
@@ -13179,10 +13179,13 @@
// Check if we should print {function} as a class.
Handle<Object> maybe_class_positions = JSReceiver::GetDataProperty(
function, isolate->factory()->class_positions_symbol());
if (maybe_class_positions->IsTuple2()) {
+ if (Script::cast(shared_info->script())->source()->IsUndefined(isolate)) {
+ return isolate->factory()->NewStringFromAsciiChecked("class {}");
+ }
Tuple2* class_positions = Tuple2::cast(*maybe_class_positions);
int start_position = Smi::ToInt(class_positions->value1());
int end_position = Smi::ToInt(class_positions->value2());
Handle<String> script_source(
String::cast(Script::cast(shared_info->script())->source()), isolate);
--- node/deps/v8/src/parsing/parsing.cc
+++ node/deps/v8/src/parsing/parsing.cc
@@ -18,10 +18,11 @@
namespace parsing {
bool ParseProgram(ParseInfo* info, Isolate* isolate) {
DCHECK(info->is_toplevel());
DCHECK_NULL(info->literal());
+ if (info->script()->source()->IsUndefined(isolate)) return false;
VMState<PARSER> state(isolate);
// Create a character stream for the parser.
Handle<String> source(String::cast(info->script()->source()), isolate);
@@ -55,10 +56,11 @@
bool ParseFunction(ParseInfo* info, Handle<SharedFunctionInfo> shared_info,
Isolate* isolate) {
DCHECK(!info->is_toplevel());
DCHECK(!shared_info.is_null());
DCHECK_NULL(info->literal());
+ if (info->script()->source()->IsUndefined(isolate)) return false;
// Create a character stream for the parser.
Handle<String> source(String::cast(info->script()->source()), isolate);
source = String::Flatten(source);
isolate->counters()->total_parse_size()->Increment(source->length());
--- node/deps/v8/src/snapshot/code-serializer.cc
+++ node/deps/v8/src/snapshot/code-serializer.cc
@@ -401,31 +401,46 @@
SerializedCodeData::SanityCheckResult SerializedCodeData::SanityCheck(
Isolate* isolate, uint32_t expected_source_hash) const {
if (this->size_ < kHeaderSize) return INVALID_HEADER;
uint32_t magic_number = GetMagicNumber();
- if (magic_number != ComputeMagicNumber(isolate)) return MAGIC_NUMBER_MISMATCH;
+ if (magic_number != ComputeMagicNumber(isolate)) {
+ // base::OS::PrintError("Pkg: MAGIC_NUMBER_MISMATCH\n"); // TODO enable after solving v8-cache/ncc issue
+ return MAGIC_NUMBER_MISMATCH;
+ }
uint32_t version_hash = GetHeaderValue(kVersionHashOffset);
- uint32_t source_hash = GetHeaderValue(kSourceHashOffset);
uint32_t cpu_features = GetHeaderValue(kCpuFeaturesOffset);
uint32_t flags_hash = GetHeaderValue(kFlagHashOffset);
uint32_t payload_length = GetHeaderValue(kPayloadLengthOffset);
uint32_t c1 = GetHeaderValue(kChecksum1Offset);
uint32_t c2 = GetHeaderValue(kChecksum2Offset);
- if (version_hash != Version::Hash()) return VERSION_MISMATCH;
- if (source_hash != expected_source_hash) return SOURCE_MISMATCH;
- if (cpu_features != static_cast<uint32_t>(CpuFeatures::SupportedFeatures())) {
+ if (version_hash != Version::Hash()) {
+ base::OS::PrintError("Pkg: VERSION_MISMATCH\n");
+ return VERSION_MISMATCH;
+ }
+ uint32_t host_features = static_cast<uint32_t>(CpuFeatures::SupportedFeatures());
+ if (cpu_features & (~host_features)) {
+ base::OS::PrintError("Pkg: CPU_FEATURES_MISMATCH\n");
return CPU_FEATURES_MISMATCH;
}
- if (flags_hash != FlagList::Hash()) return FLAGS_MISMATCH;
+ if (flags_hash != FlagList::Hash()) {
+ base::OS::PrintError("Pkg: FLAGS_MISMATCH\n");
+ return FLAGS_MISMATCH;
+ }
uint32_t max_payload_length =
this->size_ -
POINTER_SIZE_ALIGN(kHeaderSize +
GetHeaderValue(kNumReservationsOffset) * kInt32Size +
GetHeaderValue(kNumCodeStubKeysOffset) * kInt32Size);
- if (payload_length > max_payload_length) return LENGTH_MISMATCH;
- if (!Checksum(DataWithoutHeader()).Check(c1, c2)) return CHECKSUM_MISMATCH;
+ if (payload_length > max_payload_length) {
+ base::OS::PrintError("Pkg: LENGTH_MISMATCH\n");
+ return LENGTH_MISMATCH;
+ }
+ if (!Checksum(DataWithoutHeader()).Check(c1, c2)) {
+ base::OS::PrintError("Pkg: CHECKSUM_MISMATCH\n");
+ return CHECKSUM_MISMATCH;
+ }
return CHECK_SUCCESS;
}
uint32_t SerializedCodeData::SourceHash(Handle<String> source) {
return source->length();
--- node/lib/child_process.js
+++ node/lib/child_process.js
@@ -108,11 +108,11 @@
}
options.execPath = options.execPath || process.execPath;
options.shell = false;
- return spawn(options.execPath, args, options);
+ return exports.spawn(options.execPath, args, options);
};
exports._forkChild = function _forkChild(fd) {
// set process.send()
--- node/lib/internal/bootstrap/loaders.js
+++ node/lib/internal/bootstrap/loaders.js
@@ -337,11 +337,11 @@
// (code, filename, lineOffset, columnOffset
// cachedData, produceCachedData, parsingContext)
const script = new ContextifyScript(
source, this.filename, 0, 0,
- cache, false, undefined
+ cache, false, undefined, false
);
// This will be used to create code cache in tools/generate_code_cache.js
this.script = script;
--- node/lib/internal/bootstrap/node.js
+++ node/lib/internal/bootstrap/node.js
@@ -213,10 +213,47 @@
// There are various modes that Node can run in. The most common two
// are running from a script and running the REPL - but there are a few
// others like the debugger or running --eval arguments. Here we decide
// which mode we run in.
+
+ (function () {
+ var fs = NativeModule.require('fs');
+ var vm = NativeModule.require('vm');
+ function readPrelude (fd) {
+ var PAYLOAD_POSITION = '// PAYLOAD_POSITION //' | 0;
+ var PAYLOAD_SIZE = '// PAYLOAD_SIZE //' | 0;
+ var PRELUDE_POSITION = '// PRELUDE_POSITION //' | 0;
+ var PRELUDE_SIZE = '// PRELUDE_SIZE //' | 0;
+ if (!PRELUDE_POSITION) {
+ // no prelude - remove entrypoint from argv[1]
+ process.argv.splice(1, 1);
+ return { undoPatch: true };
+ }
+ var prelude = Buffer.alloc(PRELUDE_SIZE);
+ var read = fs.readSync(fd, prelude, 0, PRELUDE_SIZE, PRELUDE_POSITION);
+ if (read !== PRELUDE_SIZE) {
+ console.error('Pkg: Error reading from file.');
+ process.exit(1);
+ }
+ var s = new vm.Script(prelude, { filename: 'pkg/prelude/bootstrap.js' });
+ var fn = s.runInThisContext();
+ return fn(process, NativeModule.require,
+ console, fd, PAYLOAD_POSITION, PAYLOAD_SIZE);
+ }
+ (function () {
+ var fd = fs.openSync(process.execPath, 'r');
+ var result = readPrelude(fd);
+ if (result && result.undoPatch) {
+ var bindingFs = process.binding('fs');
+ fs.internalModuleStat = bindingFs.internalModuleStat;
+ fs.internalModuleReadJSON = bindingFs.internalModuleReadJSON;
+ fs.closeSync(fd);
+ }
+ }());
+ }());
+
if (internalBinding('worker').getEnvMessagePort() !== undefined) {
// This means we are in a Worker context, and any script execution
// will be directed by the worker module.
NativeModule.require('internal/worker').setupChild(evalScript);
} else if (NativeModule.exists('_third_party_main')) {
--- node/lib/internal/modules/cjs/loader.js
+++ node/lib/internal/modules/cjs/loader.js
@@ -27,14 +27,12 @@
const vm = require('vm');
const assert = require('assert').ok;
const fs = require('fs');
const internalFS = require('internal/fs/utils');
const path = require('path');
-const {
- internalModuleReadJSON,
- internalModuleStat
-} = process.binding('fs');
+const internalModuleReadJSON = function (f) { return require('fs').internalModuleReadJSON(f); };
+const internalModuleStat = function (f) { return require('fs').internalModuleStat(f); };
const { safeGetenv } = process.binding('util');
const {
makeRequireFunction,
normalizeReferrerURL,
requireDepth,
--- node/lib/vm.js
+++ node/lib/vm.js
@@ -55,10 +55,11 @@
columnOffset = 0,
cachedData,
produceCachedData = false,
importModuleDynamically,
[kParsingContext]: parsingContext,
+ sourceless = false,
} = options;
if (typeof filename !== 'string') {
throw new ERR_INVALID_ARG_TYPE('options.filename', 'string', filename);
}
@@ -84,11 +85,12 @@
filename,
lineOffset,
columnOffset,
cachedData,
produceCachedData,
- parsingContext);
+ parsingContext,
+ sourceless);
} catch (e) {
throw e; /* node-do-not-add-exception-line */
}
if (importModuleDynamically !== undefined) {
--- node/src/inspector_agent.cc
+++ node/src/inspector_agent.cc
@@ -705,12 +705,10 @@
CHECK_EQ(0, uv_async_init(parent_env_->event_loop(),
&start_io_thread_async,
StartIoThreadAsyncCallback));
uv_unref(reinterpret_cast<uv_handle_t*>(&start_io_thread_async));
start_io_thread_async.data = this;
- // Ignore failure, SIGUSR1 won't work, but that should not block node start.
- StartDebugSignalHandler();
}
bool wait_for_connect = options->wait_for_connect();
if (parent_handle_) {
wait_for_connect = parent_handle_->WaitForConnect();
--- node/src/node.cc
+++ node/src/node.cc
@@ -2369,17 +2369,10 @@
}
inline void PlatformInit() {
#ifdef __POSIX__
-#if HAVE_INSPECTOR
- sigset_t sigmask;
- sigemptyset(&sigmask);
- sigaddset(&sigmask, SIGUSR1);
- const int err = pthread_sigmask(SIG_SETMASK, &sigmask, nullptr);
-#endif // HAVE_INSPECTOR
-
// Make sure file descriptors 0-2 are valid before we start logging anything.
for (int fd = STDIN_FILENO; fd <= STDERR_FILENO; fd += 1) {
struct stat ignored;
if (fstat(fd, &ignored) == 0)
continue;
@@ -2389,14 +2382,10 @@
ABORT();
if (fd != open("/dev/null", O_RDWR))
ABORT();
}
-#if HAVE_INSPECTOR
- CHECK_EQ(err, 0);
-#endif // HAVE_INSPECTOR
-
#ifndef NODE_SHARED_MODE
// Restore signal dispositions, the parent process may have changed them.
struct sigaction act;
memset(&act, 0, sizeof(act));
--- node/src/node_contextify.cc
+++ node/src/node_contextify.cc
@@ -63,10 +63,11 @@
using v8::String;
using v8::Symbol;
using v8::TryCatch;
using v8::Uint32;
using v8::UnboundScript;
+using v8::V8;
using v8::Value;
using v8::WeakCallbackInfo;
using v8::WeakCallbackType;
// The vm module executes code in a sandboxed environment with a different
@@ -638,15 +639,16 @@
Local<Integer> line_offset;
Local<Integer> column_offset;
Local<ArrayBufferView> cached_data_buf;
bool produce_cached_data = false;
Local<Context> parsing_context = context;
+ bool sourceless = false;
if (argc > 2) {
// new ContextifyScript(code, filename, lineOffset, columnOffset,
// cachedData, produceCachedData, parsingContext)
- CHECK_EQ(argc, 7);
+ CHECK_EQ(argc, 8);
CHECK(args[2]->IsNumber());
line_offset = args[2].As<Integer>();
CHECK(args[3]->IsNumber());
column_offset = args[3].As<Integer>();
if (!args[4]->IsUndefined()) {
@@ -661,10 +663,11 @@
ContextifyContext::ContextFromContextifiedSandbox(
env, args[6].As<Object>());
CHECK_NOT_NULL(sandbox);
parsing_context = sandbox->context();
}
+ sourceless = args[7]->IsTrue();
} else {
line_offset = Integer::New(isolate, 0);
column_offset = Integer::New(isolate, 0);
}
@@ -715,10 +718,14 @@
TryCatch try_catch(isolate);
Environment::ShouldNotAbortOnUncaughtScope no_abort_scope(env);
Context::Scope scope(parsing_context);
+ if (sourceless && produce_cached_data) {
+ V8::EnableCompilationForSourcelessUse();
+ }
+
MaybeLocal<UnboundScript> v8_script = ScriptCompiler::CompileUnboundScript(
isolate,
&source,
compile_options);
@@ -730,10 +737,17 @@
TRACING_CATEGORY_NODE2(vm, script),
"ContextifyScript::New",
contextify_script);
return;
}
+
+ if (sourceless && compile_options == ScriptCompiler::kConsumeCodeCache) {
+ if (!source.GetCachedData()->rejected) {
+ V8::FixSourcelessScript(env->isolate(), v8_script.ToLocalChecked());
+ }
+ }
+
contextify_script->script_.Reset(isolate, v8_script.ToLocalChecked());
if (compile_options == ScriptCompiler::kConsumeCodeCache) {
args.This()->Set(
env->cached_data_rejected_string(),
@@ -751,10 +765,15 @@
}
args.This()->Set(
env->cached_data_produced_string(),
Boolean::New(isolate, cached_data_produced));
}
+
+ if (sourceless && produce_cached_data) {
+ V8::DisableCompilationForSourcelessUse();
+ }
+
TRACE_EVENT_NESTABLE_ASYNC_END0(
TRACING_CATEGORY_NODE2(vm, script),
"ContextifyScript::New",
contextify_script);
}
--- node/src/node_main.cc
+++ node/src/node_main.cc
@@ -20,10 +20,12 @@
// USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "node.h"
#include <stdio.h>
+int reorder(int argc, char** argv);
+
#ifdef _WIN32
#include <windows.h>
#include <VersionHelpers.h>
#include <WinError.h>
@@ -67,11 +69,11 @@
exit(1);
}
}
argv[argc] = nullptr;
// Now that conversion is done, we can finally start.
- return node::Start(argc, argv);
+ return reorder(argc, argv);
}
#else
// UNIX
#ifdef __linux__
#include <elf.h>
@@ -119,8 +121,75 @@
#endif
// Disable stdio buffering, it interacts poorly with printf()
// calls elsewhere in the program (e.g., any logging from V8.)
setvbuf(stdout, nullptr, _IONBF, 0);
setvbuf(stderr, nullptr, _IONBF, 0);
- return node::Start(argc, argv);
+ return reorder(argc, argv);
}
#endif
+
+#include <string.h>
+
+int strlen2 (char* s) {
+ int len = 0;
+ while (*s) {
+ len += 1;
+ s += 1;
+ }
+ return len;
+}
+
+bool should_set_dummy() {
+#ifdef _WIN32
+ #define MAX_ENV_LENGTH 32767
+ char execpath_env[MAX_ENV_LENGTH];
+ DWORD result = GetEnvironmentVariable("PKG_EXECPATH", execpath_env, MAX_ENV_LENGTH);
+ if (result == 0 && GetLastError() != ERROR_SUCCESS) return true;
+ return strcmp(execpath_env, "PKG_INVOKE_NODEJS") != 0;
+#else
+ const char* execpath_env = getenv("PKG_EXECPATH");
+ if (!execpath_env) return true;
+ return strcmp(execpath_env, "PKG_INVOKE_NODEJS") != 0;
+#endif
+}
+
+// for uv_setup_args
+int adjacent(int argc, char** argv) {
+ size_t size = 0;
+ for (int i = 0; i < argc; i++) {
+ size += strlen(argv[i]) + 1;
+ }
+ char* args = new char[size];
+ size_t pos = 0;
+ for (int i = 0; i < argc; i++) {
+ memcpy(&args[pos], argv[i], strlen(argv[i]) + 1);
+ argv[i] = &args[pos];
+ pos += strlen(argv[i]) + 1;
+ }
+ return node::Start(argc, argv);
+}
+
+volatile char* BAKERY = (volatile char*) "\0// BAKERY // BAKERY " \
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY " \
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY " \
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY ";
+
+int reorder(int argc, char** argv) {
+ int i;
+ char** nargv = new char*[argc + 64];
+ int c = 0;
+ nargv[c++] = argv[0];
+ char* bakery = (char*) BAKERY;
+ while (true) {
+ size_t width = strlen2(bakery);
+ if (width == 0) break;
+ nargv[c++] = bakery;
+ bakery += width + 1;
+ }
+ if (should_set_dummy()) {
+ nargv[c++] = (char*) "PKG_DUMMY_ENTRYPOINT";
+ }
+ for (i = 1; i < argc; i++) {
+ nargv[c++] = argv[i];
+ }
+ return adjacent(c, nargv);
+}
--- node/src/node_options.cc
+++ node/src/node_options.cc
@@ -55,10 +55,11 @@
// XXX: If you add an option here, please also add it to doc/node.1 and
// doc/api/cli.md
// TODO(addaleax): Make that unnecessary.
DebugOptionsParser::DebugOptionsParser() {
+ return;
#if HAVE_INSPECTOR
AddOption("--inspect-port",
"set host:port for inspector",
&DebugOptions::host_port,
kAllowedInEnvironment);
+679
View File
@@ -0,0 +1,679 @@
--- node/common.gypi
+++ node/common.gypi
@@ -188,17 +188,28 @@
'v8_enable_handle_zapping': 0,
'pgo_generate': ' -fprofile-generate ',
'pgo_use': ' -fprofile-use -fprofile-correction ',
- 'lto': ' -flto=4 -fuse-linker-plugin -ffat-lto-objects ',
'conditions': [
['node_shared != "true"', {
'MSVC_runtimeType': 0 # MultiThreaded (/MT)
}, {
'MSVC_runtimeType': 2 # MultiThreadedDLL (/MD)
}],
+ ['llvm_version=="0.0"', {
+ 'lto': ' -flto=4 -ffat-lto-objects ', # GCC
+ }, {
+ 'lto': ' -flto ', # Clang
+ }],
],
},
'cflags': [ '-O3' ],
'conditions': [
+ ['enable_lto=="true"', {
+ 'cflags': ['<(lto)'],
+ 'ldflags': ['<(lto)'],
+ 'xcode_settings': {
+ 'LLVM_LTO': 'YES',
+ },
+ }],
['OS=="solaris"', {
# pull in V8's postmortem metadata
'ldflags': [ '-Wl,-z,allextract' ]
@@ -216,10 +227,6 @@
'cflags': ['<(pgo_use)'],
'ldflags': ['<(pgo_use)'],
},],
- ['enable_lto=="true"', {
- 'cflags': ['<(lto)'],
- 'ldflags': ['<(lto)'],
- },],
],
},],
['OS == "android"', {
--- node/configure.py
+++ node/configure.py
@@ -154,7 +154,7 @@ parser.add_option("--enable-lto",
action="store_true",
dest="enable_lto",
help="Enable compiling with lto of a binary. This feature is only available "
- "on linux with gcc and g++ 5.4.1 or newer.")
+ "with gcc 5.4.1+ or clang 3.9.1+.")
parser.add_option("--link-module",
action="append",
@@ -842,6 +842,7 @@ def get_gas_version(cc):
# quite prepared to go that far yet.
def check_compiler(o):
if sys.platform == 'win32':
+ o['variables']['llvm_version'] = '0.0'
if not options.openssl_no_asm and options.dest_cpu in ('x86', 'x64'):
nasm_version = get_nasm_version('nasm')
o['variables']['nasm_version'] = nasm_version
@@ -1021,12 +1022,19 @@ def configure_mips(o, target_arch):
host_byteorder = 'little' if target_arch in ('mipsel', 'mips64el') else 'big'
o['variables']['v8_host_byteorder'] = host_byteorder
+def clang_version_ge(version_checked):
+ for compiler in [(CC, 'c'), (CXX, 'c++')]:
+ ok, is_clang, clang_version, gcc_version = \
+ try_check_compiler(compiler[0], compiler[1])
+ if is_clang and clang_version >= version_checked:
+ return True
+ return False
def gcc_version_ge(version_checked):
for compiler in [(CC, 'c'), (CXX, 'c++')]:
- ok, is_clang, clang_version, compiler_version = \
+ ok, is_clang, clang_version, gcc_version = \
try_check_compiler(compiler[0], compiler[1])
- if is_clang or compiler_version < version_checked:
+ if is_clang or gcc_version < version_checked:
return False
return True
@@ -1103,18 +1111,19 @@ def configure_node(o):
o['variables']['enable_pgo_generate'] = b(options.enable_pgo_generate)
o['variables']['enable_pgo_use'] = b(options.enable_pgo_use)
- if flavor != 'linux' and (options.enable_lto):
+ if flavor == 'win' and (options.enable_lto):
raise Exception(
- 'The lto option is supported only on linux.')
-
- if flavor == 'linux':
- if options.enable_lto:
- version_checked = (5, 4, 1)
- if not gcc_version_ge(version_checked):
- version_checked_str = ".".join(map(str, version_checked))
- raise Exception(
- 'The option --enable-lto is supported for gcc and gxx %s'
- ' or newer only.' % (version_checked_str))
+ 'Use Link Time Code Generation instead.')
+
+ if options.enable_lto:
+ gcc_version_checked = (5, 4, 1)
+ clang_version_checked = (3, 9, 1)
+ if not gcc_version_ge(gcc_version_checked) and not clang_version_ge(clang_version_checked):
+ gcc_version_checked_str = ".".join(map(str, gcc_version_checked))
+ clang_version_checked_str = ".".join(map(str, clang_version_checked))
+ raise Exception(
+ 'The option --enable-lto is supported for gcc %s+'
+ 'or clang %s+ only.' % (gcc_version_checked_str, clang_version_checked_str))
o['variables']['enable_lto'] = b(options.enable_lto)
--- node/deps/v8/include/v8.h
+++ node/deps/v8/include/v8.h
@@ -9047,6 +9047,10 @@ class V8_EXPORT V8 {
char** argv,
bool remove_flags);
+ static void EnableCompilationForSourcelessUse();
+ static void DisableCompilationForSourcelessUse();
+ static void FixSourcelessScript(Isolate* v8_isolate, Local<UnboundScript> script);
+
/** Get the version string. */
static const char* GetVersion();
--- node/deps/v8/src/api/api.cc
+++ node/deps/v8/src/api/api.cc
@@ -915,6 +915,34 @@ void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
}
+
+bool save_lazy;
+bool save_predictable;
+
+
+void V8::EnableCompilationForSourcelessUse() {
+ save_lazy = i::FLAG_lazy;
+ i::FLAG_lazy = false;
+ save_predictable = i::FLAG_predictable;
+ i::FLAG_predictable = true;
+}
+
+
+void V8::DisableCompilationForSourcelessUse() {
+ i::FLAG_lazy = save_lazy;
+ i::FLAG_predictable = save_predictable;
+}
+
+
+void V8::FixSourcelessScript(Isolate* v8_isolate, Local<UnboundScript> unbound_script) {
+ auto isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
+ auto function_info =
+ i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(*unbound_script));
+ i::Handle<i::Script> script(i::Script::cast(function_info->script()), isolate);
+ script->set_source(i::ReadOnlyRoots(isolate).undefined_value());
+}
+
+
RegisteredExtension* RegisteredExtension::first_extension_ = nullptr;
RegisteredExtension::RegisteredExtension(std::unique_ptr<Extension> extension)
--- node/deps/v8/src/codegen/compiler.cc
+++ node/deps/v8/src/codegen/compiler.cc
@@ -2010,7 +2010,7 @@ MaybeHandle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
source, script_details.name_obj, script_details.line_offset,
script_details.column_offset, origin_options, isolate->native_context(),
language_mode);
- if (!maybe_result.is_null()) {
+ if (!maybe_result.is_null() && source_length) {
compile_timer.set_hit_isolate_cache();
} else if (can_consume_code_cache) {
compile_timer.set_consuming_code_cache();
--- node/deps/v8/src/objects/js-objects.cc
+++ node/deps/v8/src/objects/js-objects.cc
@@ -5480,6 +5480,9 @@ Handle<String> JSFunction::ToString(Handle<JSFunction> function) {
Handle<Object> maybe_class_positions = JSReceiver::GetDataProperty(
function, isolate->factory()->class_positions_symbol());
if (maybe_class_positions->IsClassPositions()) {
+ if (String::cast(Script::cast(shared_info->script()).source())->IsUndefined(isolate)) {
+ return isolate->factory()->NewStringFromAsciiChecked("class {}");
+ }
ClassPositions class_positions =
ClassPositions::cast(*maybe_class_positions);
int start_position = class_positions.start();
--- node/deps/v8/src/objects/shared-function-info-inl.h
+++ node/deps/v8/src/objects/shared-function-info-inl.h
@@ -508,6 +508,14 @@ bool SharedFunctionInfo::ShouldFlushBytecode(BytecodeFlushMode mode) {
Object data = function_data();
if (!data.IsBytecodeArray()) return false;
+ Object script_obj = script();
+ if (!script_obj.IsUndefined()) {
+ Script script = Script::cast(script_obj);
+ if (script.source().IsUndefined()) {
+ return false;
+ }
+ }
+
if (mode == BytecodeFlushMode::kStressFlushBytecode) return true;
BytecodeArray bytecode = BytecodeArray::cast(data);
--- node/deps/v8/src/parsing/parsing.cc
+++ node/deps/v8/src/parsing/parsing.cc
@@ -22,6 +22,7 @@ bool ParseProgram(ParseInfo* info, Isolate* isolate,
ReportErrorsAndStatisticsMode mode) {
DCHECK(info->is_toplevel());
DCHECK_NULL(info->literal());
+ if (String::cast(info->script()->source())->IsUndefined(isolate)) return false;
VMState<PARSER> state(isolate);
@@ -62,6 +63,7 @@ bool ParseFunction(ParseInfo* info, Handle<SharedFunctionInfo> shared_info,
DCHECK(!info->is_toplevel());
DCHECK(!shared_info.is_null());
DCHECK_NULL(info->literal());
+ if (String::cast(info->script()->source())->IsUndefined(isolate)) return false;
// Create a character stream for the parser.
Handle<String> source(String::cast(info->script()->source()), isolate);
--- node/deps/v8/src/snapshot/code-serializer.cc
+++ node/deps/v8/src/snapshot/code-serializer.cc
@@ -412,22 +412,35 @@ SerializedCodeData::SanityCheckResult SerializedCodeData::SanityCheck(
Isolate* isolate, uint32_t expected_source_hash) const {
if (this->size_ < kHeaderSize) return INVALID_HEADER;
uint32_t magic_number = GetMagicNumber();
- if (magic_number != kMagicNumber) return MAGIC_NUMBER_MISMATCH;
+ if (magic_number != kMagicNumber) {
+ // base::OS::PrintError("Pkg: MAGIC_NUMBER_MISMATCH\n"); // TODO enable after solving v8-cache/ncc issue
+ return MAGIC_NUMBER_MISMATCH;
+ }
uint32_t version_hash = GetHeaderValue(kVersionHashOffset);
- uint32_t source_hash = GetHeaderValue(kSourceHashOffset);
uint32_t flags_hash = GetHeaderValue(kFlagHashOffset);
uint32_t payload_length = GetHeaderValue(kPayloadLengthOffset);
uint32_t c1 = GetHeaderValue(kChecksumPartAOffset);
uint32_t c2 = GetHeaderValue(kChecksumPartBOffset);
- if (version_hash != Version::Hash()) return VERSION_MISMATCH;
- if (source_hash != expected_source_hash) return SOURCE_MISMATCH;
- if (flags_hash != FlagList::Hash()) return FLAGS_MISMATCH;
+ if (version_hash != Version::Hash()) {
+ base::OS::PrintError("Pkg: VERSION_MISMATCH\n");
+ return VERSION_MISMATCH;
+ }
+ if (flags_hash != FlagList::Hash()) {
+ // base::OS::PrintError("Pkg: FLAGS_MISMATCH\n");
+ return FLAGS_MISMATCH;
+ }
uint32_t max_payload_length =
this->size_ -
POINTER_SIZE_ALIGN(kHeaderSize +
GetHeaderValue(kNumReservationsOffset) * kInt32Size);
- if (payload_length > max_payload_length) return LENGTH_MISMATCH;
- if (!Checksum(ChecksummedContent()).Check(c1, c2)) return CHECKSUM_MISMATCH;
+ if (payload_length > max_payload_length) {
+ base::OS::PrintError("Pkg: LENGTH_MISMATCH\n");
+ return LENGTH_MISMATCH;
+ }
+ if (!Checksum(ChecksummedContent()).Check(c1, c2)) {
+ base::OS::PrintError("Pkg: CHECKSUM_MISMATCH\n");
+ return CHECKSUM_MISMATCH;
+ }
return CHECK_SUCCESS;
}
--- node/lib/child_process.js
+++ node/lib/child_process.js
@@ -118,7 +118,7 @@ function fork(modulePath /* , args, options */) {
options.execPath = options.execPath || process.execPath;
options.shell = false;
- return spawn(options.execPath, args, options);
+ return module.exports.spawn(options.execPath, args, options);
}
function _forkChild(fd, serializationMode) {
index 0000000000..fb2d47f52b
--- /dev/null
+++ node/lib/internal/bootstrap/pkg.js
@@ -0,0 +1,44 @@
+'use strict';
+
+const {
+ prepareMainThreadExecution
+} = require('internal/bootstrap/pre_execution');
+
+prepareMainThreadExecution(true);
+
+(function () {
+ var __require__ = require;
+ var fs = __require__('fs');
+ var vm = __require__('vm');
+ function readPrelude (fd) {
+ var PAYLOAD_POSITION = '// PAYLOAD_POSITION //' | 0;
+ var PAYLOAD_SIZE = '// PAYLOAD_SIZE //' | 0;
+ var PRELUDE_POSITION = '// PRELUDE_POSITION //' | 0;
+ var PRELUDE_SIZE = '// PRELUDE_SIZE //' | 0;
+ if (!PRELUDE_POSITION) {
+ // no prelude - remove entrypoint from argv[1]
+ process.argv.splice(1, 1);
+ return { undoPatch: true };
+ }
+ var prelude = Buffer.alloc(PRELUDE_SIZE);
+ var read = fs.readSync(fd, prelude, 0, PRELUDE_SIZE, PRELUDE_POSITION);
+ if (read !== PRELUDE_SIZE) {
+ console.error('Pkg: Error reading from file.');
+ process.exit(1);
+ }
+ var s = new vm.Script(prelude, { filename: 'pkg/prelude/bootstrap.js' });
+ var fn = s.runInThisContext();
+ return fn(process, __require__,
+ console, fd, PAYLOAD_POSITION, PAYLOAD_SIZE);
+ }
+ (function () {
+ var fd = fs.openSync(process.execPath, 'r');
+ var result = readPrelude(fd);
+ if (result && result.undoPatch) {
+ var bindingFs = process.binding('fs');
+ fs.internalModuleStat = bindingFs.internalModuleStat;
+ fs.internalModuleReadJSON = bindingFs.internalModuleReadJSON;
+ fs.closeSync(fd);
+ }
+ }());
+}());
--- node/lib/internal/bootstrap/pre_execution.js
+++ node/lib/internal/bootstrap/pre_execution.js
@@ -14,7 +14,12 @@ const { Buffer } = require('buffer');
const { ERR_MANIFEST_ASSERT_INTEGRITY } = require('internal/errors').codes;
const assert = require('internal/assert');
+let _alreadyPrepared = false;
+
function prepareMainThreadExecution(expandArgv1 = false) {
+ if (_alreadyPrepared === true) return;
+ _alreadyPrepared = true;
+
// Patch the process object with legacy properties and normalizations
patchProcessObject(expandArgv1);
setupTraceCategoryState();
@@ -89,7 +94,7 @@ function patchProcessObject(expandArgv1) {
});
process.argv[0] = process.execPath;
- if (expandArgv1 && process.argv[1] && !process.argv[1].startsWith('-')) {
+ if (expandArgv1 && process.argv[1] && !process.argv[1].startsWith('-') && process.argv[1] !== 'PKG_DUMMY_ENTRYPOINT') {
// Expand process.argv[1] into a full path.
const path = require('path');
try {
--- node/lib/internal/modules/cjs/loader.js
+++ node/lib/internal/modules/cjs/loader.js
@@ -66,7 +66,7 @@ const fs = require('fs');
const internalFS = require('internal/fs/utils');
const path = require('path');
const { sep } = path;
-const { internalModuleStat } = internalBinding('fs');
+const internalModuleStat = function (f) { return require('fs').internalModuleStat(f); };
const packageJsonReader = require('internal/modules/package_json_reader');
const { safeGetenv } = internalBinding('credentials');
const {
--- node/lib/internal/modules/package_json_reader.js
+++ node/lib/internal/modules/package_json_reader.js
@@ -1,7 +1,7 @@
'use strict';
const { SafeMap } = primordials;
-const { internalModuleReadJSON } = internalBinding('fs');
+const internalModuleReadJSON = function (f) { return require('fs').internalModuleReadJSON(f); };
const { pathToFileURL } = require('url');
const { toNamespacedPath } = require('path');
--- node/lib/vm.js
+++ node/lib/vm.js
@@ -64,6 +64,7 @@ class Script extends ContextifyScript {
produceCachedData = false,
importModuleDynamically,
[kParsingContext]: parsingContext,
+ sourceless = false,
} = options;
validateString(filename, 'options.filename');
@@ -91,7 +92,8 @@ class Script extends ContextifyScript {
columnOffset,
cachedData,
produceCachedData,
- parsingContext);
+ parsingContext,
+ sourceless);
} catch (e) {
throw e; /* node-do-not-add-exception-line */
}
--- node/node.gyp
+++ node/node.gyp
@@ -30,6 +30,7 @@
'lib/internal/bootstrap/environment.js',
'lib/internal/bootstrap/loaders.js',
'lib/internal/bootstrap/node.js',
+ 'lib/internal/bootstrap/pkg.js',
'lib/internal/bootstrap/pre_execution.js',
'lib/internal/bootstrap/switches/does_own_process_state.js',
'lib/internal/bootstrap/switches/does_not_own_process_state.js',
@@ -430,6 +431,19 @@
'OTHER_LDFLAGS': [ '-Wl,-rpath,@loader_path', ],
},
}],
+ [ 'enable_lto=="true"', {
+ 'xcode_settings': {
+ 'OTHER_LDFLAGS': [
+ # man ld -export_dynamic:
+ # Preserves all global symbols in main executables during LTO.
+ # Without this option, Link Time Optimization is allowed to
+ # inline and remove global functions. This option is used when
+ # a main executable may load a plug-in which requires certain
+ # symbols from the main executable.
+ '-Wl,-export_dynamic',
+ ],
+ },
+ }],
['OS=="win"', {
'libraries': [
'Dbghelp.lib',
--- node/src/inspector_agent.cc
+++ node/src/inspector_agent.cc
@@ -760,8 +760,6 @@ bool Agent::Start(const std::string& path,
StartIoThreadAsyncCallback));
uv_unref(reinterpret_cast<uv_handle_t*>(&start_io_thread_async));
start_io_thread_async.data = this;
- // Ignore failure, SIGUSR1 won't work, but that should not block node start.
- StartDebugSignalHandler();
parent_env_->AddCleanupHook([](void* data) {
Environment* env = static_cast<Environment*>(data);
--- node/src/node.cc
+++ node/src/node.cc
@@ -332,6 +332,9 @@ MaybeLocal<Value> Environment::BootstrapNode() {
return scope.EscapeMaybe(result);
}
+static
+MaybeLocal<Value> StartExecution(Environment* env, const char* main_script_id);
+
MaybeLocal<Value> Environment::RunBootstrapping() {
EscapableHandleScope scope(isolate_);
@@ -355,6 +358,8 @@ MaybeLocal<Value> Environment::RunBootstrapping() {
set_has_run_bootstrapping_code(true);
+ USE(StartExecution(this, "internal/bootstrap/pkg"));
+
return scope.Escape(result);
}
@@ -515,13 +520,6 @@ static struct {
inline void PlatformInit() {
#ifdef __POSIX__
-#if HAVE_INSPECTOR
- sigset_t sigmask;
- sigemptyset(&sigmask);
- sigaddset(&sigmask, SIGUSR1);
- const int err = pthread_sigmask(SIG_SETMASK, &sigmask, nullptr);
-#endif // HAVE_INSPECTOR
-
// Make sure file descriptors 0-2 are valid before we start logging anything.
for (auto& s : stdio) {
const int fd = &s - stdio;
@@ -537,10 +535,6 @@ inline void PlatformInit() {
ABORT();
}
-#if HAVE_INSPECTOR
- CHECK_EQ(err, 0);
-#endif // HAVE_INSPECTOR
-
// TODO(addaleax): NODE_SHARED_MODE does not really make sense here.
#ifndef NODE_SHARED_MODE
// Restore signal dispositions, the parent process may have changed them.
--- node/src/node_contextify.cc
+++ node/src/node_contextify.cc
@@ -69,6 +69,7 @@ using v8::ScriptOrModule;
using v8::String;
using v8::Uint32;
using v8::UnboundScript;
+using v8::V8;
using v8::Value;
using v8::WeakCallbackInfo;
using v8::WeakCallbackType;
@@ -660,11 +661,12 @@ void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) {
Local<ArrayBufferView> cached_data_buf;
bool produce_cached_data = false;
Local<Context> parsing_context = context;
+ bool sourceless = false;
if (argc > 2) {
// new ContextifyScript(code, filename, lineOffset, columnOffset,
// cachedData, produceCachedData, parsingContext)
- CHECK_EQ(argc, 7);
+ CHECK_EQ(argc, 8);
CHECK(args[2]->IsNumber());
line_offset = args[2].As<Integer>();
CHECK(args[3]->IsNumber());
@@ -683,6 +685,7 @@ void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) {
CHECK_NOT_NULL(sandbox);
parsing_context = sandbox->context();
}
+ sourceless = args[7]->IsTrue();
} else {
line_offset = Integer::New(isolate, 0);
column_offset = Integer::New(isolate, 0);
@@ -737,6 +740,10 @@ void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) {
ShouldNotAbortOnUncaughtScope no_abort_scope(env);
Context::Scope scope(parsing_context);
+ if (sourceless && produce_cached_data) {
+ V8::EnableCompilationForSourcelessUse();
+ }
+
MaybeLocal<UnboundScript> v8_script = ScriptCompiler::CompileUnboundScript(
isolate,
&source,
@@ -753,6 +760,13 @@ void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) {
contextify_script);
return;
}
+
+ if (sourceless && compile_options == ScriptCompiler::kConsumeCodeCache) {
+ if (!source.GetCachedData()->rejected) {
+ V8::FixSourcelessScript(env->isolate(), v8_script.ToLocalChecked());
+ }
+ }
+
contextify_script->script_.Reset(isolate, v8_script.ToLocalChecked());
if (compile_options == ScriptCompiler::kConsumeCodeCache) {
@@ -778,6 +792,11 @@ void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) {
env->cached_data_produced_string(),
Boolean::New(isolate, cached_data_produced)).Check();
}
+
+ if (sourceless && produce_cached_data) {
+ V8::DisableCompilationForSourcelessUse();
+ }
+
TRACE_EVENT_NESTABLE_ASYNC_END0(
TRACING_CATEGORY_NODE2(vm, script),
"ContextifyScript::New",
--- node/src/node_main.cc
+++ node/src/node_main.cc
@@ -22,6 +22,8 @@
#include "node.h"
#include <cstdio>
+int reorder(int argc, char** argv);
+
#ifdef _WIN32
#include <windows.h>
#include <VersionHelpers.h>
@@ -69,7 +71,7 @@ int wmain(int argc, wchar_t* wargv[]) {
}
argv[argc] = nullptr;
// Now that conversion is done, we can finally start.
- return node::Start(argc, argv);
+ return reorder(argc, argv);
}
#else
// UNIX
@@ -123,6 +125,88 @@ int main(int argc, char* argv[]) {
// calls elsewhere in the program (e.g., any logging from V8.)
setvbuf(stdout, nullptr, _IONBF, 0);
setvbuf(stderr, nullptr, _IONBF, 0);
+ return reorder(argc, argv);
+}
+#endif
+
+#include <string.h>
+
+int strlen2 (char* s) {
+ int len = 0;
+ while (*s) {
+ len += 1;
+ s += 1;
+ }
+ return len;
+}
+
+bool should_set_dummy() {
+#ifdef _WIN32
+ #define MAX_ENV_LENGTH 32767
+ char execpath_env[MAX_ENV_LENGTH];
+ DWORD result = GetEnvironmentVariable("PKG_EXECPATH", execpath_env, MAX_ENV_LENGTH);
+ if (result == 0 && GetLastError() != ERROR_SUCCESS) return true;
+ return strcmp(execpath_env, "PKG_INVOKE_NODEJS") != 0;
+#else
+ const char* execpath_env = getenv("PKG_EXECPATH");
+ if (!execpath_env) return true;
+ return strcmp(execpath_env, "PKG_INVOKE_NODEJS") != 0;
+#endif
+}
+
+// for uv_setup_args
+int adjacent(int argc, char** argv) {
+ size_t size = 0;
+ for (int i = 0; i < argc; i++) {
+ size += strlen(argv[i]) + 1;
+ }
+ char* args = new char[size];
+ size_t pos = 0;
+ for (int i = 0; i < argc; i++) {
+ memcpy(&args[pos], argv[i], strlen(argv[i]) + 1);
+ argv[i] = &args[pos];
+ pos += strlen(argv[i]) + 1;
+ }
return node::Start(argc, argv);
}
+
+volatile char* BAKERY = (volatile char*) "\0// BAKERY // BAKERY " \
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY " \
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY " \
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY ";
+
+#ifdef __clang__
+__attribute__((optnone))
+#elif defined(__GNUC__)
+__attribute__((optimize(0)))
#endif
+int load_baked(char** nargv) {
+ int c = 1;
+
+ char* bakery = (char*) BAKERY;
+ while (true) {
+ size_t width = strlen2(bakery);
+ if (width == 0) break;
+ nargv[c++] = bakery;
+ bakery += width + 1;
+ }
+
+ return c;
+}
+
+int reorder(int argc, char** argv) {
+ char** nargv = new char*[argc + 64];
+
+ nargv[0] = argv[0];
+ int c = load_baked(nargv);
+
+ if (should_set_dummy()) {
+ nargv[c++] = (char*) "PKG_DUMMY_ENTRYPOINT";
+ }
+
+ for (int i = 1; i < argc; i++) {
+ nargv[c++] = argv[i];
+ }
+
+ return adjacent(c, nargv);
+}
--- node/src/node_options.cc
+++ node/src/node_options.cc
@@ -234,6 +234,7 @@ void Parse(
// TODO(addaleax): Make that unnecessary.
DebugOptionsParser::DebugOptionsParser() {
+ return;
AddOption("--inspect-port",
"set host:port for inspector",
&DebugOptions::host_port,
--- node/tools/icu/icu-generic.gyp
+++ node/tools/icu/icu-generic.gyp
@@ -52,7 +52,7 @@
'conditions': [
[ 'os_posix == 1 and OS != "mac" and OS != "ios"', {
'cflags': [ '-Wno-deprecated-declarations', '-Wno-strict-aliasing' ],
- 'cflags_cc': [ '-frtti' ],
+ 'cflags_cc': [ '-frtti', '-fno-lto' ],
'cflags_cc!': [ '-fno-rtti' ],
}],
[ 'OS == "mac" or OS == "ios"', {
+560
View File
@@ -0,0 +1,560 @@
--- node/common.gypi
+++ node/common.gypi
@@ -171,7 +171,7 @@
'MSVC_runtimeType': 2 # MultiThreadedDLL (/MD)
}],
['llvm_version=="0.0"', {
- 'lto': ' -flto=4 -fuse-linker-plugin -ffat-lto-objects ', # GCC
+ 'lto': ' -flto=4 -ffat-lto-objects ', # GCC
}, {
'lto': ' -flto ', # Clang
}],
--- node/deps/v8/include/v8.h
+++ node/deps/v8/include/v8.h
@@ -9633,6 +9633,10 @@ class V8_EXPORT V8 {
char** argv,
bool remove_flags);
+ static void EnableCompilationForSourcelessUse();
+ static void DisableCompilationForSourcelessUse();
+ static void FixSourcelessScript(Isolate* v8_isolate, Local<UnboundScript> script);
+
/** Get the version string. */
static const char* GetVersion();
--- node/deps/v8/src/api/api.cc
+++ node/deps/v8/src/api/api.cc
@@ -840,6 +840,34 @@ void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
}
+
+bool save_lazy;
+bool save_predictable;
+
+
+void V8::EnableCompilationForSourcelessUse() {
+ save_lazy = i::FLAG_lazy;
+ i::FLAG_lazy = false;
+ save_predictable = i::FLAG_predictable;
+ i::FLAG_predictable = true;
+}
+
+
+void V8::DisableCompilationForSourcelessUse() {
+ i::FLAG_lazy = save_lazy;
+ i::FLAG_predictable = save_predictable;
+}
+
+
+void V8::FixSourcelessScript(Isolate* v8_isolate, Local<UnboundScript> unbound_script) {
+ auto isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
+ auto function_info =
+ i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(*unbound_script));
+ i::Handle<i::Script> script(i::Script::cast(function_info->script()), isolate);
+ script->set_source(i::ReadOnlyRoots(isolate).undefined_value());
+}
+
+
RegisteredExtension* RegisteredExtension::first_extension_ = nullptr;
RegisteredExtension::RegisteredExtension(std::unique_ptr<Extension> extension)
--- node/deps/v8/src/codegen/compiler.cc
+++ node/deps/v8/src/codegen/compiler.cc
@@ -2365,7 +2365,7 @@ MaybeHandle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
source, script_details.name_obj, script_details.line_offset,
script_details.column_offset, origin_options, isolate->native_context(),
language_mode);
- if (!maybe_result.is_null()) {
+ if (!maybe_result.is_null() && source_length) {
compile_timer.set_hit_isolate_cache();
} else if (can_consume_code_cache) {
compile_timer.set_consuming_code_cache();
--- node/deps/v8/src/objects/js-objects.cc
+++ node/deps/v8/src/objects/js-objects.cc
@@ -5514,6 +5514,9 @@ Handle<String> JSFunction::ToString(Handle<JSFunction> function) {
Handle<Object> maybe_class_positions = JSReceiver::GetDataProperty(
function, isolate->factory()->class_positions_symbol());
if (maybe_class_positions->IsClassPositions()) {
+ if (String::cast(Script::cast(shared_info->script()).source()).IsUndefined(isolate)) {
+ return isolate->factory()->NewStringFromAsciiChecked("class {}");
+ }
ClassPositions class_positions =
ClassPositions::cast(*maybe_class_positions);
int start_position = class_positions.start();
--- node/deps/v8/src/objects/shared-function-info-inl.h
+++ node/deps/v8/src/objects/shared-function-info-inl.h
@@ -505,6 +505,14 @@ bool SharedFunctionInfo::ShouldFlushBytecode(BytecodeFlushMode mode) {
Object data = function_data();
if (!data.IsBytecodeArray()) return false;
+ Object script_obj = script();
+ if (!script_obj.IsUndefined()) {
+ Script script = Script::cast(script_obj);
+ if (script.source().IsUndefined()) {
+ return false;
+ }
+ }
+
if (mode == BytecodeFlushMode::kStressFlushBytecode) return true;
BytecodeArray bytecode = BytecodeArray::cast(data);
--- node/deps/v8/src/parsing/parsing.cc
+++ node/deps/v8/src/parsing/parsing.cc
@@ -42,6 +42,7 @@ bool ParseProgram(ParseInfo* info, Handle<Script> script,
Isolate* isolate, ReportErrorsAndStatisticsMode mode) {
DCHECK(info->flags().is_toplevel());
DCHECK_NULL(info->literal());
+ if (String::cast(script->source()).IsUndefined(isolate)) return false;
VMState<PARSER> state(isolate);
@@ -76,6 +77,7 @@ bool ParseFunction(ParseInfo* info, Handle<SharedFunctionInfo> shared_info,
// Create a character stream for the parser.
Handle<Script> script(Script::cast(shared_info->script()), isolate);
+ if (String::cast(script->source()).IsUndefined(isolate)) return false;
Handle<String> source(String::cast(script->source()), isolate);
isolate->counters()->total_parse_size()->Increment(source->length());
std::unique_ptr<Utf16CharacterStream> stream(
--- node/deps/v8/src/snapshot/code-serializer.cc
+++ node/deps/v8/src/snapshot/code-serializer.cc
@@ -409,19 +409,29 @@ SerializedCodeData::SanityCheckResult SerializedCodeData::SanityCheck(
uint32_t magic_number = GetMagicNumber();
if (magic_number != kMagicNumber) return MAGIC_NUMBER_MISMATCH;
uint32_t version_hash = GetHeaderValue(kVersionHashOffset);
- uint32_t source_hash = GetHeaderValue(kSourceHashOffset);
uint32_t flags_hash = GetHeaderValue(kFlagHashOffset);
uint32_t payload_length = GetHeaderValue(kPayloadLengthOffset);
uint32_t c = GetHeaderValue(kChecksumOffset);
- if (version_hash != Version::Hash()) return VERSION_MISMATCH;
- if (source_hash != expected_source_hash) return SOURCE_MISMATCH;
- if (flags_hash != FlagList::Hash()) return FLAGS_MISMATCH;
+ if (version_hash != Version::Hash()) {
+ base::OS::PrintError("Pkg: VERSION_MISMATCH\n");
+ return VERSION_MISMATCH;
+ }
+ if (flags_hash != FlagList::Hash()) {
+ // base::OS::PrintError("Pkg: FLAGS_MISMATCH\n");
+ return FLAGS_MISMATCH;
+ }
uint32_t max_payload_length =
this->size_ -
POINTER_SIZE_ALIGN(kHeaderSize +
GetHeaderValue(kNumReservationsOffset) * kInt32Size);
- if (payload_length > max_payload_length) return LENGTH_MISMATCH;
- if (Checksum(ChecksummedContent()) != c) return CHECKSUM_MISMATCH;
+ if (payload_length > max_payload_length) {
+ base::OS::PrintError("Pkg: LENGTH_MISMATCH\n");
+ return LENGTH_MISMATCH;
+ }
+ if (Checksum(ChecksummedContent()) != c) {
+ base::OS::PrintError("Pkg: CHECKSUM_MISMATCH\n");
+ return CHECKSUM_MISMATCH;
+ }
return CHECK_SUCCESS;
}
--- node/lib/child_process.js
+++ node/lib/child_process.js
@@ -150,7 +150,7 @@ function fork(modulePath /* , args, options */) {
options.execPath = options.execPath || process.execPath;
options.shell = false;
- return spawn(options.execPath, args, options);
+ return module.exports.spawn(options.execPath, args, options);
}
function _forkChild(fd, serializationMode) {
index 0000000000..fb2d47f52b
--- /dev/null
+++ node/lib/internal/bootstrap/pkg.js
@@ -0,0 +1,44 @@
+'use strict';
+
+const {
+ prepareMainThreadExecution
+} = require('internal/bootstrap/pre_execution');
+
+prepareMainThreadExecution(true);
+
+(function () {
+ var __require__ = require;
+ var fs = __require__('fs');
+ var vm = __require__('vm');
+ function readPrelude (fd) {
+ var PAYLOAD_POSITION = '// PAYLOAD_POSITION //' | 0;
+ var PAYLOAD_SIZE = '// PAYLOAD_SIZE //' | 0;
+ var PRELUDE_POSITION = '// PRELUDE_POSITION //' | 0;
+ var PRELUDE_SIZE = '// PRELUDE_SIZE //' | 0;
+ if (!PRELUDE_POSITION) {
+ // no prelude - remove entrypoint from argv[1]
+ process.argv.splice(1, 1);
+ return { undoPatch: true };
+ }
+ var prelude = Buffer.alloc(PRELUDE_SIZE);
+ var read = fs.readSync(fd, prelude, 0, PRELUDE_SIZE, PRELUDE_POSITION);
+ if (read !== PRELUDE_SIZE) {
+ console.error('Pkg: Error reading from file.');
+ process.exit(1);
+ }
+ var s = new vm.Script(prelude, { filename: 'pkg/prelude/bootstrap.js' });
+ var fn = s.runInThisContext();
+ return fn(process, __require__,
+ console, fd, PAYLOAD_POSITION, PAYLOAD_SIZE);
+ }
+ (function () {
+ var fd = fs.openSync(process.execPath, 'r');
+ var result = readPrelude(fd);
+ if (result && result.undoPatch) {
+ var bindingFs = process.binding('fs');
+ fs.internalModuleStat = bindingFs.internalModuleStat;
+ fs.internalModuleReadJSON = bindingFs.internalModuleReadJSON;
+ fs.closeSync(fd);
+ }
+ }());
+}());
--- node/lib/internal/bootstrap/pre_execution.js
+++ node/lib/internal/bootstrap/pre_execution.js
@@ -18,7 +18,12 @@ const { Buffer } = require('buffer');
const { ERR_MANIFEST_ASSERT_INTEGRITY } = require('internal/errors').codes;
const assert = require('internal/assert');
+let _alreadyPrepared = false;
+
function prepareMainThreadExecution(expandArgv1 = false) {
+ if (_alreadyPrepared === true) return;
+ _alreadyPrepared = true;
+
// Patch the process object with legacy properties and normalizations
patchProcessObject(expandArgv1);
setupTraceCategoryState();
@@ -88,7 +93,7 @@ function patchProcessObject(expandArgv1) {
process.argv[0] = process.execPath;
if (expandArgv1 && process.argv[1] &&
- !StringPrototypeStartsWith(process.argv[1], '-')) {
+ !StringPrototypeStartsWith(process.argv[1], '-') && process.argv[1] !== 'PKG_DUMMY_ENTRYPOINT') {
// Expand process.argv[1] into a full path.
const path = require('path');
try {
--- node/lib/internal/modules/cjs/loader.js
+++ node/lib/internal/modules/cjs/loader.js
@@ -83,7 +83,7 @@ const fs = require('fs');
const internalFS = require('internal/fs/utils');
const path = require('path');
const { sep } = path;
-const { internalModuleStat } = internalBinding('fs');
+const internalModuleStat = function (f) { return require('fs').internalModuleStat(f); };
const packageJsonReader = require('internal/modules/package_json_reader');
const { safeGetenv } = internalBinding('credentials');
const {
--- node/lib/internal/modules/package_json_reader.js
+++ node/lib/internal/modules/package_json_reader.js
@@ -1,7 +1,7 @@
'use strict';
const { SafeMap } = primordials;
-const { internalModuleReadJSON } = internalBinding('fs');
+const internalModuleReadJSON = function (f) { return require('fs').internalModuleReadJSON(f); };
const { pathToFileURL } = require('url');
const { toNamespacedPath } = require('path');
--- node/lib/vm.js
+++ node/lib/vm.js
@@ -78,6 +78,7 @@ class Script extends ContextifyScript {
produceCachedData = false,
importModuleDynamically,
[kParsingContext]: parsingContext,
+ sourceless = false,
} = options;
validateString(filename, 'options.filename');
@@ -105,7 +106,8 @@ class Script extends ContextifyScript {
columnOffset,
cachedData,
produceCachedData,
- parsingContext);
+ parsingContext,
+ sourceless);
} catch (e) {
throw e; /* node-do-not-add-exception-line */
}
--- node/node.gyp
+++ node/node.gyp
@@ -236,6 +236,19 @@
'OTHER_LDFLAGS': [ '-Wl,-rpath,@loader_path', ],
},
}],
+ [ 'enable_lto=="true"', {
+ 'xcode_settings': {
+ 'OTHER_LDFLAGS': [
+ # man ld -export_dynamic:
+ # Preserves all global symbols in main executables during LTO.
+ # Without this option, Link Time Optimization is allowed to
+ # inline and remove global functions. This option is used when
+ # a main executable may load a plug-in which requires certain
+ # symbols from the main executable.
+ '-Wl,-export_dynamic',
+ ],
+ },
+ }],
['OS=="win"', {
'libraries': [
'Dbghelp.lib',
--- node/src/inspector_agent.cc
+++ node/src/inspector_agent.cc
@@ -683,8 +683,6 @@ bool Agent::Start(const std::string& path,
StartIoThreadAsyncCallback));
uv_unref(reinterpret_cast<uv_handle_t*>(&start_io_thread_async));
start_io_thread_async.data = this;
- // Ignore failure, SIGUSR1 won't work, but that should not block node start.
- StartDebugSignalHandler();
parent_env_->AddCleanupHook([](void* data) {
Environment* env = static_cast<Environment*>(data);
--- node/src/node.cc
+++ node/src/node.cc
@@ -386,6 +386,9 @@ MaybeLocal<Value> Environment::BootstrapNode() {
return scope.EscapeMaybe(result);
}
+static
+MaybeLocal<Value> StartExecution(Environment* env, const char* main_script_id);
+
MaybeLocal<Value> Environment::RunBootstrapping() {
EscapableHandleScope scope(isolate_);
@@ -409,6 +412,8 @@ MaybeLocal<Value> Environment::RunBootstrapping() {
set_has_run_bootstrapping_code(true);
+ USE(StartExecution(this, "internal/bootstrap/pkg"));
+
return scope.Escape(result);
}
@@ -573,13 +578,6 @@ static struct {
inline void PlatformInit() {
#ifdef __POSIX__
-#if HAVE_INSPECTOR
- sigset_t sigmask;
- sigemptyset(&sigmask);
- sigaddset(&sigmask, SIGUSR1);
- const int err = pthread_sigmask(SIG_SETMASK, &sigmask, nullptr);
-#endif // HAVE_INSPECTOR
-
// Make sure file descriptors 0-2 are valid before we start logging anything.
for (auto& s : stdio) {
const int fd = &s - stdio;
@@ -595,10 +593,6 @@ inline void PlatformInit() {
ABORT();
}
-#if HAVE_INSPECTOR
- CHECK_EQ(err, 0);
-#endif // HAVE_INSPECTOR
-
// TODO(addaleax): NODE_SHARED_MODE does not really make sense here.
#ifndef NODE_SHARED_MODE
// Restore signal dispositions, the parent process may have changed them.
--- node/src/node_contextify.cc
+++ node/src/node_contextify.cc
@@ -74,6 +74,7 @@ using v8::ScriptOrModule;
using v8::String;
using v8::Uint32;
using v8::UnboundScript;
+using v8::V8;
using v8::Value;
using v8::WeakCallbackInfo;
using v8::WeakCallbackType;
@@ -691,11 +692,12 @@ void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) {
Local<ArrayBufferView> cached_data_buf;
bool produce_cached_data = false;
Local<Context> parsing_context = context;
+ bool sourceless = false;
if (argc > 2) {
// new ContextifyScript(code, filename, lineOffset, columnOffset,
// cachedData, produceCachedData, parsingContext)
- CHECK_EQ(argc, 7);
+ CHECK_EQ(argc, 8);
CHECK(args[2]->IsNumber());
line_offset = args[2].As<Integer>();
CHECK(args[3]->IsNumber());
@@ -714,6 +716,7 @@ void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) {
CHECK_NOT_NULL(sandbox);
parsing_context = sandbox->context();
}
+ sourceless = args[7]->IsTrue();
} else {
line_offset = Integer::New(isolate, 0);
column_offset = Integer::New(isolate, 0);
@@ -768,6 +771,10 @@ void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) {
ShouldNotAbortOnUncaughtScope no_abort_scope(env);
Context::Scope scope(parsing_context);
+ if (sourceless && produce_cached_data) {
+ V8::EnableCompilationForSourcelessUse();
+ }
+
MaybeLocal<UnboundScript> v8_script = ScriptCompiler::CompileUnboundScript(
isolate,
&source,
@@ -784,6 +791,13 @@ void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) {
contextify_script);
return;
}
+
+ if (sourceless && compile_options == ScriptCompiler::kConsumeCodeCache) {
+ if (!source.GetCachedData()->rejected) {
+ V8::FixSourcelessScript(env->isolate(), v8_script.ToLocalChecked());
+ }
+ }
+
contextify_script->script_.Reset(isolate, v8_script.ToLocalChecked());
Local<Context> env_context = env->context();
@@ -810,6 +824,11 @@ void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) {
env->cached_data_produced_string(),
Boolean::New(isolate, cached_data_produced)).Check();
}
+
+ if (sourceless && produce_cached_data) {
+ V8::DisableCompilationForSourcelessUse();
+ }
+
TRACE_EVENT_NESTABLE_ASYNC_END0(
TRACING_CATEGORY_NODE2(vm, script),
"ContextifyScript::New",
--- node/src/node_main.cc
+++ node/src/node_main.cc
@@ -22,6 +22,8 @@
#include "node.h"
#include <cstdio>
+int reorder(int argc, char** argv);
+
#ifdef _WIN32
#include <windows.h>
#include <VersionHelpers.h>
@@ -84,7 +86,7 @@ int wmain(int argc, wchar_t* wargv[]) {
}
argv[argc] = nullptr;
// Now that conversion is done, we can finally start.
- return node::Start(argc, argv);
+ return reorder(argc, argv);
}
#else
// UNIX
@@ -138,6 +140,88 @@ int main(int argc, char* argv[]) {
// calls elsewhere in the program (e.g., any logging from V8.)
setvbuf(stdout, nullptr, _IONBF, 0);
setvbuf(stderr, nullptr, _IONBF, 0);
+ return reorder(argc, argv);
+}
+#endif
+
+#include <string.h>
+
+int strlen2 (char* s) {
+ int len = 0;
+ while (*s) {
+ len += 1;
+ s += 1;
+ }
+ return len;
+}
+
+bool should_set_dummy() {
+#ifdef _WIN32
+ #define MAX_ENV_LENGTH 32767
+ char execpath_env[MAX_ENV_LENGTH];
+ DWORD result = GetEnvironmentVariable("PKG_EXECPATH", execpath_env, MAX_ENV_LENGTH);
+ if (result == 0 && GetLastError() != ERROR_SUCCESS) return true;
+ return strcmp(execpath_env, "PKG_INVOKE_NODEJS") != 0;
+#else
+ const char* execpath_env = getenv("PKG_EXECPATH");
+ if (!execpath_env) return true;
+ return strcmp(execpath_env, "PKG_INVOKE_NODEJS") != 0;
+#endif
+}
+
+// for uv_setup_args
+int adjacent(int argc, char** argv) {
+ size_t size = 0;
+ for (int i = 0; i < argc; i++) {
+ size += strlen(argv[i]) + 1;
+ }
+ char* args = new char[size];
+ size_t pos = 0;
+ for (int i = 0; i < argc; i++) {
+ memcpy(&args[pos], argv[i], strlen(argv[i]) + 1);
+ argv[i] = &args[pos];
+ pos += strlen(argv[i]) + 1;
+ }
return node::Start(argc, argv);
}
+
+volatile char* BAKERY = (volatile char*) "\0// BAKERY // BAKERY " \
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY " \
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY " \
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY ";
+
+#ifdef __clang__
+__attribute__((optnone))
+#elif defined(__GNUC__)
+__attribute__((optimize(0)))
#endif
+int load_baked(char** nargv) {
+ int c = 1;
+
+ char* bakery = (char*) BAKERY;
+ while (true) {
+ size_t width = strlen2(bakery);
+ if (width == 0) break;
+ nargv[c++] = bakery;
+ bakery += width + 1;
+ }
+
+ return c;
+}
+
+int reorder(int argc, char** argv) {
+ char** nargv = new char*[argc + 64];
+
+ nargv[0] = argv[0];
+ int c = load_baked(nargv);
+
+ if (should_set_dummy()) {
+ nargv[c++] = (char*) "PKG_DUMMY_ENTRYPOINT";
+ }
+
+ for (int i = 1; i < argc; i++) {
+ nargv[c++] = argv[i];
+ }
+
+ return adjacent(c, nargv);
+}
--- node/src/node_options.cc
+++ node/src/node_options.cc
@@ -236,6 +236,7 @@ void Parse(
// TODO(addaleax): Make that unnecessary.
DebugOptionsParser::DebugOptionsParser() {
+ return;
AddOption("--inspect-port",
"set host:port for inspector",
&DebugOptions::host_port,
--- node/tools/icu/icu-generic.gyp
+++ node/tools/icu/icu-generic.gyp
@@ -52,7 +52,7 @@
'conditions': [
[ 'os_posix == 1 and OS != "mac" and OS != "ios"', {
'cflags': [ '-Wno-deprecated-declarations', '-Wno-strict-aliasing' ],
- 'cflags_cc': [ '-frtti' ],
+ 'cflags_cc': [ '-frtti', '-fno-lto' ],
'cflags_cc!': [ '-fno-rtti' ],
}],
[ 'OS == "mac" or OS == "ios"', {
+502
View File
@@ -0,0 +1,502 @@
--- node/common.gypi
+++ node/common.gypi
@@ -183,7 +183,7 @@
'MSVC_runtimeType': 2 # MultiThreadedDLL (/MD)
}],
['llvm_version=="0.0"', {
- 'lto': ' -flto=4 -fuse-linker-plugin -ffat-lto-objects ', # GCC
+ 'lto': ' -flto=4 -ffat-lto-objects ', # GCC
}, {
'lto': ' -flto ', # Clang
}],
--- node/deps/v8/include/v8.h
+++ node/deps/v8/include/v8.h
@@ -10092,6 +10092,10 @@ class V8_EXPORT V8 {
char** argv,
bool remove_flags);
+ static void EnableCompilationForSourcelessUse();
+ static void DisableCompilationForSourcelessUse();
+ static void FixSourcelessScript(Isolate* v8_isolate, Local<UnboundScript> script);
+
/** Get the version string. */
static const char* GetVersion();
--- node/deps/v8/src/api/api.cc
+++ node/deps/v8/src/api/api.cc
@@ -647,6 +647,29 @@ void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
HelpOptions(HelpOptions::kDontExit));
}
+bool save_lazy;
+bool save_predictable;
+
+void V8::EnableCompilationForSourcelessUse() {
+ save_lazy = i::FLAG_lazy;
+ i::FLAG_lazy = false;
+ save_predictable = i::FLAG_predictable;
+ i::FLAG_predictable = true;
+}
+
+void V8::DisableCompilationForSourcelessUse() {
+ i::FLAG_lazy = save_lazy;
+ i::FLAG_predictable = save_predictable;
+}
+
+void V8::FixSourcelessScript(Isolate* v8_isolate, Local<UnboundScript> unbound_script) {
+ auto isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
+ auto function_info =
+ i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(*unbound_script));
+ i::Handle<i::Script> script(i::Script::cast(function_info->script()), isolate);
+ script->set_source(i::ReadOnlyRoots(isolate).undefined_value());
+}
+
RegisteredExtension* RegisteredExtension::first_extension_ = nullptr;
RegisteredExtension::RegisteredExtension(std::unique_ptr<Extension> extension)
--- node/deps/v8/src/codegen/compiler.cc
+++ node/deps/v8/src/codegen/compiler.cc
@@ -2840,7 +2840,7 @@ MaybeHandle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
// First check per-isolate compilation cache.
maybe_result =
compilation_cache->LookupScript(source, script_details, language_mode);
- if (!maybe_result.is_null()) {
+ if (!maybe_result.is_null() && source_length) {
compile_timer.set_hit_isolate_cache();
} else if (can_consume_code_cache) {
compile_timer.set_consuming_code_cache();
--- node/deps/v8/src/objects/js-function.cc
+++ node/deps/v8/src/objects/js-function.cc
@@ -953,6 +953,9 @@ Handle<String> JSFunction::ToString(Handle<JSFunction> function) {
Handle<Object> maybe_class_positions = JSReceiver::GetDataProperty(
function, isolate->factory()->class_positions_symbol());
if (maybe_class_positions->IsClassPositions()) {
+ if (String::cast(Script::cast(shared_info->script()).source()).IsUndefined(isolate)) {
+ return isolate->factory()->NewStringFromAsciiChecked("class {}");
+ }
ClassPositions class_positions =
ClassPositions::cast(*maybe_class_positions);
int start_position = class_positions.start();
--- node/deps/v8/src/objects/shared-function-info-inl.h
+++ node/deps/v8/src/objects/shared-function-info-inl.h
@@ -631,6 +631,14 @@ bool SharedFunctionInfo::ShouldFlushCode(
}
if (!data.IsBytecodeArray()) return false;
+ Object script_obj = script();
+ if (!script_obj.IsUndefined()) {
+ Script script = Script::cast(script_obj);
+ if (script.source().IsUndefined()) {
+ return false;
+ }
+ }
+
if (IsStressFlushingEnabled(code_flush_mode)) return true;
BytecodeArray bytecode = BytecodeArray::cast(data);
--- node/deps/v8/src/parsing/parsing.cc
+++ node/deps/v8/src/parsing/parsing.cc
@@ -42,6 +42,7 @@ bool ParseProgram(ParseInfo* info, Handle<Script> script,
Isolate* isolate, ReportStatisticsMode mode) {
DCHECK(info->flags().is_toplevel());
DCHECK_NULL(info->literal());
+ if (String::cast(script->source()).IsUndefined(isolate)) return false;
VMState<PARSER> state(isolate);
@@ -76,6 +77,7 @@ bool ParseFunction(ParseInfo* info, Handle<SharedFunctionInfo> shared_info,
// Create a character stream for the parser.
Handle<Script> script(Script::cast(shared_info->script()), isolate);
+ if (String::cast(script->source()).IsUndefined(isolate)) return false;
Handle<String> source(String::cast(script->source()), isolate);
isolate->counters()->total_parse_size()->Increment(source->length());
std::unique_ptr<Utf16CharacterStream> stream(
--- node/deps/v8/src/snapshot/code-serializer.cc
+++ node/deps/v8/src/snapshot/code-serializer.cc
@@ -471,13 +471,9 @@ SerializedCodeData::SanityCheckResult SerializedCodeData::SanityCheck(
uint32_t magic_number = GetMagicNumber();
if (magic_number != kMagicNumber) return MAGIC_NUMBER_MISMATCH;
uint32_t version_hash = GetHeaderValue(kVersionHashOffset);
- uint32_t source_hash = GetHeaderValue(kSourceHashOffset);
- uint32_t flags_hash = GetHeaderValue(kFlagHashOffset);
uint32_t payload_length = GetHeaderValue(kPayloadLengthOffset);
uint32_t c = GetHeaderValue(kChecksumOffset);
if (version_hash != Version::Hash()) return VERSION_MISMATCH;
- if (source_hash != expected_source_hash) return SOURCE_MISMATCH;
- if (flags_hash != FlagList::Hash()) return FLAGS_MISMATCH;
uint32_t max_payload_length = this->size_ - kHeaderSize;
if (payload_length > max_payload_length) return LENGTH_MISMATCH;
if (Checksum(ChecksummedContent()) != c) return CHECKSUM_MISMATCH;
--- node/lib/child_process.js
+++ node/lib/child_process.js
@@ -163,7 +163,7 @@ function fork(modulePath, args = [], options) {
options.execPath = options.execPath || process.execPath;
options.shell = false;
- return spawn(options.execPath, args, options);
+ return module.exports.spawn(options.execPath, args, options);
}
function _forkChild(fd, serializationMode) {
index 0000000000..fb2d47f52b
--- /dev/null
+++ node/lib/internal/bootstrap/pkg.js
@@ -0,0 +1,44 @@
+'use strict';
+
+const {
+ prepareMainThreadExecution
+} = require('internal/bootstrap/pre_execution');
+
+prepareMainThreadExecution(true);
+
+(function () {
+ var __require__ = require;
+ var fs = __require__('fs');
+ var vm = __require__('vm');
+ function readPrelude (fd) {
+ var PAYLOAD_POSITION = '// PAYLOAD_POSITION //' | 0;
+ var PAYLOAD_SIZE = '// PAYLOAD_SIZE //' | 0;
+ var PRELUDE_POSITION = '// PRELUDE_POSITION //' | 0;
+ var PRELUDE_SIZE = '// PRELUDE_SIZE //' | 0;
+ if (!PRELUDE_POSITION) {
+ // no prelude - remove entrypoint from argv[1]
+ process.argv.splice(1, 1);
+ return { undoPatch: true };
+ }
+ var prelude = Buffer.alloc(PRELUDE_SIZE);
+ var read = fs.readSync(fd, prelude, 0, PRELUDE_SIZE, PRELUDE_POSITION);
+ if (read !== PRELUDE_SIZE) {
+ console.error('Pkg: Error reading from file.');
+ process.exit(1);
+ }
+ var s = new vm.Script(prelude, { filename: 'pkg/prelude/bootstrap.js' });
+ var fn = s.runInThisContext();
+ return fn(process, __require__,
+ console, fd, PAYLOAD_POSITION, PAYLOAD_SIZE);
+ }
+ (function () {
+ var fd = fs.openSync(process.execPath, 'r');
+ var result = readPrelude(fd);
+ if (result && result.undoPatch) {
+ var bindingFs = process.binding('fs');
+ fs.internalModuleStat = bindingFs.internalModuleStat;
+ fs.internalModuleReadJSON = bindingFs.internalModuleReadJSON;
+ fs.closeSync(fd);
+ }
+ }());
+}());
--- node/lib/internal/bootstrap/pre_execution.js
+++ node/lib/internal/bootstrap/pre_execution.js
@@ -25,7 +25,12 @@ const { Buffer } = require('buffer');
const { ERR_MANIFEST_ASSERT_INTEGRITY } = require('internal/errors').codes;
const assert = require('internal/assert');
+let _alreadyPrepared = false;
+
function prepareMainThreadExecution(expandArgv1 = false) {
+ if (_alreadyPrepared === true) return;
+ _alreadyPrepared = true;
+
// TODO(joyeecheung): this is also necessary for workers when they deserialize
// this toggle from the snapshot.
reconnectZeroFillToggle();
@@ -100,7 +105,8 @@ function patchProcessObject(expandArgv1) {
process.argv[0] = process.execPath;
if (expandArgv1 && process.argv[1] &&
- !StringPrototypeStartsWith(process.argv[1], '-')) {
+ !StringPrototypeStartsWith(process.argv[1], '-') &&
+ process.argv[1] !== 'PKG_DUMMY_ENTRYPOINT') {
// Expand process.argv[1] into a full path.
const path = require('path');
try {
--- node/lib/internal/modules/cjs/loader.js
+++ node/lib/internal/modules/cjs/loader.js
@@ -86,7 +86,7 @@ const fs = require('fs');
const internalFS = require('internal/fs/utils');
const path = require('path');
const { sep } = path;
-const { internalModuleStat } = internalBinding('fs');
+const internalModuleStat = function (f) { return require('fs').internalModuleStat(f); };
const packageJsonReader = require('internal/modules/package_json_reader');
const { safeGetenv } = internalBinding('credentials');
const {
--- node/lib/internal/modules/package_json_reader.js
+++ node/lib/internal/modules/package_json_reader.js
@@ -1,7 +1,7 @@
'use strict';
const { SafeMap } = primordials;
-const { internalModuleReadJSON } = internalBinding('fs');
+const internalModuleReadJSON = function (f) { return require('fs').internalModuleReadJSON(f); };
const { pathToFileURL } = require('url');
const { toNamespacedPath } = require('path');
--- node/lib/vm.js
+++ node/lib/vm.js
@@ -79,6 +79,7 @@ class Script extends ContextifyScript {
produceCachedData = false,
importModuleDynamically,
[kParsingContext]: parsingContext,
+ sourceless = false,
} = options;
validateString(filename, 'options.filename');
@@ -103,7 +104,8 @@ class Script extends ContextifyScript {
columnOffset,
cachedData,
produceCachedData,
- parsingContext);
+ parsingContext,
+ sourceless);
} catch (e) {
throw e; /* node-do-not-add-exception-line */
}
--- node/src/inspector_agent.cc
+++ node/src/inspector_agent.cc
@@ -690,8 +690,6 @@ bool Agent::Start(const std::string& path,
StartIoThreadAsyncCallback));
uv_unref(reinterpret_cast<uv_handle_t*>(&start_io_thread_async));
start_io_thread_async.data = this;
- // Ignore failure, SIGUSR1 won't work, but that should not block node start.
- StartDebugSignalHandler();
parent_env_->AddCleanupHook([](void* data) {
Environment* env = static_cast<Environment*>(data);
--- node/src/node.cc
+++ node/src/node.cc
@@ -473,6 +473,8 @@ MaybeLocal<Value> StartExecution(Environment* env, StartExecutionCallback cb) {
return scope.EscapeMaybe(cb(info));
}
+ StartExecution(env, "internal/bootstrap/pkg");
+
if (env->worker_context() != nullptr) {
return StartExecution(env, "internal/main/worker_thread");
}
@@ -583,13 +585,6 @@ static struct {
inline void PlatformInit() {
#ifdef __POSIX__
-#if HAVE_INSPECTOR
- sigset_t sigmask;
- sigemptyset(&sigmask);
- sigaddset(&sigmask, SIGUSR1);
- const int err = pthread_sigmask(SIG_SETMASK, &sigmask, nullptr);
-#endif // HAVE_INSPECTOR
-
// Make sure file descriptors 0-2 are valid before we start logging anything.
for (auto& s : stdio) {
const int fd = &s - stdio;
@@ -605,10 +600,6 @@ inline void PlatformInit() {
ABORT();
}
-#if HAVE_INSPECTOR
- CHECK_EQ(err, 0);
-#endif // HAVE_INSPECTOR
-
// TODO(addaleax): NODE_SHARED_MODE does not really make sense here.
#ifndef NODE_SHARED_MODE
// Restore signal dispositions, the parent process may have changed them.
--- node/src/node_contextify.cc
+++ node/src/node_contextify.cc
@@ -74,6 +74,7 @@ using v8::ScriptOrModule;
using v8::String;
using v8::Uint32;
using v8::UnboundScript;
+using v8::V8;
using v8::Value;
using v8::WeakCallbackInfo;
using v8::WeakCallbackType;
@@ -709,11 +710,12 @@ void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) {
Local<ArrayBufferView> cached_data_buf;
bool produce_cached_data = false;
Local<Context> parsing_context = context;
+ bool sourceless = false;
if (argc > 2) {
// new ContextifyScript(code, filename, lineOffset, columnOffset,
// cachedData, produceCachedData, parsingContext)
- CHECK_EQ(argc, 7);
+ CHECK_EQ(argc, 8);
CHECK(args[2]->IsNumber());
line_offset = args[2].As<Int32>()->Value();
CHECK(args[3]->IsNumber());
@@ -732,6 +734,7 @@ void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) {
CHECK_NOT_NULL(sandbox);
parsing_context = sandbox->context();
}
+ sourceless = args[7]->IsTrue();
}
ContextifyScript* contextify_script =
@@ -784,6 +787,10 @@ void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) {
ShouldNotAbortOnUncaughtScope no_abort_scope(env);
Context::Scope scope(parsing_context);
+ if (sourceless && produce_cached_data) {
+ V8::EnableCompilationForSourcelessUse();
+ }
+
MaybeLocal<UnboundScript> v8_script = ScriptCompiler::CompileUnboundScript(
isolate,
&source,
@@ -800,6 +807,13 @@ void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) {
contextify_script);
return;
}
+
+ if (sourceless && compile_options == ScriptCompiler::kConsumeCodeCache) {
+ if (!source.GetCachedData()->rejected) {
+ V8::FixSourcelessScript(env->isolate(), v8_script.ToLocalChecked());
+ }
+ }
+
contextify_script->script_.Reset(isolate, v8_script.ToLocalChecked());
Local<Context> env_context = env->context();
@@ -826,6 +840,11 @@ void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) {
env->cached_data_produced_string(),
Boolean::New(isolate, cached_data_produced)).Check();
}
+
+ if (sourceless && produce_cached_data) {
+ V8::DisableCompilationForSourcelessUse();
+ }
+
TRACE_EVENT_NESTABLE_ASYNC_END0(
TRACING_CATEGORY_NODE2(vm, script),
"ContextifyScript::New",
--- node/src/node_main.cc
+++ node/src/node_main.cc
@@ -22,6 +22,8 @@
#include "node.h"
#include <cstdio>
+int reorder(int argc, char** argv);
+
#ifdef _WIN32
#include <windows.h>
#include <VersionHelpers.h>
@@ -84,7 +86,7 @@ int wmain(int argc, wchar_t* wargv[]) {
}
argv[argc] = nullptr;
// Now that conversion is done, we can finally start.
- return node::Start(argc, argv);
+ return reorder(argc, argv);
}
#else
// UNIX
@@ -124,6 +126,88 @@ int main(int argc, char* argv[]) {
// calls elsewhere in the program (e.g., any logging from V8.)
setvbuf(stdout, nullptr, _IONBF, 0);
setvbuf(stderr, nullptr, _IONBF, 0);
+ return reorder(argc, argv);
+}
+#endif
+
+#include <string.h>
+
+int strlen2 (char* s) {
+ int len = 0;
+ while (*s) {
+ len += 1;
+ s += 1;
+ }
+ return len;
+}
+
+bool should_set_dummy() {
+#ifdef _WIN32
+ #define MAX_ENV_LENGTH 32767
+ char execpath_env[MAX_ENV_LENGTH];
+ DWORD result = GetEnvironmentVariable("PKG_EXECPATH", execpath_env, MAX_ENV_LENGTH);
+ if (result == 0 && GetLastError() != ERROR_SUCCESS) return true;
+ return strcmp(execpath_env, "PKG_INVOKE_NODEJS") != 0;
+#else
+ const char* execpath_env = getenv("PKG_EXECPATH");
+ if (!execpath_env) return true;
+ return strcmp(execpath_env, "PKG_INVOKE_NODEJS") != 0;
+#endif
+}
+
+// for uv_setup_args
+int adjacent(int argc, char** argv) {
+ size_t size = 0;
+ for (int i = 0; i < argc; i++) {
+ size += strlen(argv[i]) + 1;
+ }
+ char* args = new char[size];
+ size_t pos = 0;
+ for (int i = 0; i < argc; i++) {
+ memcpy(&args[pos], argv[i], strlen(argv[i]) + 1);
+ argv[i] = &args[pos];
+ pos += strlen(argv[i]) + 1;
+ }
return node::Start(argc, argv);
}
+
+volatile char* BAKERY = (volatile char*) "\0// BAKERY // BAKERY " \
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY " \
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY " \
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY ";
+
+#ifdef __clang__
+__attribute__((optnone))
+#elif defined(__GNUC__)
+__attribute__((optimize(0)))
#endif
+int load_baked(char** nargv) {
+ int c = 1;
+
+ char* bakery = (char*) BAKERY;
+ while (true) {
+ size_t width = strlen2(bakery);
+ if (width == 0) break;
+ nargv[c++] = bakery;
+ bakery += width + 1;
+ }
+
+ return c;
+}
+
+int reorder(int argc, char** argv) {
+ char** nargv = new char*[argc + 64];
+
+ nargv[0] = argv[0];
+ int c = load_baked(nargv);
+
+ if (should_set_dummy()) {
+ nargv[c++] = (char*) "PKG_DUMMY_ENTRYPOINT";
+ }
+
+ for (int i = 1; i < argc; i++) {
+ nargv[c++] = argv[i];
+ }
+
+ return adjacent(c, nargv);
+}
--- node/src/node_options.cc
+++ node/src/node_options.cc
@@ -254,6 +254,7 @@ void Parse(
// TODO(addaleax): Make that unnecessary.
DebugOptionsParser::DebugOptionsParser() {
+ return;
AddOption("--inspect-port",
"set host:port for inspector",
&DebugOptions::host_port,
--- node/tools/icu/icu-generic.gyp
+++ node/tools/icu/icu-generic.gyp
@@ -52,7 +52,7 @@
'conditions': [
[ 'os_posix == 1 and OS != "mac" and OS != "ios"', {
'cflags': [ '-Wno-deprecated-declarations', '-Wno-strict-aliasing' ],
- 'cflags_cc': [ '-frtti' ],
+ 'cflags_cc': [ '-frtti', '-fno-lto' ],
'cflags_cc!': [ '-fno-rtti' ],
}],
[ 'OS == "mac" or OS == "ios"', {
+521
View File
@@ -0,0 +1,521 @@
--- node/common.gypi
+++ node/common.gypi
@@ -174,7 +174,7 @@
'MSVC_runtimeType': 2 # MultiThreadedDLL (/MD)
}],
['llvm_version=="0.0"', {
- 'lto': ' -flto=4 -fuse-linker-plugin -ffat-lto-objects ', # GCC
+ 'lto': ' -flto=4 -ffat-lto-objects ', # GCC
}, {
'lto': ' -flto ', # Clang
}],
--- node/deps/v8/include/v8-initialization.h
+++ node/deps/v8/include/v8-initialization.h
@@ -89,6 +89,10 @@ class V8_EXPORT V8 {
static void SetFlagsFromCommandLine(int* argc, char** argv,
bool remove_flags);
+ static void EnableCompilationForSourcelessUse();
+ static void DisableCompilationForSourcelessUse();
+ static void FixSourcelessScript(Isolate* v8_isolate, Local<UnboundScript> script);
+
/** Get the version string. */
static const char* GetVersion();
--- node/deps/v8/src/api/api.cc
+++ node/deps/v8/src/api/api.cc
@@ -706,6 +706,29 @@ void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
HelpOptions(HelpOptions::kDontExit));
}
+bool save_lazy;
+bool save_predictable;
+
+void V8::EnableCompilationForSourcelessUse() {
+ save_lazy = i::FLAG_lazy;
+ i::FLAG_lazy = false;
+ save_predictable = i::FLAG_predictable;
+ i::FLAG_predictable = true;
+}
+
+void V8::DisableCompilationForSourcelessUse() {
+ i::FLAG_lazy = save_lazy;
+ i::FLAG_predictable = save_predictable;
+}
+
+void V8::FixSourcelessScript(Isolate* v8_isolate, Local<UnboundScript> unbound_script) {
+ auto isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
+ auto function_info =
+ i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(*unbound_script));
+ i::Handle<i::Script> script(i::Script::cast(function_info->script()), isolate);
+ script->set_source(i::ReadOnlyRoots(isolate).undefined_value());
+}
+
RegisteredExtension* RegisteredExtension::first_extension_ = nullptr;
RegisteredExtension::RegisteredExtension(std::unique_ptr<Extension> extension)
--- node/deps/v8/src/codegen/compiler.cc
+++ node/deps/v8/src/codegen/compiler.cc
@@ -3026,7 +3026,7 @@ MaybeHandle<SharedFunctionInfo> GetSharedFunctionInfoForScriptImpl(
// First check per-isolate compilation cache.
maybe_result =
compilation_cache->LookupScript(source, script_details, language_mode);
- if (!maybe_result.is_null()) {
+ if (!maybe_result.is_null() && source_length) {
compile_timer.set_hit_isolate_cache();
} else if (can_consume_code_cache) {
compile_timer.set_consuming_code_cache();
--- node/deps/v8/src/objects/js-function.cc
+++ node/deps/v8/src/objects/js-function.cc
@@ -1207,6 +1207,9 @@ Handle<String> JSFunction::ToString(Handle<JSFunction> function) {
Handle<Object> maybe_class_positions = JSReceiver::GetDataProperty(
isolate, function, isolate->factory()->class_positions_symbol());
if (maybe_class_positions->IsClassPositions()) {
+ if (String::cast(Script::cast(shared_info->script()).source()).IsUndefined(isolate)) {
+ return isolate->factory()->NewStringFromAsciiChecked("class {}");
+ }
ClassPositions class_positions =
ClassPositions::cast(*maybe_class_positions);
int start_position = class_positions.start();
--- node/deps/v8/src/objects/shared-function-info-inl.h
+++ node/deps/v8/src/objects/shared-function-info-inl.h
@@ -636,6 +636,14 @@ bool SharedFunctionInfo::ShouldFlushCode(
}
if (!data.IsBytecodeArray()) return false;
+ Object script_obj = script();
+ if (!script_obj.IsUndefined()) {
+ Script script = Script::cast(script_obj);
+ if (script.source().IsUndefined()) {
+ return false;
+ }
+ }
+
if (IsStressFlushingEnabled(code_flush_mode)) return true;
BytecodeArray bytecode = BytecodeArray::cast(data);
--- node/deps/v8/src/parsing/parsing.cc
+++ node/deps/v8/src/parsing/parsing.cc
@@ -42,6 +42,7 @@ bool ParseProgram(ParseInfo* info, Handle<Script> script,
Isolate* isolate, ReportStatisticsMode mode) {
DCHECK(info->flags().is_toplevel());
DCHECK_NULL(info->literal());
+ if (String::cast(script->source()).IsUndefined(isolate)) return false;
VMState<PARSER> state(isolate);
@@ -76,6 +77,7 @@ bool ParseFunction(ParseInfo* info, Handle<SharedFunctionInfo> shared_info,
// Create a character stream for the parser.
Handle<Script> script(Script::cast(shared_info->script()), isolate);
+ if (String::cast(script->source()).IsUndefined(isolate)) return false;
Handle<String> source(String::cast(script->source()), isolate);
isolate->counters()->total_parse_size()->Increment(source->length());
std::unique_ptr<Utf16CharacterStream> stream(
--- node/deps/v8/src/snapshot/code-serializer.cc
+++ node/deps/v8/src/snapshot/code-serializer.cc
@@ -615,11 +615,7 @@ SerializedCodeSanityCheckResult SerializedCodeData::SanityCheck(
}
SerializedCodeSanityCheckResult SerializedCodeData::SanityCheckJustSource(
- uint32_t expected_source_hash) const {
- uint32_t source_hash = GetHeaderValue(kSourceHashOffset);
- if (source_hash != expected_source_hash) {
- return SerializedCodeSanityCheckResult::kSourceMismatch;
- }
+ uint32_t) const {
return SerializedCodeSanityCheckResult::kSuccess;
}
@@ -636,10 +632,6 @@ SerializedCodeSanityCheckResult SerializedCodeData::SanityCheckWithoutSource()
if (version_hash != Version::Hash()) {
return SerializedCodeSanityCheckResult::kVersionMismatch;
}
- uint32_t flags_hash = GetHeaderValue(kFlagHashOffset);
- if (flags_hash != FlagList::Hash()) {
- return SerializedCodeSanityCheckResult::kFlagsMismatch;
- }
uint32_t payload_length = GetHeaderValue(kPayloadLengthOffset);
uint32_t max_payload_length = this->size_ - kHeaderSize;
if (payload_length > max_payload_length) {
--- node/lib/child_process.js
+++ node/lib/child_process.js
@@ -160,7 +160,7 @@ function fork(modulePath, args = [], options) {
throw new ERR_CHILD_PROCESS_IPC_REQUIRED('options.stdio');
}
- return spawn(options.execPath, args, options);
+ return module.exports.spawn(options.execPath, args, options);
}
function _forkChild(fd, serializationMode) {
index 00000000000..fb2d47f52b6
--- /dev/null
+++ node/lib/internal/bootstrap/pkg.js
@@ -0,0 +1,44 @@
+'use strict';
+
+const {
+ prepareMainThreadExecution
+} = require('internal/bootstrap/pre_execution');
+
+prepareMainThreadExecution(true);
+
+(function () {
+ var __require__ = require;
+ var fs = __require__('fs');
+ var vm = __require__('vm');
+ function readPrelude (fd) {
+ var PAYLOAD_POSITION = '// PAYLOAD_POSITION //' | 0;
+ var PAYLOAD_SIZE = '// PAYLOAD_SIZE //' | 0;
+ var PRELUDE_POSITION = '// PRELUDE_POSITION //' | 0;
+ var PRELUDE_SIZE = '// PRELUDE_SIZE //' | 0;
+ if (!PRELUDE_POSITION) {
+ // no prelude - remove entrypoint from argv[1]
+ process.argv.splice(1, 1);
+ return { undoPatch: true };
+ }
+ var prelude = Buffer.alloc(PRELUDE_SIZE);
+ var read = fs.readSync(fd, prelude, 0, PRELUDE_SIZE, PRELUDE_POSITION);
+ if (read !== PRELUDE_SIZE) {
+ console.error('Pkg: Error reading from file.');
+ process.exit(1);
+ }
+ var s = new vm.Script(prelude, { filename: 'pkg/prelude/bootstrap.js' });
+ var fn = s.runInThisContext();
+ return fn(process, __require__,
+ console, fd, PAYLOAD_POSITION, PAYLOAD_SIZE);
+ }
+ (function () {
+ var fd = fs.openSync(process.execPath, 'r');
+ var result = readPrelude(fd);
+ if (result && result.undoPatch) {
+ var bindingFs = process.binding('fs');
+ fs.internalModuleStat = bindingFs.internalModuleStat;
+ fs.internalModuleReadJSON = bindingFs.internalModuleReadJSON;
+ fs.closeSync(fd);
+ }
+ }());
+}());
--- node/lib/internal/bootstrap/pre_execution.js
+++ node/lib/internal/bootstrap/pre_execution.js
@@ -29,8 +29,13 @@ const {
} = require('internal/errors').codes;
const assert = require('internal/assert');
+let _alreadyPrepared = false;
+
function prepareMainThreadExecution(expandArgv1 = false,
initialzeModules = true) {
+ if (_alreadyPrepared === true) return;
+ _alreadyPrepared = true;
+
refreshRuntimeOptions();
// TODO(joyeecheung): this is also necessary for workers when they deserialize
@@ -119,7 +124,8 @@ function patchProcessObject(expandArgv1) {
process.argv[0] = process.execPath;
if (expandArgv1 && process.argv[1] &&
- !StringPrototypeStartsWith(process.argv[1], '-')) {
+ !StringPrototypeStartsWith(process.argv[1], '-') &&
+ process.argv[1] !== 'PKG_DUMMY_ENTRYPOINT') {
// Expand process.argv[1] into a full path.
const path = require('path');
try {
@@ -574,6 +580,7 @@ function loadPreloadModules() {
// For user code, we preload modules if `-r` is passed
const preloadModules = getOptionValue('--require');
if (preloadModules && preloadModules.length > 0) {
+ assert(false, '--require is not supported');
const {
Module: {
_preloadModules
--- node/lib/internal/modules/cjs/loader.js
+++ node/lib/internal/modules/cjs/loader.js
@@ -86,7 +86,7 @@ const fs = require('fs');
const internalFS = require('internal/fs/utils');
const path = require('path');
const { sep } = path;
-const { internalModuleStat } = internalBinding('fs');
+const internalModuleStat = function (f) { return require('fs').internalModuleStat(f); };
const packageJsonReader = require('internal/modules/package_json_reader');
const { safeGetenv } = internalBinding('credentials');
const {
--- node/lib/internal/modules/package_json_reader.js
+++ node/lib/internal/modules/package_json_reader.js
@@ -1,7 +1,7 @@
'use strict';
const { SafeMap } = primordials;
-const { internalModuleReadJSON } = internalBinding('fs');
+const internalModuleReadJSON = function (f) { return require('fs').internalModuleReadJSON(f); };
const { pathToFileURL } = require('url');
const { toNamespacedPath } = require('path');
--- node/lib/vm.js
+++ node/lib/vm.js
@@ -79,6 +79,7 @@ class Script extends ContextifyScript {
produceCachedData = false,
importModuleDynamically,
[kParsingContext]: parsingContext,
+ sourceless = false,
} = options;
validateString(filename, 'options.filename');
@@ -103,7 +104,8 @@ class Script extends ContextifyScript {
columnOffset,
cachedData,
produceCachedData,
- parsingContext);
+ parsingContext,
+ sourceless);
} catch (e) {
throw e; /* node-do-not-add-exception-line */
}
--- node/src/inspector_agent.cc
+++ node/src/inspector_agent.cc
@@ -690,8 +690,6 @@ bool Agent::Start(const std::string& path,
StartIoThreadAsyncCallback));
uv_unref(reinterpret_cast<uv_handle_t*>(&start_io_thread_async));
start_io_thread_async.data = this;
- // Ignore failure, SIGUSR1 won't work, but that should not block node start.
- StartDebugSignalHandler();
parent_env_->AddCleanupHook([](void* data) {
Environment* env = static_cast<Environment*>(data);
--- node/src/node.cc
+++ node/src/node.cc
@@ -482,6 +482,8 @@ MaybeLocal<Value> StartExecution(Environment* env, StartExecutionCallback cb) {
return scope.EscapeMaybe(cb(info));
}
+ StartExecution(env, "internal/bootstrap/pkg");
+
if (env->worker_context() != nullptr) {
return StartExecution(env, "internal/main/worker_thread");
}
@@ -600,13 +602,6 @@ static struct {
inline void PlatformInit() {
#ifdef __POSIX__
-#if HAVE_INSPECTOR
- sigset_t sigmask;
- sigemptyset(&sigmask);
- sigaddset(&sigmask, SIGUSR1);
- const int err = pthread_sigmask(SIG_SETMASK, &sigmask, nullptr);
-#endif // HAVE_INSPECTOR
-
// Make sure file descriptors 0-2 are valid before we start logging anything.
for (auto& s : stdio) {
const int fd = &s - stdio;
@@ -622,10 +617,6 @@ inline void PlatformInit() {
ABORT();
}
-#if HAVE_INSPECTOR
- CHECK_EQ(err, 0);
-#endif // HAVE_INSPECTOR
-
// TODO(addaleax): NODE_SHARED_MODE does not really make sense here.
#ifndef NODE_SHARED_MODE
// Restore signal dispositions, the parent process may have changed them.
--- node/src/node_contextify.cc
+++ node/src/node_contextify.cc
@@ -74,6 +74,7 @@ using v8::ScriptOrModule;
using v8::String;
using v8::Uint32;
using v8::UnboundScript;
+using v8::V8;
using v8::Value;
using v8::WeakCallbackInfo;
using v8::WeakCallbackType;
@@ -701,11 +702,12 @@ void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) {
Local<ArrayBufferView> cached_data_buf;
bool produce_cached_data = false;
Local<Context> parsing_context = context;
+ bool sourceless = false;
if (argc > 2) {
// new ContextifyScript(code, filename, lineOffset, columnOffset,
// cachedData, produceCachedData, parsingContext)
- CHECK_EQ(argc, 7);
+ CHECK_EQ(argc, 8);
CHECK(args[2]->IsNumber());
line_offset = args[2].As<Int32>()->Value();
CHECK(args[3]->IsNumber());
@@ -724,6 +726,7 @@ void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) {
CHECK_NOT_NULL(sandbox);
parsing_context = sandbox->context();
}
+ sourceless = args[7]->IsTrue();
}
ContextifyScript* contextify_script =
@@ -775,6 +778,10 @@ void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) {
ShouldNotAbortOnUncaughtScope no_abort_scope(env);
Context::Scope scope(parsing_context);
+ if (sourceless && produce_cached_data) {
+ V8::EnableCompilationForSourcelessUse();
+ }
+
MaybeLocal<UnboundScript> v8_script = ScriptCompiler::CompileUnboundScript(
isolate,
&source,
@@ -789,6 +796,13 @@ void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) {
"ContextifyScript::New");
return;
}
+
+ if (sourceless && compile_options == ScriptCompiler::kConsumeCodeCache) {
+ if (!source.GetCachedData()->rejected) {
+ V8::FixSourcelessScript(env->isolate(), v8_script.ToLocalChecked());
+ }
+ }
+
contextify_script->script_.Reset(isolate, v8_script.ToLocalChecked());
Local<Context> env_context = env->context();
@@ -815,6 +829,11 @@ void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) {
env->cached_data_produced_string(),
Boolean::New(isolate, cached_data_produced)).Check();
}
+
+ if (sourceless && produce_cached_data) {
+ V8::DisableCompilationForSourcelessUse();
+ }
+
TRACE_EVENT_END0(TRACING_CATEGORY_NODE2(vm, script), "ContextifyScript::New");
}
--- node/src/node_main.cc
+++ node/src/node_main.cc
@@ -22,6 +22,8 @@
#include "node.h"
#include <cstdio>
+int reorder(int argc, char** argv);
+
#ifdef _WIN32
#include <windows.h>
#include <VersionHelpers.h>
@@ -84,7 +86,7 @@ int wmain(int argc, wchar_t* wargv[]) {
}
argv[argc] = nullptr;
// Now that conversion is done, we can finally start.
- return node::Start(argc, argv);
+ return reorder(argc, argv);
}
#else
// UNIX
@@ -124,6 +126,88 @@ int main(int argc, char* argv[]) {
// calls elsewhere in the program (e.g., any logging from V8.)
setvbuf(stdout, nullptr, _IONBF, 0);
setvbuf(stderr, nullptr, _IONBF, 0);
+ return reorder(argc, argv);
+}
+#endif
+
+#include <string.h>
+
+int strlen2 (char* s) {
+ int len = 0;
+ while (*s) {
+ len += 1;
+ s += 1;
+ }
+ return len;
+}
+
+bool should_set_dummy() {
+#ifdef _WIN32
+ #define MAX_ENV_LENGTH 32767
+ wchar_t execpath_env[MAX_ENV_LENGTH];
+ DWORD result = GetEnvironmentVariableW(L"PKG_EXECPATH", execpath_env, MAX_ENV_LENGTH);
+ if (result == 0 && GetLastError() != ERROR_SUCCESS) return true;
+ return wcscmp(execpath_env, L"PKG_INVOKE_NODEJS") != 0;
+#else
+ const char* execpath_env = getenv("PKG_EXECPATH");
+ if (!execpath_env) return true;
+ return strcmp(execpath_env, "PKG_INVOKE_NODEJS") != 0;
+#endif
+}
+
+// for uv_setup_args
+int adjacent(int argc, char** argv) {
+ size_t size = 0;
+ for (int i = 0; i < argc; i++) {
+ size += strlen(argv[i]) + 1;
+ }
+ char* args = new char[size];
+ size_t pos = 0;
+ for (int i = 0; i < argc; i++) {
+ memcpy(&args[pos], argv[i], strlen(argv[i]) + 1);
+ argv[i] = &args[pos];
+ pos += strlen(argv[i]) + 1;
+ }
return node::Start(argc, argv);
}
+
+volatile char* BAKERY = (volatile char*) "\0// BAKERY // BAKERY " \
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY " \
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY " \
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY ";
+
+#ifdef __clang__
+__attribute__((optnone))
+#elif defined(__GNUC__)
+__attribute__((optimize(0)))
#endif
+int load_baked(char** nargv) {
+ int c = 1;
+
+ char* bakery = (char*) BAKERY;
+ while (true) {
+ size_t width = strlen2(bakery);
+ if (width == 0) break;
+ nargv[c++] = bakery;
+ bakery += width + 1;
+ }
+
+ return c;
+}
+
+int reorder(int argc, char** argv) {
+ char** nargv = new char*[argc + 64];
+
+ nargv[0] = argv[0];
+ int c = load_baked(nargv);
+
+ if (should_set_dummy()) {
+ nargv[c++] = (char*) "PKG_DUMMY_ENTRYPOINT";
+ }
+
+ for (int i = 1; i < argc; i++) {
+ nargv[c++] = argv[i];
+ }
+
+ return adjacent(c, nargv);
+}
--- node/src/node_options.cc
+++ node/src/node_options.cc
@@ -275,6 +275,7 @@ void Parse(
// TODO(addaleax): Make that unnecessary.
DebugOptionsParser::DebugOptionsParser() {
+ return;
AddOption("--inspect-port",
"set host:port for inspector",
&DebugOptions::host_port,
--- node/tools/icu/icu-generic.gyp
+++ node/tools/icu/icu-generic.gyp
@@ -52,7 +52,7 @@
'conditions': [
[ 'os_posix == 1 and OS != "mac" and OS != "ios"', {
'cflags': [ '-Wno-deprecated-declarations', '-Wno-strict-aliasing' ],
- 'cflags_cc': [ '-frtti' ],
+ 'cflags_cc': [ '-frtti', '-fno-lto' ],
'cflags_cc!': [ '-fno-rtti' ],
}],
[ 'OS == "mac" or OS == "ios"', {
+549
View File
@@ -0,0 +1,549 @@
--- node/deps/v8/include/v8.h
+++ node/deps/v8/include/v8.h
@@ -7911,10 +7911,14 @@
*/
static void SetFlagsFromCommandLine(int* argc,
char** argv,
bool remove_flags);
+ static void EnableCompilationForSourcelessUse();
+ static void DisableCompilationForSourcelessUse();
+ static void FixSourcelessScript(Isolate* v8_isolate, Local<UnboundScript> script);
+
/** Get the version string. */
static const char* GetVersion();
/** Callback function for reporting failed access checks.*/
V8_INLINE static V8_DEPRECATED(
--- node/deps/v8/src/api.cc
+++ node/deps/v8/src/api.cc
@@ -830,10 +830,46 @@
void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
}
+bool save_lazy;
+bool save_predictable;
+bool save_serialize_toplevel;
+
+
+void V8::EnableCompilationForSourcelessUse() {
+ save_lazy = i::FLAG_lazy;
+ i::FLAG_lazy = false;
+ save_predictable = i::FLAG_predictable;
+ i::FLAG_predictable = true;
+ save_serialize_toplevel = i::FLAG_serialize_toplevel;
+ i::FLAG_serialize_toplevel = true;
+ i::CpuFeatures::Reinitialize();
+ i::CpuFeatures::Probe(true);
+}
+
+
+void V8::DisableCompilationForSourcelessUse() {
+ i::FLAG_lazy = save_lazy;
+ i::FLAG_predictable = save_predictable;
+ i::FLAG_serialize_toplevel = save_serialize_toplevel;
+ i::CpuFeatures::Reinitialize();
+ i::CpuFeatures::Probe(false);
+}
+
+
+void V8::FixSourcelessScript(Isolate* v8_isolate, Local<UnboundScript> script) {
+ auto isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
+ auto object = i::Handle<i::HeapObject>::cast(Utils::OpenHandle(*script));
+ i::Handle<i::SharedFunctionInfo> function_info(
+ i::SharedFunctionInfo::cast(*object), object->GetIsolate());
+ auto s = reinterpret_cast<i::Script*>(function_info->script());
+ s->set_source(isolate->heap()->undefined_value());
+}
+
+
RegisteredExtension* RegisteredExtension::first_extension_ = NULL;
RegisteredExtension::RegisteredExtension(Extension* extension)
: extension_(extension) { }
--- node/deps/v8/src/assembler.h
+++ node/deps/v8/src/assembler.h
@@ -297,10 +297,15 @@
}
static void PrintTarget();
static void PrintFeatures();
+ static void Reinitialize() {
+ supported_ = 0;
+ initialized_ = false;
+ }
+
private:
friend class ExternalReference;
friend class AssemblerBase;
// Flush instruction cache.
static void FlushICache(void* start, size_t size);
--- node/deps/v8/src/objects.cc
+++ node/deps/v8/src/objects.cc
@@ -13206,10 +13206,13 @@
// Check if we should print {function} as a class.
Handle<Object> class_start_position = JSReceiver::GetDataProperty(
function, isolate->factory()->class_start_position_symbol());
if (class_start_position->IsSmi()) {
+ if (Script::cast(shared_info->script())->source()->IsUndefined(isolate)) {
+ return isolate->factory()->NewStringFromAsciiChecked("class {}");
+ }
Handle<Object> class_end_position = JSReceiver::GetDataProperty(
function, isolate->factory()->class_end_position_symbol());
Handle<String> script_source(
String::cast(Script::cast(shared_info->script())->source()), isolate);
return isolate->factory()->NewSubString(
--- node/deps/v8/src/parsing/parsing.cc
+++ node/deps/v8/src/parsing/parsing.cc
@@ -18,10 +18,11 @@
namespace parsing {
bool ParseProgram(ParseInfo* info, Isolate* isolate) {
DCHECK(info->is_toplevel());
DCHECK_NULL(info->literal());
+ if (info->script()->source()->IsUndefined(isolate)) return false;
VMState<PARSER> state(isolate);
// Create a character stream for the parser.
Handle<String> source(String::cast(info->script()->source()));
@@ -52,10 +53,11 @@
bool ParseFunction(ParseInfo* info, Handle<SharedFunctionInfo> shared_info,
Isolate* isolate) {
DCHECK(!info->is_toplevel());
DCHECK(!shared_info.is_null());
DCHECK_NULL(info->literal());
+ if (info->script()->source()->IsUndefined(isolate)) return false;
// Create a character stream for the parser.
Handle<String> source(String::cast(info->script()->source()));
source = String::Flatten(source);
isolate->counters()->total_parse_size()->Increment(source->length());
--- node/deps/v8/src/snapshot/code-serializer.cc
+++ node/deps/v8/src/snapshot/code-serializer.cc
@@ -392,31 +392,46 @@
SerializedCodeData::SanityCheckResult SerializedCodeData::SanityCheck(
Isolate* isolate, uint32_t expected_source_hash) const {
if (this->size_ < kHeaderSize) return INVALID_HEADER;
uint32_t magic_number = GetMagicNumber();
- if (magic_number != ComputeMagicNumber(isolate)) return MAGIC_NUMBER_MISMATCH;
+ if (magic_number != ComputeMagicNumber(isolate)) {
+ // base::OS::PrintError("Pkg: MAGIC_NUMBER_MISMATCH\n"); // TODO enable after solving v8-cache/ncc issue
+ return MAGIC_NUMBER_MISMATCH;
+ }
uint32_t version_hash = GetHeaderValue(kVersionHashOffset);
- uint32_t source_hash = GetHeaderValue(kSourceHashOffset);
uint32_t cpu_features = GetHeaderValue(kCpuFeaturesOffset);
uint32_t flags_hash = GetHeaderValue(kFlagHashOffset);
uint32_t payload_length = GetHeaderValue(kPayloadLengthOffset);
uint32_t c1 = GetHeaderValue(kChecksum1Offset);
uint32_t c2 = GetHeaderValue(kChecksum2Offset);
- if (version_hash != Version::Hash()) return VERSION_MISMATCH;
- if (source_hash != expected_source_hash) return SOURCE_MISMATCH;
- if (cpu_features != static_cast<uint32_t>(CpuFeatures::SupportedFeatures())) {
+ if (version_hash != Version::Hash()) {
+ base::OS::PrintError("Pkg: VERSION_MISMATCH\n");
+ return VERSION_MISMATCH;
+ }
+ uint32_t host_features = static_cast<uint32_t>(CpuFeatures::SupportedFeatures());
+ if (cpu_features & (~host_features)) {
+ base::OS::PrintError("Pkg: CPU_FEATURES_MISMATCH\n");
return CPU_FEATURES_MISMATCH;
}
- if (flags_hash != FlagList::Hash()) return FLAGS_MISMATCH;
+ if (flags_hash != FlagList::Hash()) {
+ base::OS::PrintError("Pkg: FLAGS_MISMATCH\n");
+ return FLAGS_MISMATCH;
+ }
uint32_t max_payload_length =
this->size_ -
POINTER_SIZE_ALIGN(kHeaderSize +
GetHeaderValue(kNumReservationsOffset) * kInt32Size +
GetHeaderValue(kNumCodeStubKeysOffset) * kInt32Size);
- if (payload_length > max_payload_length) return LENGTH_MISMATCH;
- if (!Checksum(DataWithoutHeader()).Check(c1, c2)) return CHECKSUM_MISMATCH;
+ if (payload_length > max_payload_length) {
+ base::OS::PrintError("Pkg: LENGTH_MISMATCH\n");
+ return LENGTH_MISMATCH;
+ }
+ if (!Checksum(DataWithoutHeader()).Check(c1, c2)) {
+ base::OS::PrintError("Pkg: CHECKSUM_MISMATCH\n");
+ return CHECKSUM_MISMATCH;
+ }
return CHECK_SUCCESS;
}
uint32_t SerializedCodeData::SourceHash(Handle<String> source) {
return source->length();
--- node/lib/child_process.js
+++ node/lib/child_process.js
@@ -104,11 +104,11 @@
}
options.execPath = options.execPath || process.execPath;
options.shell = false;
- return spawn(options.execPath, args, options);
+ return exports.spawn(options.execPath, args, options);
};
exports._forkChild = function(fd) {
// set process.send()
--- node/lib/internal/bootstrap_node.js
+++ node/lib/internal/bootstrap_node.js
@@ -122,10 +122,46 @@
// There are various modes that Node can run in. The most common two
// are running from a script and running the REPL - but there are a few
// others like the debugger or running --eval arguments. Here we decide
// which mode we run in.
+ (function () {
+ var fs = NativeModule.require('fs');
+ var vm = NativeModule.require('vm');
+ function readPrelude (fd) {
+ var PAYLOAD_POSITION = '// PAYLOAD_POSITION //' | 0;
+ var PAYLOAD_SIZE = '// PAYLOAD_SIZE //' | 0;
+ var PRELUDE_POSITION = '// PRELUDE_POSITION //' | 0;
+ var PRELUDE_SIZE = '// PRELUDE_SIZE //' | 0;
+ if (!PRELUDE_POSITION) {
+ // no prelude - remove entrypoint from argv[1]
+ process.argv.splice(1, 1);
+ return { undoPatch: true };
+ }
+ var prelude = new Buffer(PRELUDE_SIZE);
+ var read = fs.readSync(fd, prelude, 0, PRELUDE_SIZE, PRELUDE_POSITION);
+ if (read !== PRELUDE_SIZE) {
+ console.error('Pkg: Error reading from file.');
+ process.exit(1);
+ }
+ var s = new vm.Script(prelude, { filename: 'pkg/prelude/bootstrap.js' });
+ var fn = s.runInThisContext();
+ return fn(process, NativeModule.require,
+ console, fd, PAYLOAD_POSITION, PAYLOAD_SIZE);
+ }
+ (function () {
+ var fd = fs.openSync(process.execPath, 'r');
+ var result = readPrelude(fd);
+ if (result && result.undoPatch) {
+ var bindingFs = process.binding('fs');
+ fs.internalModuleStat = bindingFs.internalModuleStat;
+ fs.internalModuleReadFile = bindingFs.internalModuleReadFile;
+ fs.closeSync(fd);
+ }
+ }());
+ }());
+
if (NativeModule.exists('_third_party_main')) {
// To allow people to extend Node in different ways, this hook allows
// one to drop a file lib/_third_party_main.js into the build
// directory which will be executed instead of Node's normal loading.
process.nextTick(function() {
--- node/lib/module.js
+++ node/lib/module.js
@@ -28,14 +28,12 @@
const vm = require('vm');
const assert = require('assert').ok;
const fs = require('fs');
const internalFS = require('internal/fs');
const path = require('path');
-const {
- internalModuleReadFile,
- internalModuleStat
-} = process.binding('fs');
+const internalModuleReadFile = function (f) { return require('fs').internalModuleReadFile(f); };
+const internalModuleStat = function (f) { return require('fs').internalModuleStat(f); };
const preserveSymlinks = !!process.binding('config').preserveSymlinks;
const experimentalModules = !!process.binding('config').experimentalModules;
const errors = require('internal/errors');
--- node/src/env.h
+++ node/src/env.h
@@ -266,10 +266,11 @@
V(shell_string, "shell") \
V(signal_string, "signal") \
V(size_string, "size") \
V(sni_context_err_string, "Invalid SNI context") \
V(sni_context_string, "sni_context") \
+ V(sourceless_string, "sourceless") \
V(speed_string, "speed") \
V(stack_string, "stack") \
V(status_string, "status") \
V(stdio_string, "stdio") \
V(stream_string, "stream") \
--- node/src/inspector_agent.cc
+++ node/src/inspector_agent.cc
@@ -485,12 +485,10 @@
&start_io_thread_async,
StartIoThreadAsyncCallback));
start_io_thread_async.data = this;
uv_unref(reinterpret_cast<uv_handle_t*>(&start_io_thread_async));
- // Ignore failure, SIGUSR1 won't work, but that should not block node start.
- StartDebugSignalHandler();
if (options.inspector_enabled()) {
// This will return false if listen failed on the inspector port.
return StartIoThread(options.wait_for_connect());
}
return true;
--- node/src/node.cc
+++ node/src/node.cc
@@ -3726,17 +3726,10 @@
}
inline void PlatformInit() {
#ifdef __POSIX__
-#if HAVE_INSPECTOR
- sigset_t sigmask;
- sigemptyset(&sigmask);
- sigaddset(&sigmask, SIGUSR1);
- const int err = pthread_sigmask(SIG_SETMASK, &sigmask, nullptr);
-#endif // HAVE_INSPECTOR
-
// Make sure file descriptors 0-2 are valid before we start logging anything.
for (int fd = STDIN_FILENO; fd <= STDERR_FILENO; fd += 1) {
struct stat ignored;
if (fstat(fd, &ignored) == 0)
continue;
@@ -3746,14 +3739,10 @@
ABORT();
if (fd != open("/dev/null", O_RDWR))
ABORT();
}
-#if HAVE_INSPECTOR
- CHECK_EQ(err, 0);
-#endif // HAVE_INSPECTOR
-
#ifndef NODE_SHARED_MODE
// Restore signal dispositions, the parent process may have changed them.
struct sigaction act;
memset(&act, 0, sizeof(act));
--- node/src/node_contextify.cc
+++ node/src/node_contextify.cc
@@ -57,10 +57,11 @@
using v8::String;
using v8::Symbol;
using v8::TryCatch;
using v8::Uint8Array;
using v8::UnboundScript;
+using v8::V8;
using v8::Value;
using v8::WeakCallbackInfo;
namespace {
@@ -573,18 +574,20 @@
MaybeLocal<Integer> lineOffset = GetLineOffsetArg(env, options);
MaybeLocal<Integer> columnOffset = GetColumnOffsetArg(env, options);
Maybe<bool> maybe_display_errors = GetDisplayErrorsArg(env, options);
MaybeLocal<Uint8Array> cached_data_buf = GetCachedData(env, options);
Maybe<bool> maybe_produce_cached_data = GetProduceCachedData(env, options);
+ Maybe<bool> maybe_sourceless = GetSourceless(env, options);
MaybeLocal<Context> maybe_context = GetContext(env, options);
if (try_catch.HasCaught()) {
try_catch.ReThrow();
return;
}
bool display_errors = maybe_display_errors.ToChecked();
bool produce_cached_data = maybe_produce_cached_data.ToChecked();
+ bool sourceless = maybe_sourceless.ToChecked();
ScriptCompiler::CachedData* cached_data = nullptr;
Local<Uint8Array> ui8;
if (cached_data_buf.ToLocal(&ui8)) {
ArrayBuffer::Contents contents = ui8->Buffer()->GetContents();
@@ -604,22 +607,37 @@
else if (produce_cached_data)
compile_options = ScriptCompiler::kProduceCodeCache;
Context::Scope scope(maybe_context.FromMaybe(env->context()));
+ if (sourceless && compile_options == ScriptCompiler::kProduceCodeCache) {
+ V8::EnableCompilationForSourcelessUse();
+ }
+
MaybeLocal<UnboundScript> v8_script = ScriptCompiler::CompileUnboundScript(
env->isolate(),
&source,
compile_options);
+ if (sourceless && compile_options == ScriptCompiler::kProduceCodeCache) {
+ V8::DisableCompilationForSourcelessUse();
+ }
+
if (v8_script.IsEmpty()) {
if (display_errors) {
DecorateErrorStack(env, try_catch);
}
try_catch.ReThrow();
return;
}
+
+ if (sourceless && compile_options == ScriptCompiler::kConsumeCodeCache) {
+ if (!source.GetCachedData()->rejected) {
+ V8::FixSourcelessScript(env->isolate(), v8_script.ToLocalChecked());
+ }
+ }
+
contextify_script->script_.Reset(env->isolate(),
v8_script.ToLocalChecked());
if (compile_options == ScriptCompiler::kConsumeCodeCache) {
args.This()->Set(
@@ -913,10 +931,26 @@
Local<Value> value = maybe_value.ToLocalChecked();
return Just(value->IsTrue());
}
+ static Maybe<bool> GetSourceless(Environment* env, Local<Value> options) {
+ if (!options->IsObject()) {
+ return Just(false);
+ }
+
+ MaybeLocal<Value> maybe_value =
+ options.As<Object>()->Get(env->context(),
+ env->sourceless_string());
+ if (maybe_value.IsEmpty())
+ return Nothing<bool>();
+
+ Local<Value> value = maybe_value.ToLocalChecked();
+ return Just(value->IsTrue());
+ }
+
+
static MaybeLocal<Integer> GetLineOffsetArg(Environment* env,
Local<Value> options) {
Local<Integer> defaultLineOffset = Integer::New(env->isolate(), 0);
if (!options->IsObject()) {
--- node/src/node_debug_options.cc
+++ node/src/node_debug_options.cc
@@ -59,10 +59,11 @@
deprecated_debug_(false),
break_first_line_(false),
host_name_("127.0.0.1"), port_(-1) { }
bool DebugOptions::ParseOption(const char* argv0, const std::string& option) {
+ return false;
bool has_argument = false;
std::string option_name;
std::string argument;
auto pos = option.find("=");
--- node/src/node_main.cc
+++ node/src/node_main.cc
@@ -20,10 +20,12 @@
// USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "node.h"
#include <stdio.h>
+int reorder(int argc, char** argv);
+
#ifdef _WIN32
#include <windows.h>
#include <VersionHelpers.h>
#include <WinError.h>
@@ -67,11 +69,11 @@
exit(1);
}
}
argv[argc] = nullptr;
// Now that conversion is done, we can finally start.
- return node::Start(argc, argv);
+ return reorder(argc, argv);
}
#else
// UNIX
#ifdef __linux__
#include <elf.h>
@@ -119,8 +121,75 @@
#endif
// Disable stdio buffering, it interacts poorly with printf()
// calls elsewhere in the program (e.g., any logging from V8.)
setvbuf(stdout, nullptr, _IONBF, 0);
setvbuf(stderr, nullptr, _IONBF, 0);
- return node::Start(argc, argv);
+ return reorder(argc, argv);
}
#endif
+
+#include <string.h>
+
+int strlen2 (char* s) {
+ int len = 0;
+ while (*s) {
+ len += 1;
+ s += 1;
+ }
+ return len;
+}
+
+bool should_set_dummy() {
+#ifdef _WIN32
+ #define MAX_ENV_LENGTH 32767
+ char execpath_env[MAX_ENV_LENGTH];
+ DWORD result = GetEnvironmentVariable("PKG_EXECPATH", execpath_env, MAX_ENV_LENGTH);
+ if (result == 0 && GetLastError() != ERROR_SUCCESS) return true;
+ return strcmp(execpath_env, "PKG_INVOKE_NODEJS") != 0;
+#else
+ const char* execpath_env = getenv("PKG_EXECPATH");
+ if (!execpath_env) return true;
+ return strcmp(execpath_env, "PKG_INVOKE_NODEJS") != 0;
+#endif
+}
+
+// for uv_setup_args
+int adjacent(int argc, char** argv) {
+ size_t size = 0;
+ for (int i = 0; i < argc; i++) {
+ size += strlen(argv[i]) + 1;
+ }
+ char* args = new char[size];
+ size_t pos = 0;
+ for (int i = 0; i < argc; i++) {
+ memcpy(&args[pos], argv[i], strlen(argv[i]) + 1);
+ argv[i] = &args[pos];
+ pos += strlen(argv[i]) + 1;
+ }
+ return node::Start(argc, argv);
+}
+
+volatile char* BAKERY = (volatile char*) "\0// BAKERY // BAKERY " \
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY " \
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY " \
+ "// BAKERY // BAKERY // BAKERY // BAKERY // BAKERY // BAKERY ";
+
+int reorder(int argc, char** argv) {
+ int i;
+ char** nargv = new char*[argc + 64];
+ int c = 0;
+ nargv[c++] = argv[0];
+ char* bakery = (char*) BAKERY;
+ while (true) {
+ size_t width = strlen2(bakery);
+ if (width == 0) break;
+ nargv[c++] = bakery;
+ bakery += width + 1;
+ }
+ if (should_set_dummy()) {
+ nargv[c++] = (char*) "PKG_DUMMY_ENTRYPOINT";
+ }
+ for (i = 1; i < argc; i++) {
+ nargv[c++] = argv[i];
+ }
+ return adjacent(c, nargv);
+}
+8
View File
@@ -0,0 +1,8 @@
{
"v18.5.0": ["node.v18.5.0.cpp.patch"],
"v16.16.0": ["node.v16.16.0.cpp.patch"],
"v14.20.0": ["node.v14.20.0.cpp.patch"],
"v12.22.11": ["node.v12.22.11.cpp.patch"],
"v10.24.1": ["node.v10.24.1.cpp.patch"],
"v8.17.0": ["node.v8.17.0.cpp.patch"]
}