Initial commit
This commit is contained in:
commit
e49726988c
5445 files changed
+1089914
No files matched your search
+49
@@ -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
@@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env node
|
||||
export {};
|
||||
//# sourceMappingURL=bin.d.ts.map
|
||||
+102
@@ -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
@@ -0,0 +1,2 @@
|
||||
export default function build(nodeVersion: string, targetArch: string, targetPlatform: string, local: string): Promise<void>;
|
||||
//# sourceMappingURL=build.d.ts.map
|
||||
+394
@@ -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
@@ -0,0 +1,2 @@
|
||||
export declare const EXPECTED_HASHES: Record<string, string>;
|
||||
//# sourceMappingURL=expected.d.ts.map
|
||||
+97
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,2 @@
|
||||
export declare function verify(local: string): Promise<void>;
|
||||
//# sourceMappingURL=verify.d.ts.map
|
||||
+60
@@ -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
@@ -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
@@ -0,0 +1 @@
|
||||
../../../semver/bin/semver.js
|
||||
+64
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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"]
|
||||
}
|
||||
Reference in new issue
Block a user