Merge remote-tracking branch '1609-pkg-fetch-private/master'
This commit is contained in:
commit
b700a8c8e1
@ -1,5 +1,4 @@
|
||||
/lib
|
||||
/patches/*.patch
|
||||
/test
|
||||
.eslintignore
|
||||
.gitignore
|
||||
|
||||
10
lib/bin.js
10
lib/bin.js
@ -5,18 +5,20 @@ import minimist from 'minimist';
|
||||
import { need } from './index.js';
|
||||
|
||||
async function main () {
|
||||
const argv = minimist(process.argv.slice(2));
|
||||
const argv = minimist(process.argv.slice(2), {
|
||||
string: [ 'n', 'p', 'a', 'f', 'b' ]
|
||||
});
|
||||
const nodeRange = argv.n || argv._.shift();
|
||||
const platform = argv.p || argv._.shift();
|
||||
const arch = argv.a || argv._.shift();
|
||||
const forceDownload = argv.d;
|
||||
const forceFetch = argv.f;
|
||||
const forceBuild = argv.b;
|
||||
const local = await need({ nodeRange, platform,
|
||||
arch, forceDownload, forceBuild });
|
||||
arch, forceFetch, forceBuild });
|
||||
log.info(local);
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
log.error(error);
|
||||
if (!error.wasReported) log.error(error);
|
||||
process.exit(2);
|
||||
});
|
||||
|
||||
@ -22,13 +22,16 @@ async function gitClone () {
|
||||
|
||||
async function gitResetHard (nodeVersion) {
|
||||
log.info(`Checking out ${nodeVersion}`);
|
||||
const args = [ '--work-tree', '.', 'reset', '--hard', nodeVersion ];
|
||||
const patches = patchesJson[nodeVersion];
|
||||
const commit = patches.commit || nodeVersion;
|
||||
const args = [ '--work-tree', '.', 'reset', '--hard', commit ];
|
||||
await spawn('git', args, { cwd: nodePath });
|
||||
}
|
||||
|
||||
async function applyPatches (nodeVersion) {
|
||||
log.info('Applying patches');
|
||||
const patches = patchesJson[nodeVersion];
|
||||
let patches = patchesJson[nodeVersion];
|
||||
patches = patches.patches || patches;
|
||||
for (const patch of patches) {
|
||||
const patchPath = path.join(patchesPath, patch);
|
||||
const args = [ '-p1', '-i', patchPath ];
|
||||
|
||||
46
lib/cloud.js
46
lib/cloud.js
@ -1,49 +1,53 @@
|
||||
import { createRelease, downloadAsset,
|
||||
getRelease, uploadAsset } from './github.js';
|
||||
import { createRelease, downloadUrl, getRelease,
|
||||
getReleaseDraft, tryDirectly, uploadAsset } from './github.js';
|
||||
import { mkdirp, remove } from 'fs-promise';
|
||||
import assert from 'assert';
|
||||
import { moveFile } from './copy-file.js';
|
||||
import path from 'path';
|
||||
import { version } from '../package.json';
|
||||
|
||||
function uniqueName (remote, names) {
|
||||
if (names.indexOf(remote) < 0) return remote;
|
||||
let name;
|
||||
function uniqueName (name, names) {
|
||||
if (names.indexOf(name) < 0) return name;
|
||||
let newName;
|
||||
let counter = 0;
|
||||
while (true) {
|
||||
name = `${remote}-${counter}`;
|
||||
if (names.indexOf(name) < 0) return name;
|
||||
newName = `${name}-new-${counter}`;
|
||||
if (names.indexOf(newName) < 0) return newName;
|
||||
counter += 1;
|
||||
}
|
||||
}
|
||||
|
||||
export async function upload (local, remote) {
|
||||
const tag = `v${version}`;
|
||||
const { tag } = remote;
|
||||
let release = await getRelease(tag);
|
||||
if (!release) release = await getReleaseDraft(tag);
|
||||
if (!release) release = await createRelease(tag);
|
||||
const names = release.assets.map(({ name }) => {
|
||||
assert(name);
|
||||
return name;
|
||||
});
|
||||
const name = uniqueName(remote, names);
|
||||
const name = uniqueName(remote.name, names);
|
||||
await uploadAsset(local, release, name);
|
||||
}
|
||||
|
||||
export async function download (remote, local) {
|
||||
const tag = `v${version}`;
|
||||
const release = await getRelease(tag);
|
||||
if (!release) return false;
|
||||
const assets = release.assets.filter(({ name }) => {
|
||||
assert(name);
|
||||
return name === remote;
|
||||
});
|
||||
if (!assets.length) return false;
|
||||
assert(assets.length === 1);
|
||||
const asset = assets[0];
|
||||
const { tag } = remote;
|
||||
const tempFile = local + '.downloading';
|
||||
await mkdirp(path.dirname(tempFile));
|
||||
const short = path.basename(local);
|
||||
await downloadAsset(asset, tempFile, short);
|
||||
const ok = await tryDirectly(tag, remote.name, tempFile, short);
|
||||
if (!ok) {
|
||||
let release = await getRelease(tag);
|
||||
if (!release) release = await getReleaseDraft(tag);
|
||||
if (!release) return false;
|
||||
const assets = release.assets.filter(({ name }) => {
|
||||
assert(name);
|
||||
return name === remote.name;
|
||||
});
|
||||
if (!assets.length) return false;
|
||||
assert(assets.length === 1);
|
||||
const asset = assets[0];
|
||||
await downloadUrl(asset.url, tempFile, short);
|
||||
}
|
||||
await remove(local);
|
||||
await moveFile(tempFile, local);
|
||||
await remove(tempFile);
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
/* eslint-disable camelcase */
|
||||
|
||||
import { log, wasReported } from './log.js';
|
||||
import assert from 'assert';
|
||||
import fs from 'fs';
|
||||
import { log } from './log.js';
|
||||
import progress from 'request-progress';
|
||||
import request from 'request';
|
||||
|
||||
@ -11,27 +11,39 @@ const REPO = 'pkg-fetch';
|
||||
const { GITHUB_USERNAME, GITHUB_PASSWORD } = process.env;
|
||||
const auth = { user: GITHUB_USERNAME, pass: GITHUB_PASSWORD };
|
||||
const request2 = request.defaults({
|
||||
auth: auth.user ? auth : null,
|
||||
auth: auth.user ? auth : undefined,
|
||||
headers: { 'User-Agent': `${OWNER}/${REPO}/${GITHUB_USERNAME}` },
|
||||
timeout: 30 * 1000
|
||||
});
|
||||
|
||||
export function getRelease (tag) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const url = `https://api.github.com/repos/${OWNER}/${REPO}/releases/tags/${tag}`;
|
||||
request2(url, (error, response, body) => {
|
||||
if (error) return reject(wasReported(error.message));
|
||||
const release = JSON.parse(body);
|
||||
const { message } = release;
|
||||
if (message === 'Not Found') return resolve(undefined);
|
||||
if (message) return reject(wasReported(message));
|
||||
resolve(release);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function getReleaseDraft (tag) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const url = `https://api.github.com/repos/${OWNER}/${REPO}/releases`;
|
||||
request2(url, (error, response, body) => {
|
||||
if (error) return reject(error);
|
||||
// we cannot use `get release by tag` endpoint here
|
||||
if (error) return reject(wasReported(error.message));
|
||||
// here we use `get release by tag` endpoint
|
||||
// because draft releases are really `untagged`.
|
||||
// seems that `get release by tag` is for non-drafts.
|
||||
// hence listing all releases and looking through them
|
||||
const releases = JSON.parse(body);
|
||||
if (releases.message) return reject(new Error(releases.message));
|
||||
if (releases.message) return reject(wasReported(releases.message));
|
||||
const found = releases.filter(({ tag_name }) => tag_name === tag); // eslint-disable-line camelcase
|
||||
if (found.length > 1) {
|
||||
return reject(new Error(`More than one ${tag} release found. Fix it!`));
|
||||
}
|
||||
if (!found.length) return resolve(null);
|
||||
assert(found.length <= 1);
|
||||
if (!found.length) return resolve(undefined);
|
||||
resolve(found[0]);
|
||||
});
|
||||
});
|
||||
@ -48,9 +60,9 @@ export function createRelease (tag) {
|
||||
});
|
||||
const url = `https://api.github.com/repos/${OWNER}/${REPO}/releases`;
|
||||
request2.post(url, { form }, (error, response, body) => {
|
||||
if (error) return reject(error);
|
||||
if (error) return reject(wasReported(error.message));
|
||||
const release = JSON.parse(body);
|
||||
if (release.message) return reject(new Error(release.message));
|
||||
if (release.message) return reject(wasReported(release.message));
|
||||
resolve(release);
|
||||
});
|
||||
});
|
||||
@ -69,11 +81,11 @@ export function uploadAsset (file, release, name) {
|
||||
const subst = `?name=${name}`;
|
||||
const url = release.upload_url.replace(/\{\?name,label\}/, subst);
|
||||
const req = request2.post(url, { headers }, (error2, response, body) => {
|
||||
if (error2) return reject(error2);
|
||||
if (error2) return reject(wasReported(error2.message));
|
||||
const asset = JSON.parse(body);
|
||||
const { errors } = asset;
|
||||
if (errors && errors[0]) return reject(new Error(errors[0].code));
|
||||
if (asset.message) return reject(new Error(asset.message));
|
||||
if (errors && errors[0]) return reject(wasReported(errors[0].code));
|
||||
if (asset.message) return reject(wasReported(asset.message));
|
||||
resolve(asset);
|
||||
});
|
||||
rs.pipe(req);
|
||||
@ -81,16 +93,24 @@ export function uploadAsset (file, release, name) {
|
||||
});
|
||||
}
|
||||
|
||||
export function downloadAsset (asset, file, short) {
|
||||
export function downloadUrl (url, file, short) {
|
||||
log.enableProgress(short);
|
||||
log.showProgress(0);
|
||||
return new Promise((resolve, reject) => {
|
||||
const headers = { Accept: 'application/octet-stream' };
|
||||
const ws = fs.createWriteStream(file);
|
||||
const url = asset.url;
|
||||
const req = progress(request2.get(url, { headers }, (error, response) => {
|
||||
if (error) {
|
||||
log.disableProgress();
|
||||
return reject(wasReported(error.message));
|
||||
}
|
||||
if (response.statusCode !== 200) {
|
||||
log.disableProgress();
|
||||
const message = `${response.statusCode} ${response.body}`;
|
||||
return reject(wasReported(message, url));
|
||||
}
|
||||
log.showProgress(100);
|
||||
log.disableProgress();
|
||||
if (error) return reject(error);
|
||||
resolve(response);
|
||||
}));
|
||||
req.on('progress', (state) => {
|
||||
@ -100,3 +120,14 @@ export function downloadAsset (asset, file, short) {
|
||||
req.pipe(ws);
|
||||
});
|
||||
}
|
||||
|
||||
export async function tryDirectly (tag, name, file, short) {
|
||||
try {
|
||||
const url = `https://github.com/${OWNER}/${REPO}/releases/download/${tag}/${name}`;
|
||||
await downloadUrl(url, file, short);
|
||||
return true;
|
||||
} catch (error) {
|
||||
log.info(`Asset '${tag}/${name}' not found by direct link`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
65
lib/index.js
65
lib/index.js
@ -1,25 +1,28 @@
|
||||
import * as system from './system.js';
|
||||
import { abiToNodeRange, // eslint-disable-line no-duplicate-imports
|
||||
toFancyArch, toFancyPlatform } from './system.js';
|
||||
hostPlatform, knownArchs, toFancyArch, toFancyPlatform } from './system.js';
|
||||
import { localPlace, remotePlace } from './places.js';
|
||||
import { log, wasReported } from './log.js';
|
||||
import build from './build.js';
|
||||
import { download } from './cloud.js';
|
||||
import { exists } from 'fs-promise';
|
||||
import { log } from './log.js';
|
||||
import patchesJson from '../patches/patches.json';
|
||||
import path from 'path';
|
||||
import semver from 'semver';
|
||||
import { version } from '../package.json';
|
||||
|
||||
export async function need ({
|
||||
nodeRange, platform, arch, forceDownload, forceBuild
|
||||
} = {}) {
|
||||
if (!nodeRange) throw new Error('nodeRange not specified');
|
||||
if (!platform) throw new Error('platform not specified');
|
||||
if (!arch) throw new Error('arch not specified');
|
||||
export async function need (opts = {}) {
|
||||
let { nodeRange, platform, arch, forceFetch, forceBuild } = opts;
|
||||
if (!nodeRange) throw wasReported('nodeRange not specified');
|
||||
if (!platform) throw wasReported('platform not specified');
|
||||
if (!arch) throw wasReported('arch not specified');
|
||||
|
||||
nodeRange = abiToNodeRange(nodeRange); // 'm48' -> 'node6'
|
||||
if (nodeRange !== 'latest') {
|
||||
if (!(/^node/.test(nodeRange))) throw wasReported('nodeRange must start with \'node\'');
|
||||
nodeRange = 'v' + nodeRange.slice(4); // 'node6' -> 'v6' for semver
|
||||
}
|
||||
|
||||
nodeRange = abiToNodeRange(nodeRange); // m48 -> '6'
|
||||
nodeRange = nodeRange.toString(); // 6 -> '6'
|
||||
platform = toFancyPlatform(platform); // win32 -> win
|
||||
arch = toFancyArch(arch); // ia32 -> x86
|
||||
|
||||
@ -28,25 +31,41 @@ export async function need ({
|
||||
nodeRange === 'latest')
|
||||
.sort((nv1, nv2) => semver.gt(nv1, nv2));
|
||||
if (!nodeVersions.length) {
|
||||
throw new Error(`No available node version satisfies '${nodeRange}'`);
|
||||
throw wasReported(`No available node version satisfies '${opts.nodeRange}'`);
|
||||
}
|
||||
const nodeVersion = nodeVersions.pop();
|
||||
const local = localPlace({ arch, nodeVersion, platform, version });
|
||||
const name = path.basename(local);
|
||||
const fetched = localPlace({ from: 'fetched', arch, nodeVersion, platform, version });
|
||||
const built = localPlace({ from: 'built', arch, nodeVersion, platform, version });
|
||||
const remote = remotePlace({ arch, nodeVersion, platform, version });
|
||||
|
||||
let downloadFailed;
|
||||
if (!forceDownload && !forceBuild) {
|
||||
if (await exists(local)) return local;
|
||||
let fetchFailed;
|
||||
if (!forceBuild) {
|
||||
if (await exists(fetched)) return fetched;
|
||||
}
|
||||
if (!forceFetch) {
|
||||
if (await exists(built)) {
|
||||
if (forceBuild) log.info('Reusing base binaries built locally:', built);
|
||||
return built;
|
||||
}
|
||||
}
|
||||
if (!forceBuild) {
|
||||
log.info('Downloading base binaries to \'~/.pkg-cache\'...', name);
|
||||
const remote = remotePlace({ arch, nodeVersion, platform, version });
|
||||
if (await download(remote, local)) return local;
|
||||
downloadFailed = true;
|
||||
log.info('Fetching base binaries to:', path.dirname(fetched));
|
||||
if (await download(remote, fetched)) return fetched;
|
||||
fetchFailed = true;
|
||||
}
|
||||
if (downloadFailed) log.info('Not found in GitHub releases. Building...');
|
||||
await build(nodeVersion, arch, local);
|
||||
return local;
|
||||
if (fetchFailed) {
|
||||
log.info('Not found in GitHub releases:', JSON.stringify(remote));
|
||||
}
|
||||
log.info('Building base binary from source:', path.basename(built));
|
||||
if (hostPlatform !== platform) {
|
||||
throw wasReported(`Not able to build for '${opts.platform}' here, only for '${hostPlatform}'`);
|
||||
}
|
||||
if (knownArchs.indexOf(arch) < 0) {
|
||||
throw wasReported(`Unknown arch '${opts.arch}'. Specify ${knownArchs.join(', ')}`);
|
||||
}
|
||||
|
||||
await build(nodeVersion, arch, built);
|
||||
return built;
|
||||
}
|
||||
|
||||
export { system };
|
||||
|
||||
52
lib/log.js
52
lib/log.js
@ -3,22 +3,43 @@ import assert from 'assert';
|
||||
import chalk from 'chalk';
|
||||
|
||||
class Log {
|
||||
info (text) {
|
||||
_lines (lines) {
|
||||
if (lines === undefined) return;
|
||||
if (!Array.isArray(lines)) {
|
||||
console.log(` ${lines}`);
|
||||
return;
|
||||
}
|
||||
for (const line of lines) {
|
||||
console.log(` ${line}`);
|
||||
}
|
||||
}
|
||||
|
||||
debug (text, lines) {
|
||||
if (!this.debugMode) return;
|
||||
console.log(`> ${chalk.green('[debug]')} ${text}`);
|
||||
this._lines(lines);
|
||||
}
|
||||
|
||||
info (text, lines) {
|
||||
console.log(`> ${text}`);
|
||||
this._lines(lines);
|
||||
}
|
||||
|
||||
warn (text) {
|
||||
console.log(`> ${chalk.blue('WARN')} ${text}`);
|
||||
warn (text, lines) {
|
||||
console.log(`> ${chalk.blue('Warning')} ${text}`);
|
||||
this._lines(lines);
|
||||
}
|
||||
|
||||
error (text) {
|
||||
error (text, lines) {
|
||||
if (text.stack) text = text.stack;
|
||||
console.log(`> ${chalk.red('ERR!')} ${text}`);
|
||||
console.log(`> ${chalk.red('Error!')} ${text}`);
|
||||
this._lines(lines);
|
||||
}
|
||||
|
||||
enableProgress (text) {
|
||||
assert(!this.bar);
|
||||
this.bar = new Progress(` ${text} [:bar] :percent`, {
|
||||
this.bar = new Progress(` ${text} [:bar] :percent`, {
|
||||
stream: process.stdout,
|
||||
width: 20,
|
||||
complete: '=',
|
||||
incomplete: ' ',
|
||||
@ -32,10 +53,25 @@ class Log {
|
||||
|
||||
disableProgress () {
|
||||
assert(this.bar);
|
||||
this.bar.update(1);
|
||||
this.bar.terminate();
|
||||
// it is auto-completed once it updates to 100
|
||||
// otherwise it outputs a blank line
|
||||
if (!this.bar.complete) {
|
||||
this.bar.update(1);
|
||||
}
|
||||
delete this.bar;
|
||||
}
|
||||
}
|
||||
|
||||
export const log = new Log();
|
||||
|
||||
export function wasReported (error, lines) {
|
||||
if (error === undefined) {
|
||||
error = new Error('No message');
|
||||
} else
|
||||
if (typeof error === 'string') {
|
||||
log.error(error, lines);
|
||||
error = new Error(error);
|
||||
}
|
||||
error.wasReported = true;
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -1,16 +1,29 @@
|
||||
import { major, minor } from 'semver';
|
||||
import expandTemplate from 'expand-template';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
import placesJson from '../places.json';
|
||||
const expand = expandTemplate();
|
||||
|
||||
function tagFromVersion (version) {
|
||||
const mj = major(version);
|
||||
const mn = minor(version);
|
||||
return `v${mj}.${mn}`;
|
||||
}
|
||||
|
||||
export function localPlace (opts) {
|
||||
const p = placesJson.localPlace;
|
||||
const { version } = opts;
|
||||
const tag = tagFromVersion(version);
|
||||
Object.assign(opts, { tag });
|
||||
const atHome = p.replace('~', os.homedir());
|
||||
return expand(path.resolve(atHome), opts);
|
||||
}
|
||||
|
||||
export function remotePlace (opts) {
|
||||
const p = placesJson.remotePlace;
|
||||
return expand(p, opts);
|
||||
const { version } = opts;
|
||||
const tag = tagFromVersion(version);
|
||||
Object.assign(opts, { tag });
|
||||
return { tag, name: expand(p, opts) };
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import byline from 'byline';
|
||||
import chipo from 'child_process';
|
||||
import chip from 'child_process';
|
||||
import fs from 'fs';
|
||||
import { log } from './log.js';
|
||||
|
||||
@ -12,7 +12,7 @@ function errorLines (lines) {
|
||||
}
|
||||
|
||||
export function spawn (cmd, args, opts) {
|
||||
const child = chipo.spawn(cmd, args, opts);
|
||||
const child = chip.spawn(cmd, args, opts);
|
||||
const stdout = byline(child.stdout);
|
||||
const stderr = byline(child.stderr);
|
||||
const lines = [];
|
||||
|
||||
@ -5,15 +5,16 @@ function getHostAbi () {
|
||||
}
|
||||
|
||||
export function abiToNodeRange (abi) {
|
||||
if (/^m?14/.test(abi)) return '0.12';
|
||||
if (/^m?46/.test(abi)) return '4';
|
||||
if (/^m?47/.test(abi)) return '5';
|
||||
if (/^m?48/.test(abi)) return '6';
|
||||
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';
|
||||
return abi;
|
||||
}
|
||||
|
||||
export function toFancyPlatform (platform) {
|
||||
if (platform === 'darwin') return 'macos';
|
||||
if (platform === 'osx') return 'macos';
|
||||
if (platform === 'win32') return 'win';
|
||||
return platform;
|
||||
}
|
||||
|
||||
@ -1,13 +1,21 @@
|
||||
import { hostPlatform, targetArchs } from './system.js';
|
||||
import { localPlace, remotePlace } from './places.js';
|
||||
import { log, wasReported } from './log.js';
|
||||
import build from './build.js';
|
||||
import { log } from './log.js';
|
||||
import patchesJson from '../patches/patches.json';
|
||||
import path from 'path';
|
||||
import { upload } from './cloud.js';
|
||||
import { version } from '../package.json';
|
||||
|
||||
function isBrokenBuild (nodeVersion, targetArch) {
|
||||
function dontBuild (nodeVersion, targetArch) {
|
||||
// https://support.apple.com/en-us/HT201948
|
||||
// don't disable macos-x86 because it breaks
|
||||
// cross-platform tests on x86 hosts
|
||||
// TODO disabe macos-x86 again once we have
|
||||
// cross-arch compilation
|
||||
// if (hostPlatform === 'macos' &&
|
||||
// targetArch === 'x86') return true;
|
||||
// official node 0.12 does not compile on arm
|
||||
if (/^v?0/.test(nodeVersion) &&
|
||||
/^arm/.test(targetArch)) return true;
|
||||
return false;
|
||||
@ -15,23 +23,25 @@ function isBrokenBuild (nodeVersion, targetArch) {
|
||||
|
||||
export async function main () {
|
||||
if (!process.env.GITHUB_USERNAME) {
|
||||
throw new Error('No github credentials. Upload will fail!');
|
||||
throw wasReported('No github credentials. Upload will fail!');
|
||||
}
|
||||
|
||||
for (const nodeVersion in patchesJson) {
|
||||
for (const targetArch of targetArchs) {
|
||||
if (isBrokenBuild(nodeVersion, targetArch)) continue;
|
||||
const local = localPlace({ arch: targetArch, nodeVersion, platform: hostPlatform, version });
|
||||
if (dontBuild(nodeVersion, targetArch)) continue;
|
||||
const local = localPlace({ from: 'built', arch: targetArch,
|
||||
nodeVersion, platform: hostPlatform, version });
|
||||
const short = path.basename(local);
|
||||
log.info(`Building ${short}...`);
|
||||
await build(nodeVersion, targetArch, local);
|
||||
log.info(`Uploading ${short}...`);
|
||||
const remote = remotePlace({ arch: targetArch, nodeVersion, platform: hostPlatform, version });
|
||||
const remote = remotePlace({ arch: targetArch,
|
||||
nodeVersion, platform: hostPlatform, version });
|
||||
try {
|
||||
await upload(local, remote);
|
||||
} catch (error) {
|
||||
// TODO catch only network errors
|
||||
log.error(error);
|
||||
if (!error.wasReported) log.error(error);
|
||||
log.info('Meanwhile i will continue making binaries');
|
||||
}
|
||||
}
|
||||
@ -40,7 +50,7 @@ export async function main () {
|
||||
|
||||
if (!module.parent) {
|
||||
main().catch((error) => {
|
||||
log.error(error);
|
||||
if (!error.wasReported) log.error(error);
|
||||
process.exit(2);
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "pkg-fetch",
|
||||
"version": "0.0.3",
|
||||
"version": "1.5.0-beta.0",
|
||||
"description": "",
|
||||
"readme": "",
|
||||
"main": "lib-es5/index.js",
|
||||
@ -40,10 +40,11 @@
|
||||
"eslint-config-klopov": "0.9.0"
|
||||
},
|
||||
"scripts": {
|
||||
"babel": "babel lib --out-dir lib-es5",
|
||||
"babel": "node test/rimraf-es5.js && babel lib --out-dir lib-es5",
|
||||
"bin": "node lib-es5/bin.js",
|
||||
"upload": "node lib-es5/upload.js",
|
||||
"lint": "eslint-klopov . || true",
|
||||
"prepublish": "eslint-klopov . && npm test && npm run babel",
|
||||
"test": "ava"
|
||||
},
|
||||
"eslintConfig": {
|
||||
|
||||
139
patches/backport.PR4777.for.N0.patch
Normal file
139
patches/backport.PR4777.for.N0.patch
Normal file
@ -0,0 +1,139 @@
|
||||
From d1cacb814f6d42395184beaaba906ba930e711eb Mon Sep 17 00:00:00 2001
|
||||
From: Fedor Indutny <fedor@indutny.com>
|
||||
Date: Wed, 20 Jan 2016 19:34:19 -0500
|
||||
Subject: vm: introduce `cachedData`/`produceCachedData`
|
||||
|
||||
Introduce `cachedData`/`produceCachedData` options for `v8.Script`.
|
||||
Could be used to consume/produce V8's code cache for speeding up
|
||||
compilation of known code.
|
||||
|
||||
PR-URL: https://github.com/nodejs/node/pull/4777
|
||||
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
|
||||
|
||||
diff --git a/src/node_contextify.cc b/src/node_contextify.cc
|
||||
index 2e8fd2c..1b3d618 100644
|
||||
--- a/src/node_contextify.cc
|
||||
+++ b/src/node_contextify.cc
|
||||
@@ -18,10 +18,11 @@
|
||||
// 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.
|
||||
|
||||
#include "node.h"
|
||||
+#include "node_buffer.h"
|
||||
#include "node_internals.h"
|
||||
#include "node_watchdog.h"
|
||||
#include "base-object.h"
|
||||
#include "base-object-inl.h"
|
||||
#include "env.h"
|
||||
@@ -484,28 +485,60 @@ class ContextifyScript : public BaseObject {
|
||||
|
||||
TryCatch try_catch;
|
||||
Local<String> code = args[0]->ToString();
|
||||
Local<String> filename = GetFilenameArg(args, 1);
|
||||
bool display_errors = GetDisplayErrorsArg(args, 1);
|
||||
+ Local<Value> cached_data_buf = GetCachedData(args, 1);
|
||||
+ bool produce_cached_data = GetProduceCachedData(args, 1);
|
||||
if (try_catch.HasCaught()) {
|
||||
try_catch.ReThrow();
|
||||
return;
|
||||
}
|
||||
|
||||
+ ScriptCompiler::CachedData* cached_data = NULL;
|
||||
+ if (!cached_data_buf.IsEmpty()) {
|
||||
+ cached_data = new ScriptCompiler::CachedData(
|
||||
+ reinterpret_cast<uint8_t*>(Buffer::Data(cached_data_buf)),
|
||||
+ Buffer::Length(cached_data_buf));
|
||||
+ }
|
||||
+
|
||||
ScriptOrigin origin(filename);
|
||||
- ScriptCompiler::Source source(code, origin);
|
||||
- Local<UnboundScript> v8_script =
|
||||
- ScriptCompiler::CompileUnbound(env->isolate(), &source);
|
||||
+ ScriptCompiler::Source source(code, origin, cached_data);
|
||||
+ ScriptCompiler::CompileOptions compile_options =
|
||||
+ ScriptCompiler::kNoCompileOptions;
|
||||
+
|
||||
+ if (source.GetCachedData() != NULL)
|
||||
+ compile_options = ScriptCompiler::kConsumeCodeCache;
|
||||
+ else if (produce_cached_data)
|
||||
+ compile_options = ScriptCompiler::kProduceCodeCache;
|
||||
+
|
||||
+ Local<UnboundScript> v8_script = ScriptCompiler::CompileUnbound(
|
||||
+ env->isolate(),
|
||||
+ &source,
|
||||
+ compile_options);
|
||||
|
||||
if (v8_script.IsEmpty()) {
|
||||
if (display_errors) {
|
||||
AppendExceptionLine(env, try_catch.Exception(), try_catch.Message());
|
||||
}
|
||||
try_catch.ReThrow();
|
||||
return;
|
||||
}
|
||||
contextify_script->script_.Reset(env->isolate(), v8_script);
|
||||
+
|
||||
+ if (compile_options == ScriptCompiler::kConsumeCodeCache) {
|
||||
+ // no 'rejected' field in cachedData
|
||||
+ } else if (compile_options == ScriptCompiler::kProduceCodeCache) {
|
||||
+ const ScriptCompiler::CachedData* cached_data = source.GetCachedData();
|
||||
+ Local<Object> buf = Buffer::New(
|
||||
+ env,
|
||||
+ reinterpret_cast<const char*>(cached_data->data),
|
||||
+ cached_data->length);
|
||||
+ Local<String> cached_data_string = FIXED_ONE_BYTE_STRING(
|
||||
+ args.GetIsolate(), "cachedData");
|
||||
+ args.This()->Set(cached_data_string, buf);
|
||||
+ }
|
||||
}
|
||||
|
||||
|
||||
static bool InstanceOf(Environment* env, const Local<Value>& value) {
|
||||
return !value.IsEmpty() &&
|
||||
@@ -656,10 +689,46 @@ class ContextifyScript : public BaseObject {
|
||||
|
||||
return value->IsUndefined() ? defaultFilename : value->ToString();
|
||||
}
|
||||
|
||||
|
||||
+ static Local<Value> GetCachedData(
|
||||
+ const FunctionCallbackInfo<Value>& args,
|
||||
+ const int i) {
|
||||
+ if (!args[i]->IsObject()) {
|
||||
+ return Local<Value>();
|
||||
+ }
|
||||
+ Local<String> key = FIXED_ONE_BYTE_STRING(args.GetIsolate(), "cachedData");
|
||||
+ Local<Value> value = args[i].As<Object>()->Get(key);
|
||||
+ if (value->IsUndefined()) {
|
||||
+ return Local<Value>();
|
||||
+ }
|
||||
+
|
||||
+ if (!Buffer::HasInstance(value)) {
|
||||
+ Environment::ThrowTypeError(
|
||||
+ args.GetIsolate(),
|
||||
+ "options.cachedData must be a Buffer instance");
|
||||
+ return Local<Value>();
|
||||
+ }
|
||||
+
|
||||
+ return value;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ static bool GetProduceCachedData(
|
||||
+ const FunctionCallbackInfo<Value>& args,
|
||||
+ const int i) {
|
||||
+ if (!args[i]->IsObject()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ Local<String> key = FIXED_ONE_BYTE_STRING(args.GetIsolate(), "produceCachedData");
|
||||
+ Local<Value> value = args[i].As<Object>()->Get(key);
|
||||
+
|
||||
+ return value->IsTrue();
|
||||
+ }
|
||||
+
|
||||
+
|
||||
static bool EvalMachine(Environment* env,
|
||||
const int64_t timeout,
|
||||
const bool display_errors,
|
||||
const FunctionCallbackInfo<Value>& args,
|
||||
TryCatch& try_catch) {
|
||||
178
patches/backport.PR4777.for.N4.patch
Normal file
178
patches/backport.PR4777.for.N4.patch
Normal file
@ -0,0 +1,178 @@
|
||||
From d1cacb814f6d42395184beaaba906ba930e711eb Mon Sep 17 00:00:00 2001
|
||||
From: Fedor Indutny <fedor@indutny.com>
|
||||
Date: Wed, 20 Jan 2016 19:34:19 -0500
|
||||
Subject: vm: introduce `cachedData`/`produceCachedData`
|
||||
|
||||
Introduce `cachedData`/`produceCachedData` options for `v8.Script`.
|
||||
Could be used to consume/produce V8's code cache for speeding up
|
||||
compilation of known code.
|
||||
|
||||
PR-URL: https://github.com/nodejs/node/pull/4777
|
||||
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
|
||||
|
||||
diff --git a/src/env.h b/src/env.h
|
||||
index 7b6ffc8..5c99f80 100644
|
||||
--- a/src/env.h
|
||||
+++ b/src/env.h
|
||||
@@ -53,10 +53,12 @@ namespace node {
|
||||
V(blocks_string, "blocks") \
|
||||
V(buffer_string, "buffer") \
|
||||
V(bytes_string, "bytes") \
|
||||
V(bytes_parsed_string, "bytesParsed") \
|
||||
V(bytes_read_string, "bytesRead") \
|
||||
+ V(cached_data_string, "cachedData") \
|
||||
+ V(cached_data_rejected_string, "cachedDataRejected") \
|
||||
V(callback_string, "callback") \
|
||||
V(change_string, "change") \
|
||||
V(oncertcb_string, "oncertcb") \
|
||||
V(onclose_string, "_onclose") \
|
||||
V(code_string, "code") \
|
||||
@@ -165,10 +167,11 @@ namespace node {
|
||||
V(pipe_string, "pipe") \
|
||||
V(port_string, "port") \
|
||||
V(preference_string, "preference") \
|
||||
V(priority_string, "priority") \
|
||||
V(processed_string, "processed") \
|
||||
+ V(produce_cached_data_string, "produceCachedData") \
|
||||
V(prototype_string, "prototype") \
|
||||
V(raw_string, "raw") \
|
||||
V(rdev_string, "rdev") \
|
||||
V(readable_string, "readable") \
|
||||
V(received_shutdown_string, "receivedShutdown") \
|
||||
diff --git a/src/node_contextify.cc b/src/node_contextify.cc
|
||||
index 7404bbb..ecf9444 100644
|
||||
--- a/src/node_contextify.cc
|
||||
+++ b/src/node_contextify.cc
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "node.h"
|
||||
+#include "node_buffer.h"
|
||||
#include "node_internals.h"
|
||||
#include "node_watchdog.h"
|
||||
#include "base-object.h"
|
||||
#include "base-object-inl.h"
|
||||
#include "env.h"
|
||||
@@ -11,10 +12,11 @@
|
||||
|
||||
namespace node {
|
||||
|
||||
using v8::AccessType;
|
||||
using v8::Array;
|
||||
+using v8::ArrayBuffer;
|
||||
using v8::Boolean;
|
||||
using v8::Context;
|
||||
using v8::Debug;
|
||||
using v8::EscapableHandleScope;
|
||||
using v8::External;
|
||||
@@ -474,28 +476,61 @@ class ContextifyScript : public BaseObject {
|
||||
Local<String> code = args[0]->ToString(env->isolate());
|
||||
Local<String> filename = GetFilenameArg(args, 1);
|
||||
Local<Integer> lineOffset = GetLineOffsetArg(args, 1);
|
||||
Local<Integer> columnOffset = GetColumnOffsetArg(args, 1);
|
||||
bool display_errors = GetDisplayErrorsArg(args, 1);
|
||||
+ MaybeLocal<Value> cached_data_buf = GetCachedData(env, args, 1);
|
||||
+ bool produce_cached_data = GetProduceCachedData(env, args, 1);
|
||||
if (try_catch.HasCaught()) {
|
||||
try_catch.ReThrow();
|
||||
return;
|
||||
}
|
||||
|
||||
+ ScriptCompiler::CachedData* cached_data = nullptr;
|
||||
+ if (!cached_data_buf.IsEmpty()) {
|
||||
+ auto cached_data_local = cached_data_buf.ToLocalChecked();
|
||||
+ cached_data = new ScriptCompiler::CachedData(
|
||||
+ reinterpret_cast<uint8_t*>(Buffer::Data(cached_data_local)),
|
||||
+ Buffer::Length(cached_data_local));
|
||||
+ }
|
||||
+
|
||||
ScriptOrigin origin(filename, lineOffset, columnOffset);
|
||||
- ScriptCompiler::Source source(code, origin);
|
||||
- Local<UnboundScript> v8_script =
|
||||
- ScriptCompiler::CompileUnbound(env->isolate(), &source);
|
||||
+ ScriptCompiler::Source source(code, origin, cached_data);
|
||||
+ ScriptCompiler::CompileOptions compile_options =
|
||||
+ ScriptCompiler::kNoCompileOptions;
|
||||
+
|
||||
+ if (source.GetCachedData() != nullptr)
|
||||
+ compile_options = ScriptCompiler::kConsumeCodeCache;
|
||||
+ else if (produce_cached_data)
|
||||
+ compile_options = ScriptCompiler::kProduceCodeCache;
|
||||
+
|
||||
+ Local<UnboundScript> v8_script = ScriptCompiler::CompileUnbound(
|
||||
+ env->isolate(),
|
||||
+ &source,
|
||||
+ compile_options);
|
||||
|
||||
if (v8_script.IsEmpty()) {
|
||||
if (display_errors) {
|
||||
AppendExceptionLine(env, try_catch.Exception(), try_catch.Message());
|
||||
}
|
||||
try_catch.ReThrow();
|
||||
return;
|
||||
}
|
||||
contextify_script->script_.Reset(env->isolate(), v8_script);
|
||||
+
|
||||
+ if (compile_options == ScriptCompiler::kConsumeCodeCache) {
|
||||
+ args.This()->Set(
|
||||
+ env->cached_data_rejected_string(),
|
||||
+ Boolean::New(env->isolate(), source.GetCachedData()->rejected));
|
||||
+ } else if (compile_options == ScriptCompiler::kProduceCodeCache) {
|
||||
+ const ScriptCompiler::CachedData* cached_data = source.GetCachedData();
|
||||
+ MaybeLocal<Object> buf = Buffer::Copy(
|
||||
+ env,
|
||||
+ reinterpret_cast<const char*>(cached_data->data),
|
||||
+ cached_data->length);
|
||||
+ args.This()->Set(env->cached_data_string(), buf.ToLocalChecked());
|
||||
+ }
|
||||
}
|
||||
|
||||
|
||||
static bool InstanceOf(Environment* env, const Local<Value>& value) {
|
||||
return !value.IsEmpty() &&
|
||||
@@ -644,10 +679,47 @@ class ContextifyScript : public BaseObject {
|
||||
return defaultFilename;
|
||||
return value->ToString(args.GetIsolate());
|
||||
}
|
||||
|
||||
|
||||
+ static MaybeLocal<Value> GetCachedData(
|
||||
+ Environment* env,
|
||||
+ const FunctionCallbackInfo<Value>& args,
|
||||
+ const int i) {
|
||||
+ if (!args[i]->IsObject()) {
|
||||
+ return MaybeLocal<Value>();
|
||||
+ }
|
||||
+ Local<Value> value = args[i].As<Object>()->Get(env->cached_data_string());
|
||||
+ if (value->IsUndefined()) {
|
||||
+ return MaybeLocal<Value>();
|
||||
+ }
|
||||
+
|
||||
+ if (!Buffer::HasInstance(value)) {
|
||||
+ Environment::ThrowTypeError(
|
||||
+ args.GetIsolate(),
|
||||
+ "options.cachedData must be a Buffer instance");
|
||||
+ return MaybeLocal<Value>();
|
||||
+ }
|
||||
+
|
||||
+ return value;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ static bool GetProduceCachedData(
|
||||
+ Environment* env,
|
||||
+ const FunctionCallbackInfo<Value>& args,
|
||||
+ const int i) {
|
||||
+ if (!args[i]->IsObject()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ Local<Value> value =
|
||||
+ args[i].As<Object>()->Get(env->produce_cached_data_string());
|
||||
+
|
||||
+ return value->IsTrue();
|
||||
+ }
|
||||
+
|
||||
+
|
||||
static Local<Integer> GetLineOffsetArg(
|
||||
const FunctionCallbackInfo<Value>& args,
|
||||
const int i) {
|
||||
Local<Integer> defaultLineOffset = Integer::New(args.GetIsolate(), 0);
|
||||
|
||||
39
patches/backport.PR5159.for.N4.patch
Normal file
39
patches/backport.PR5159.for.N4.patch
Normal file
@ -0,0 +1,39 @@
|
||||
From 16b0a8c1acb97a84e9a6e1868d600c525f27b0ec Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= <mic.besace@gmail.com>
|
||||
Date: Mon, 8 Feb 2016 22:36:40 +0100
|
||||
Subject: src: replace usage of deprecated CompileUnbound
|
||||
|
||||
PR-URL: https://github.com/nodejs/node/pull/5159
|
||||
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
|
||||
|
||||
diff --git a/src/node_contextify.cc b/src/node_contextify.cc
|
||||
index ecf9444..8769b53 100644
|
||||
--- a/src/node_contextify.cc
|
||||
+++ b/src/node_contextify.cc
|
||||
@@ -501,11 +501,11 @@ class ContextifyScript : public BaseObject {
|
||||
if (source.GetCachedData() != nullptr)
|
||||
compile_options = ScriptCompiler::kConsumeCodeCache;
|
||||
else if (produce_cached_data)
|
||||
compile_options = ScriptCompiler::kProduceCodeCache;
|
||||
|
||||
- Local<UnboundScript> v8_script = ScriptCompiler::CompileUnbound(
|
||||
+ MaybeLocal<UnboundScript> v8_script = ScriptCompiler::CompileUnboundScript(
|
||||
env->isolate(),
|
||||
&source,
|
||||
compile_options);
|
||||
|
||||
if (v8_script.IsEmpty()) {
|
||||
@@ -513,11 +513,12 @@ class ContextifyScript : public BaseObject {
|
||||
AppendExceptionLine(env, try_catch.Exception(), try_catch.Message());
|
||||
}
|
||||
try_catch.ReThrow();
|
||||
return;
|
||||
}
|
||||
- contextify_script->script_.Reset(env->isolate(), v8_script);
|
||||
+ contextify_script->script_.Reset(env->isolate(),
|
||||
+ v8_script.ToLocalChecked());
|
||||
|
||||
if (compile_options == ScriptCompiler::kConsumeCodeCache) {
|
||||
args.This()->Set(
|
||||
env->cached_data_rejected_string(),
|
||||
Boolean::New(env->isolate(), source.GetCachedData()->rejected));
|
||||
51
patches/backport.PR5343.for.N0.patch
Normal file
51
patches/backport.PR5343.for.N0.patch
Normal file
@ -0,0 +1,51 @@
|
||||
From 6c8378b15bd9ca378df6e14d5b0d7032caefd774 Mon Sep 17 00:00:00 2001
|
||||
From: Jiho Choi <jray319@gmail.com>
|
||||
Date: Sat, 20 Feb 2016 20:44:06 -0600
|
||||
Subject: vm: fix `produceCachedData`
|
||||
|
||||
Fix segmentation faults when compiling the same code with
|
||||
`produceCachedData` option. V8 ignores the option when the code is in
|
||||
its compilation cache and does not return cached data. Added
|
||||
`cachedDataProduced` property to `v8.Script` to denote whether the
|
||||
cached data is produced successfully.
|
||||
|
||||
PR-URL: https://github.com/nodejs/node/pull/5343
|
||||
Reviewed-By: Fedor Indutny <fedor@indutny.com>
|
||||
|
||||
diff --git a/src/node_contextify.cc b/src/node_contextify.cc
|
||||
index 1b3d618..dfc51e9 100644
|
||||
--- a/src/node_contextify.cc
|
||||
+++ b/src/node_contextify.cc
|
||||
@@ -527,17 +527,25 @@ class ContextifyScript : public BaseObject {
|
||||
|
||||
if (compile_options == ScriptCompiler::kConsumeCodeCache) {
|
||||
// no 'rejected' field in cachedData
|
||||
} else if (compile_options == ScriptCompiler::kProduceCodeCache) {
|
||||
const ScriptCompiler::CachedData* cached_data = source.GetCachedData();
|
||||
- Local<Object> buf = Buffer::New(
|
||||
- env,
|
||||
- reinterpret_cast<const char*>(cached_data->data),
|
||||
- cached_data->length);
|
||||
- Local<String> cached_data_string = FIXED_ONE_BYTE_STRING(
|
||||
- args.GetIsolate(), "cachedData");
|
||||
- args.This()->Set(cached_data_string, buf);
|
||||
+ bool cached_data_produced = cached_data != NULL;
|
||||
+ if (cached_data_produced) {
|
||||
+ Local<Object> buf = Buffer::New(
|
||||
+ env,
|
||||
+ reinterpret_cast<const char*>(cached_data->data),
|
||||
+ cached_data->length);
|
||||
+ Local<String> cached_data_string = FIXED_ONE_BYTE_STRING(
|
||||
+ args.GetIsolate(), "cachedData");
|
||||
+ args.This()->Set(cached_data_string, buf);
|
||||
+ }
|
||||
+ Local<String> cached_data_produced_string = FIXED_ONE_BYTE_STRING(
|
||||
+ args.GetIsolate(), "cachedDataProduced");
|
||||
+ args.This()->Set(
|
||||
+ cached_data_produced_string,
|
||||
+ Boolean::New(env->isolate(), cached_data_produced));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static bool InstanceOf(Environment* env, const Local<Value>& value) {
|
||||
61
patches/backport.PR5343.for.N4.patch
Normal file
61
patches/backport.PR5343.for.N4.patch
Normal file
@ -0,0 +1,61 @@
|
||||
From 6c8378b15bd9ca378df6e14d5b0d7032caefd774 Mon Sep 17 00:00:00 2001
|
||||
From: Jiho Choi <jray319@gmail.com>
|
||||
Date: Sat, 20 Feb 2016 20:44:06 -0600
|
||||
Subject: vm: fix `produceCachedData`
|
||||
|
||||
Fix segmentation faults when compiling the same code with
|
||||
`produceCachedData` option. V8 ignores the option when the code is in
|
||||
its compilation cache and does not return cached data. Added
|
||||
`cachedDataProduced` property to `v8.Script` to denote whether the
|
||||
cached data is produced successfully.
|
||||
|
||||
PR-URL: https://github.com/nodejs/node/pull/5343
|
||||
Reviewed-By: Fedor Indutny <fedor@indutny.com>
|
||||
|
||||
diff --git a/src/env.h b/src/env.h
|
||||
index 5c99f80..c0b6dcd 100644
|
||||
--- a/src/env.h
|
||||
+++ b/src/env.h
|
||||
@@ -54,10 +54,11 @@ namespace node {
|
||||
V(buffer_string, "buffer") \
|
||||
V(bytes_string, "bytes") \
|
||||
V(bytes_parsed_string, "bytesParsed") \
|
||||
V(bytes_read_string, "bytesRead") \
|
||||
V(cached_data_string, "cachedData") \
|
||||
+ V(cached_data_produced_string, "cachedDataProduced") \
|
||||
V(cached_data_rejected_string, "cachedDataRejected") \
|
||||
V(callback_string, "callback") \
|
||||
V(change_string, "change") \
|
||||
V(oncertcb_string, "oncertcb") \
|
||||
V(onclose_string, "_onclose") \
|
||||
diff --git a/src/node_contextify.cc b/src/node_contextify.cc
|
||||
index 8769b53..4f63c20 100644
|
||||
--- a/src/node_contextify.cc
|
||||
+++ b/src/node_contextify.cc
|
||||
@@ -522,15 +522,21 @@ class ContextifyScript : public BaseObject {
|
||||
args.This()->Set(
|
||||
env->cached_data_rejected_string(),
|
||||
Boolean::New(env->isolate(), source.GetCachedData()->rejected));
|
||||
} else if (compile_options == ScriptCompiler::kProduceCodeCache) {
|
||||
const ScriptCompiler::CachedData* cached_data = source.GetCachedData();
|
||||
- MaybeLocal<Object> buf = Buffer::Copy(
|
||||
- env,
|
||||
- reinterpret_cast<const char*>(cached_data->data),
|
||||
- cached_data->length);
|
||||
- args.This()->Set(env->cached_data_string(), buf.ToLocalChecked());
|
||||
+ bool cached_data_produced = cached_data != nullptr;
|
||||
+ if (cached_data_produced) {
|
||||
+ MaybeLocal<Object> buf = Buffer::Copy(
|
||||
+ env,
|
||||
+ reinterpret_cast<const char*>(cached_data->data),
|
||||
+ cached_data->length);
|
||||
+ args.This()->Set(env->cached_data_string(), buf.ToLocalChecked());
|
||||
+ }
|
||||
+ args.This()->Set(
|
||||
+ env->cached_data_produced_string(),
|
||||
+ Boolean::New(env->isolate(), cached_data_produced));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static bool InstanceOf(Environment* env, const Local<Value>& value) {
|
||||
@ -2,7 +2,7 @@ commit b324d0bb99045fcfe80397a978eb2ce29af4990f
|
||||
Author: igorklopov <igor@klopov.com>
|
||||
Date: Mon Aug 17 11:31:50 2015 +0400
|
||||
|
||||
U2
|
||||
some older revisions mixed together
|
||||
|
||||
diff --git a/src/code-stubs.cc b/src/code-stubs.cc
|
||||
index 0e68ab8..92aca16 100644
|
||||
|
||||
64
patches/ignition.patch
Normal file
64
patches/ignition.patch
Normal file
@ -0,0 +1,64 @@
|
||||
From 9f165610d692d5785ab4596d7769421ae18ad4a3 Mon Sep 17 00:00:00 2001
|
||||
From: Igor Klopov <igor@klopov.com>
|
||||
Date: Sun, 25 Sep 2016 18:46:33 +0300
|
||||
Subject: use ignition+turbofan for sourceless code
|
||||
|
||||
|
||||
diff --git a/deps/v8/src/compiler.cc b/deps/v8/src/compiler.cc
|
||||
index 9a5afe9..bf612c6 100644
|
||||
--- a/deps/v8/src/compiler.cc
|
||||
+++ b/deps/v8/src/compiler.cc
|
||||
@@ -439,11 +439,15 @@ void EnsureFeedbackMetadata(CompilationInfo* info) {
|
||||
CHECK(!info->shared_info()->feedback_metadata()->SpecDiffersFrom(
|
||||
info->literal()->feedback_vector_spec()));
|
||||
}
|
||||
|
||||
bool ShouldUseIgnition(CompilationInfo* info) {
|
||||
- if (!FLAG_ignition) return false;
|
||||
+ ParseInfo* parse_info = info->parse_info();
|
||||
+ Isolate* isolate = parse_info->isolate();
|
||||
+ bool flag = FLAG_ignition || !FLAG_lazy ||
|
||||
+ parse_info->script()->source()->IsUndefined(isolate);
|
||||
+ if (!flag) return false;
|
||||
|
||||
DCHECK(info->has_shared_info());
|
||||
|
||||
// When requesting debug code as a replacement for existing code, we provide
|
||||
// the same kind as the existing code (to prevent implicit tier-change).
|
||||
@@ -648,12 +652,18 @@ bool UseTurboFan(Handle<SharedFunctionInfo> shared) {
|
||||
!optimization_disabled;
|
||||
|
||||
// 3. Explicitly enabled by the command-line filter.
|
||||
bool passes_turbo_filter = shared->PassesFilter(FLAG_turbo_filter);
|
||||
|
||||
+ // 4. Same option as in ShouldUseIgnition.
|
||||
+ Isolate* isolate = shared->GetIsolate();
|
||||
+ Script* script = Script::cast(shared->script());
|
||||
+ bool sourceless_ignition = !FLAG_lazy ||
|
||||
+ script->source()->IsUndefined(isolate);
|
||||
+
|
||||
return is_turbofanable_asm || is_unsupported_by_crankshaft_but_turbofanable ||
|
||||
- passes_turbo_filter;
|
||||
+ passes_turbo_filter || sourceless_ignition;
|
||||
}
|
||||
|
||||
bool GetOptimizedCodeNow(CompilationJob* job) {
|
||||
CompilationInfo* info = job->info();
|
||||
Isolate* isolate = info->isolate();
|
||||
diff --git a/deps/v8/src/flag-definitions.h b/deps/v8/src/flag-definitions.h
|
||||
index e5ddbad..a3fb95c 100644
|
||||
--- a/deps/v8/src/flag-definitions.h
|
||||
+++ b/deps/v8/src/flag-definitions.h
|
||||
@@ -425,11 +425,11 @@ DEFINE_BOOL(omit_map_checks_for_leaf_maps, true,
|
||||
|
||||
// Flags for TurboFan.
|
||||
DEFINE_BOOL(turbo, false, "enable TurboFan compiler")
|
||||
DEFINE_IMPLICATION(turbo, turbo_asm_deoptimization)
|
||||
DEFINE_IMPLICATION(turbo, turbo_loop_peeling)
|
||||
-DEFINE_BOOL(turbo_from_bytecode, false, "enable building graphs from bytecode")
|
||||
+DEFINE_BOOL(turbo_from_bytecode, true, "enable building graphs from bytecode")
|
||||
DEFINE_BOOL(turbo_sp_frame_access, false,
|
||||
"use stack pointer-relative access to frame wherever possible")
|
||||
DEFINE_BOOL(turbo_preprocess_ranges, true,
|
||||
"run pre-register allocation heuristics")
|
||||
DEFINE_BOOL(turbo_loop_stackcheck, true, "enable stack checks in loops")
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
695
patches/node.v4.5.0.patch
Normal file
695
patches/node.v4.5.0.patch
Normal file
@ -0,0 +1,695 @@
|
||||
--- node/deps/v8/include/v8.h
|
||||
+++ node/deps/v8/include/v8.h
|
||||
@@ -6065,10 +6065,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_DEPRECATE_SOON(
|
||||
--- node/deps/v8/src/api.cc
|
||||
+++ node/deps/v8/src/api.cc
|
||||
@@ -428,10 +428,44 @@
|
||||
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::Probe(true);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+void V8::DisableCompilationForSourcelessUse() {
|
||||
+ i::FLAG_lazy = save_lazy;
|
||||
+ i::FLAG_predictable = save_predictable;
|
||||
+ i::FLAG_serialize_toplevel = save_serialize_toplevel;
|
||||
+ 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/parser.cc
|
||||
+++ node/deps/v8/src/parser.cc
|
||||
@@ -5640,10 +5640,11 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Parser::Parse(ParseInfo* info) {
|
||||
+ if (info->script()->source()->IsUndefined()) return false;
|
||||
DCHECK(info->function() == NULL);
|
||||
FunctionLiteral* result = NULL;
|
||||
// Ok to use Isolate here; this function is only called in the main thread.
|
||||
DCHECK(parsing_on_main_thread_);
|
||||
Isolate* isolate = info->isolate();
|
||||
--- node/deps/v8/src/snapshot/serialize.cc
|
||||
+++ node/deps/v8/src/snapshot/serialize.cc
|
||||
@@ -2695,24 +2695,36 @@
|
||||
|
||||
|
||||
SerializedCodeData::SanityCheckResult SerializedCodeData::SanityCheck(
|
||||
Isolate* isolate, String* source) const {
|
||||
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");
|
||||
+ 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 c1 = GetHeaderValue(kChecksum1Offset);
|
||||
uint32_t c2 = GetHeaderValue(kChecksum2Offset);
|
||||
- if (version_hash != Version::Hash()) return VERSION_MISMATCH;
|
||||
- if (source_hash != SourceHash(source)) 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 (!Checksum(Payload()).Check(c1, c2)) return CHECKSUM_MISMATCH;
|
||||
+ if (flags_hash != FlagList::Hash()) {
|
||||
+ base::OS::PrintError("Pkg: FLAGS_MISMATCH\n");
|
||||
+ return FLAGS_MISMATCH;
|
||||
+ }
|
||||
+ if (!Checksum(Payload()).Check(c1, c2)) {
|
||||
+ base::OS::PrintError("Pkg: CHECKSUM_MISMATCH\n");
|
||||
+ return CHECKSUM_MISMATCH;
|
||||
+ }
|
||||
return CHECK_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
// Return ScriptData object and relinquish ownership over it to the caller.
|
||||
--- node/lib/child_process.js
|
||||
+++ node/lib/child_process.js
|
||||
@@ -49,11 +49,11 @@
|
||||
options.stdio = options.silent ? ['pipe', 'pipe', 'pipe', 'ipc'] :
|
||||
[0, 1, 2, 'ipc'];
|
||||
|
||||
options.execPath = options.execPath || process.execPath;
|
||||
|
||||
- return spawn(options.execPath, args, options);
|
||||
+ return exports.spawn(options.execPath, args, options);
|
||||
};
|
||||
|
||||
|
||||
exports._forkChild = function(fd) {
|
||||
// set process.send()
|
||||
--- node/lib/module.js
|
||||
+++ node/lib/module.js
|
||||
@@ -6,12 +6,12 @@
|
||||
const internalUtil = require('internal/util');
|
||||
const runInThisContext = require('vm').runInThisContext;
|
||||
const assert = require('assert').ok;
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
-const internalModuleReadFile = process.binding('fs').internalModuleReadFile;
|
||||
-const internalModuleStat = process.binding('fs').internalModuleStat;
|
||||
+const internalModuleReadFile = require('fs').internalModuleReadFile;
|
||||
+const internalModuleStat = require('fs').internalModuleStat;
|
||||
|
||||
const splitRe = process.platform === 'win32' ? /[\/\\]/ : /\//;
|
||||
const isIndexRe = /^index\.\w+?$/;
|
||||
const shebangRe = /^\#\!.*/;
|
||||
|
||||
--- node/node.gyp
|
||||
+++ node/node.gyp
|
||||
@@ -387,11 +387,10 @@
|
||||
'dependencies': [ 'deps/uv/uv.gyp:libuv' ],
|
||||
}],
|
||||
|
||||
[ 'OS=="win"', {
|
||||
'sources': [
|
||||
- 'src/res/node.rc',
|
||||
],
|
||||
'defines!': [
|
||||
'NODE_PLATFORM="win"',
|
||||
],
|
||||
'defines': [
|
||||
--- node/src/env.h
|
||||
+++ node/src/env.h
|
||||
@@ -192,10 +192,11 @@
|
||||
V(session_id_string, "sessionId") \
|
||||
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(subject_string, "subject") \
|
||||
--- node/src/node.cc
|
||||
+++ node/src/node.cc
|
||||
@@ -3235,10 +3235,11 @@
|
||||
|
||||
|
||||
static void PrintHelp();
|
||||
|
||||
static bool ParseDebugOpt(const char* arg) {
|
||||
+ return false;
|
||||
const char* port = nullptr;
|
||||
|
||||
if (!strcmp(arg, "--debug")) {
|
||||
use_debug_agent = true;
|
||||
} else if (!strncmp(arg, "--debug=", sizeof("--debug=") - 1)) {
|
||||
@@ -3815,15 +3816,10 @@
|
||||
}
|
||||
|
||||
|
||||
inline void PlatformInit() {
|
||||
#ifdef __POSIX__
|
||||
- sigset_t sigmask;
|
||||
- sigemptyset(&sigmask);
|
||||
- sigaddset(&sigmask, SIGUSR1);
|
||||
- const int err = pthread_sigmask(SIG_SETMASK, &sigmask, nullptr);
|
||||
-
|
||||
// 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;
|
||||
@@ -3833,12 +3829,10 @@
|
||||
ABORT();
|
||||
if (fd != open("/dev/null", O_RDWR))
|
||||
ABORT();
|
||||
}
|
||||
|
||||
- CHECK_EQ(err, 0);
|
||||
-
|
||||
// Restore signal dispositions, the parent process may have changed them.
|
||||
struct sigaction act;
|
||||
memset(&act, 0, sizeof(act));
|
||||
|
||||
// The hard-coded upper limit is because NSIG is not very reliable; on Linux,
|
||||
@@ -3966,14 +3960,10 @@
|
||||
// is to prevent memory pointers from being moved around that are returned by
|
||||
// Buffer::Data().
|
||||
const char no_typed_array_heap[] = "--typed_array_max_size_in_heap=0";
|
||||
V8::SetFlagsFromString(no_typed_array_heap, sizeof(no_typed_array_heap) - 1);
|
||||
|
||||
- if (!use_debug_agent) {
|
||||
- RegisterDebugSignalHandler();
|
||||
- }
|
||||
-
|
||||
// We should set node_is_initialized here instead of in node::Start,
|
||||
// otherwise embedders using node::Init to initialize everything will not be
|
||||
// able to set it and native modules will not load for them.
|
||||
node_is_initialized = true;
|
||||
}
|
||||
--- node/src/node.js
|
||||
+++ node/src/node.js
|
||||
@@ -51,10 +51,14 @@
|
||||
// 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.
|
||||
|
||||
+ if (NativeModule.exists('_pkg_bootstrap')) {
|
||||
+ NativeModule.require('_pkg_bootstrap');
|
||||
+ }
|
||||
+
|
||||
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/src/node_contextify.cc
|
||||
+++ node/src/node_contextify.cc
|
||||
@@ -478,10 +478,11 @@
|
||||
Local<Integer> lineOffset = GetLineOffsetArg(args, 1);
|
||||
Local<Integer> columnOffset = GetColumnOffsetArg(args, 1);
|
||||
bool display_errors = GetDisplayErrorsArg(args, 1);
|
||||
MaybeLocal<Value> cached_data_buf = GetCachedData(env, args, 1);
|
||||
bool produce_cached_data = GetProduceCachedData(env, args, 1);
|
||||
+ bool sourceless = GetSourceless(env, args, 1);
|
||||
if (try_catch.HasCaught()) {
|
||||
try_catch.ReThrow();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -501,22 +502,37 @@
|
||||
if (source.GetCachedData() != nullptr)
|
||||
compile_options = ScriptCompiler::kConsumeCodeCache;
|
||||
else if (produce_cached_data)
|
||||
compile_options = ScriptCompiler::kProduceCodeCache;
|
||||
|
||||
+ 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) {
|
||||
AppendExceptionLine(env, try_catch.Exception(), try_catch.Message());
|
||||
}
|
||||
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(
|
||||
@@ -723,10 +739,24 @@
|
||||
|
||||
return value->IsTrue();
|
||||
}
|
||||
|
||||
|
||||
+ static bool GetSourceless(
|
||||
+ Environment* env,
|
||||
+ const FunctionCallbackInfo<Value>& args,
|
||||
+ const int i) {
|
||||
+ if (!args[i]->IsObject()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ Local<Value> value =
|
||||
+ args[i].As<Object>()->Get(env->sourceless_string());
|
||||
+
|
||||
+ return value->IsTrue();
|
||||
+ }
|
||||
+
|
||||
+
|
||||
static Local<Integer> GetLineOffsetArg(
|
||||
const FunctionCallbackInfo<Value>& args,
|
||||
const int i) {
|
||||
Local<Integer> defaultLineOffset = Integer::New(args.GetIsolate(), 0);
|
||||
|
||||
--- node/src/node_javascript.cc
|
||||
+++ node/src/node_javascript.cc
|
||||
@@ -29,8 +29,59 @@
|
||||
env->isolate(), reinterpret_cast<const char*>(native.source),
|
||||
NewStringType::kNormal, native.source_len).ToLocalChecked();
|
||||
target->Set(name, source);
|
||||
}
|
||||
}
|
||||
+
|
||||
+ auto name = String::NewFromUtf8(env->isolate(), "_pkg_bootstrap");
|
||||
+ auto source = String::NewFromUtf8(env->isolate(),
|
||||
+ "var fs = require('fs');\n" \
|
||||
+ "var vm = require('vm');\n" \
|
||||
+ "function readPayload (fd) {\n" \
|
||||
+ " var position = process.env.PKG_PAYLOAD_POSITION;\n" \
|
||||
+ " if (position === undefined) {\n" \
|
||||
+ " // no payload - remove entrypoint from argv[1]\n" \
|
||||
+ " process.argv.splice(1, 1);\n" \
|
||||
+ " if (process.argv[1] === '-e' ||\n" \
|
||||
+ " process.argv[1] === '--eval') {\n" \
|
||||
+ " process._eval = process.argv[2];\n" \
|
||||
+ " process.argv.splice(1, 2);\n" \
|
||||
+ " }\n" \
|
||||
+ " return undefined;\n" \
|
||||
+ " }\n" \
|
||||
+ " position = position | 0;\n" \
|
||||
+ " var size = process.env.PKG_PAYLOAD_SIZE | 0;\n" \
|
||||
+ " delete process.env.PKG_PAYLOAD_POSITION;\n" \
|
||||
+ " delete process.env.PKG_PAYLOAD_SIZE;\n" \
|
||||
+ " var cd = new Buffer(size);\n" \
|
||||
+ " var read = fs.readSync(fd, cd, 0, size, position);\n" \
|
||||
+ " if (read !== size) {\n" \
|
||||
+ " console.error('Pkg: Error reading from file.');\n" \
|
||||
+ " process.exit(1);\n" \
|
||||
+ " }\n" \
|
||||
+ " var s = new vm.Script(undefined, {\n" \
|
||||
+ " cachedData: cd,\n" \
|
||||
+ " sourceless: true\n" \
|
||||
+ " });\n" \
|
||||
+ " if (s.cachedDataRejected) {\n" \
|
||||
+ " console.error('Pkg: Cached data was rejected.');\n" \
|
||||
+ " process.exit(1);\n" \
|
||||
+ " }\n" \
|
||||
+ " var fn = s.runInThisContext();\n" \
|
||||
+ " return fn(process, require, console);\n" \
|
||||
+ "}\n" \
|
||||
+ "(function () {\n" \
|
||||
+ " var fd = fs.openSync(process.execPath, 'r');\n" \
|
||||
+ " var r = readPayload(fd);\n" \
|
||||
+ " fs.closeSync(fd);\n" \
|
||||
+ " if (!r || r.undoPatch) {\n" \
|
||||
+ " // need to revert patch to node/lib/module.js\n" \
|
||||
+ " var bindingFs = process.binding('fs');\n" \
|
||||
+ " fs.internalModuleStat = bindingFs.internalModuleStat;\n" \
|
||||
+ " fs.internalModuleReadFile = bindingFs.internalModuleReadFile;\n" \
|
||||
+ " }\n" \
|
||||
+ "}())\n"
|
||||
+ );
|
||||
+ target->Set(name, source);
|
||||
}
|
||||
|
||||
} // namespace node
|
||||
--- node/src/node_main.cc
|
||||
+++ node/src/node_main.cc
|
||||
@@ -1,7 +1,277 @@
|
||||
#include "node.h"
|
||||
|
||||
+#include <string.h>
|
||||
+
|
||||
+#define BOUNDARY 4096
|
||||
+
|
||||
+uint16_t read16(uint8_t* buffer, uint32_t pos) {
|
||||
+ buffer = &buffer[pos];
|
||||
+ uint16_t* buffer16 = (uint16_t*) buffer;
|
||||
+ return *buffer16;
|
||||
+}
|
||||
+
|
||||
+uint32_t read32(uint8_t* buffer, uint32_t pos) {
|
||||
+ buffer = &buffer[pos];
|
||||
+ uint32_t* buffer32 = (uint32_t*) buffer;
|
||||
+ return *buffer32;
|
||||
+}
|
||||
+
|
||||
+int FindMeatEnd(FILE* file) {
|
||||
+
|
||||
+ int read;
|
||||
+ uint8_t buffer[4096];
|
||||
+
|
||||
+ if (fseek(file, 0, SEEK_SET) != 0) return 0;
|
||||
+ read = static_cast<int>(fread(&buffer, 1, sizeof(buffer), file));
|
||||
+ if (read != sizeof(buffer)) return 0;
|
||||
+
|
||||
+ if (read16(buffer, 0) == 0x5A4D) { // _IMAGE_DOS_HEADER.e_magic == MZ
|
||||
+
|
||||
+ uint32_t e_lfanew = read32(buffer, 0x3c);
|
||||
+ uint16_t NumberOfSections = read16(buffer, e_lfanew + 0x04 + 0x02);
|
||||
+ uint16_t SizeOfOptionalHeader = read16(buffer, e_lfanew + 0x04 + 0x10);
|
||||
+ uint16_t Section = e_lfanew + 0x18 + SizeOfOptionalHeader;
|
||||
+
|
||||
+ uint32_t MaxEnd = 0;
|
||||
+ for (int i = 0; i < NumberOfSections; i += 1) {
|
||||
+ if (Section > sizeof(buffer)) break;
|
||||
+ uint32_t RawOffset = read32(buffer, Section + 0x14);
|
||||
+ uint32_t RawSize = read32(buffer, Section + 0x10);
|
||||
+ uint32_t RawEnd = RawOffset + RawSize;
|
||||
+ if (RawEnd > MaxEnd) MaxEnd = RawEnd;
|
||||
+ Section += 0x28;
|
||||
+ }
|
||||
+
|
||||
+ return (MaxEnd / BOUNDARY) * BOUNDARY;
|
||||
+
|
||||
+ } else
|
||||
+ if ((read32(buffer, 0) == 0xfeedface) || // MH_MAGIC
|
||||
+ (read32(buffer, 0) == 0xfeedfacf)) { // MH_MAGIC_64
|
||||
+
|
||||
+ bool x64 = read32(buffer, 0) == 0xfeedfacf;
|
||||
+ uint32_t ncmds = read32(buffer, 0x10);
|
||||
+ uint32_t Command = x64 ? 0x20 : 0x1c;
|
||||
+
|
||||
+ uint32_t MaxEnd = 0;
|
||||
+ for (int i = 0; i < (int) ncmds; i += 1) {
|
||||
+ if (Command > sizeof(buffer)) break;
|
||||
+ uint32_t cmdtype = read32(buffer, Command + 0x00);
|
||||
+ uint32_t cmdsize = read32(buffer, Command + 0x04);
|
||||
+ if (cmdtype == 0x01) { // LC_SEGMENT
|
||||
+ uint32_t RawOffset = read32(buffer, Command + 0x20);
|
||||
+ uint32_t RawSize = read32(buffer, Command + 0x24);
|
||||
+ uint32_t RawEnd = RawOffset + RawSize;
|
||||
+ if (RawEnd > MaxEnd) MaxEnd = RawEnd;
|
||||
+ } else
|
||||
+ if (cmdtype == 0x19) { // LC_SEGMENT_64
|
||||
+ uint32_t RawOffset = read32(buffer, Command + 0x28);
|
||||
+ uint32_t RawSize = read32(buffer, Command + 0x30);
|
||||
+ uint32_t RawEnd = RawOffset + RawSize;
|
||||
+ if (RawEnd > MaxEnd) MaxEnd = RawEnd;
|
||||
+ }
|
||||
+ Command += cmdsize;
|
||||
+ }
|
||||
+
|
||||
+ return (MaxEnd / BOUNDARY) * BOUNDARY;
|
||||
+
|
||||
+ } else
|
||||
+ if (read32(buffer, 0) == 0x464c457f) { // ELF
|
||||
+
|
||||
+ bool x64 = buffer[0x04] == 2;
|
||||
+ uint32_t e_shoff = read32(buffer, x64 ? 0x28 : 0x20);
|
||||
+ uint16_t e_shnum = read32(buffer, x64 ? 0x3c : 0x30);
|
||||
+ uint16_t e_shentsize = read32(buffer, x64 ? 0x3a : 0x2e);
|
||||
+ uint32_t SectionHeader = 0;
|
||||
+
|
||||
+ if (fseek(file, e_shoff, SEEK_SET) != 0) return 0;
|
||||
+ read = static_cast<int>(fread(&buffer, 1, sizeof(buffer), file));
|
||||
+ if (read != sizeof(buffer)) return 0;
|
||||
+
|
||||
+ uint32_t MaxEnd = 0;
|
||||
+ for (int i = 0; i < (int) e_shnum; i += 1) {
|
||||
+ uint32_t sh_type = read32(buffer, SectionHeader + 0x04);
|
||||
+ if (sh_type != 0x08) { // SHT_NOBITS
|
||||
+ uint32_t sh_offset = read32(buffer, SectionHeader + (x64 ? 0x18 : 0x10));
|
||||
+ uint32_t sh_size = read32(buffer, SectionHeader + (x64 ? 0x20 : 0x14));
|
||||
+ uint32_t end = sh_offset + sh_size;
|
||||
+ if (end > MaxEnd) MaxEnd = end;
|
||||
+ }
|
||||
+ SectionHeader += e_shentsize;
|
||||
+ }
|
||||
+
|
||||
+ return (MaxEnd / BOUNDARY) * BOUNDARY;
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ fprintf(stderr, "Pkg: Error parsing executable headers.\n");
|
||||
+ exit(1);
|
||||
+
|
||||
+}
|
||||
+
|
||||
+bool GetSentryPosition(FILE* file, int start, uint32_t s1,
|
||||
+ uint32_t s12, uint32_t s3, int* pposition, int* psize
|
||||
+) {
|
||||
+
|
||||
+ int read;
|
||||
+ uint32_t sentry, length;
|
||||
+
|
||||
+ if (fseek(file, start, SEEK_SET) != 0) return false;
|
||||
+
|
||||
+ while (true) {
|
||||
+ read = static_cast<int>(fread(&sentry, 1, sizeof(sentry), file));
|
||||
+ if (read != sizeof(sentry)) return false;
|
||||
+ if (sentry != s1) {
|
||||
+ fseek(file, BOUNDARY - 4, SEEK_CUR);
|
||||
+ continue;
|
||||
+ }
|
||||
+ fread(&length, 1, sizeof(length), file);
|
||||
+ if ((sentry^length) != s12) {
|
||||
+ fseek(file, BOUNDARY - 8, SEEK_CUR);
|
||||
+ continue;
|
||||
+ }
|
||||
+ fread(&sentry, 1, sizeof(sentry), file);
|
||||
+ if (sentry != s3) {
|
||||
+ fseek(file, BOUNDARY - 12, SEEK_CUR);
|
||||
+ continue;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ fread(&length, 1, sizeof(length), file);
|
||||
+ *pposition = ftell(file);
|
||||
+ *psize = static_cast<int>(length);
|
||||
+ return true;
|
||||
+
|
||||
+}
|
||||
+
|
||||
+
|
||||
+#ifdef _WIN32
|
||||
+void setenv(const char* name, const char* value, int overwrite) {
|
||||
+ SetEnvironmentVariable(name, value);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+
|
||||
+char* ReadOverlays(const char* filename) {
|
||||
+
|
||||
+ FILE* file = fopen(filename, "rb");
|
||||
+ if (!file) {
|
||||
+ fprintf(stderr, "Pkg: Error opening file.\n");
|
||||
+ exit(1);
|
||||
+ }
|
||||
+
|
||||
+ char env[64];
|
||||
+ int position = FindMeatEnd(file); int size;
|
||||
+ char* bakery = NULL;
|
||||
+
|
||||
+ if (GetSentryPosition(file, position, 0x4818c4df,
|
||||
+ 0x32dbc2af, 0x56558a76, &position, &size)
|
||||
+ ) {
|
||||
+
|
||||
+ bakery = static_cast<char*>(malloc(size));
|
||||
+ int read;
|
||||
+
|
||||
+ for (int i = 0; i < size;) {
|
||||
+ read = static_cast<int>(fread(&bakery[i], 1, size - i, file));
|
||||
+ if (ferror(file) != 0) {
|
||||
+ fprintf(stderr, "Pkg: Error reading from file.\n");
|
||||
+ fclose(file);
|
||||
+ exit(1);
|
||||
+ }
|
||||
+ i += read;
|
||||
+ }
|
||||
+
|
||||
+ position -= 16; // align back to boundary
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ if (GetSentryPosition(file, position, 0x26e0c928,
|
||||
+ 0x6713e24e, 0x3ea13ccf, &position, &size)
|
||||
+ ) {
|
||||
+
|
||||
+ sprintf(env, "%d", position);
|
||||
+ setenv("PKG_PAYLOAD_POSITION", env, 1);
|
||||
+ sprintf(env, "%d", size);
|
||||
+ setenv("PKG_PAYLOAD_SIZE", env, 1);
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ fclose(file);
|
||||
+ return bakery;
|
||||
+
|
||||
+}
|
||||
+
|
||||
+
|
||||
+
|
||||
+const char* OPTION_RUNTIME = "--runtime";
|
||||
+const char* OPTION_ENTRYPOINT = "--entrypoint";
|
||||
+
|
||||
+
|
||||
+// 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);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+int reorder(int argc, char** argv) {
|
||||
+ int i;
|
||||
+ int runtime_pos = argc;
|
||||
+ for (i = 1; i < argc; i++) {
|
||||
+ if (strcmp(argv[i], OPTION_RUNTIME) == 0) {
|
||||
+ runtime_pos = i;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ int entrypoint_pos = -1;
|
||||
+ for (i = 1 + 1; i < runtime_pos; i++) {
|
||||
+ if (strcmp(argv[i - 1], OPTION_ENTRYPOINT) == 0) {
|
||||
+ entrypoint_pos = i;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ char** nargv = new char*[argc + 64];
|
||||
+ char* bakery = ReadOverlays(argv[0]);
|
||||
+ int c = 0;
|
||||
+ nargv[c++] = argv[0];
|
||||
+ if (bakery) {
|
||||
+ while (true) {
|
||||
+ size_t width = strlen(bakery);
|
||||
+ if (width == 0) break;
|
||||
+ nargv[c++] = bakery;
|
||||
+ bakery += width + 1;
|
||||
+ }
|
||||
+ }
|
||||
+ for (i = runtime_pos + 1; i < argc; i++) {
|
||||
+ nargv[c++] = argv[i];
|
||||
+ }
|
||||
+ if (entrypoint_pos != -1) {
|
||||
+ nargv[c++] = argv[entrypoint_pos];
|
||||
+ } else {
|
||||
+ nargv[c++] = "DEFAULT_ENTRYPOINT";
|
||||
+ }
|
||||
+ for (i = 1; i < runtime_pos; i++) {
|
||||
+ if ((i != entrypoint_pos) &&
|
||||
+ (i != entrypoint_pos - 1)) {
|
||||
+ nargv[c++] = argv[i];
|
||||
+ }
|
||||
+ }
|
||||
+ return adjacent(c, nargv);
|
||||
+}
|
||||
+
|
||||
+
|
||||
#ifdef _WIN32
|
||||
int wmain(int argc, wchar_t *wargv[]) {
|
||||
// Convert argv to to UTF8
|
||||
char** argv = new char*[argc + 1];
|
||||
for (int i = 0; i < argc; i++) {
|
||||
@@ -35,14 +305,14 @@
|
||||
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
|
||||
int main(int argc, char *argv[]) {
|
||||
setvbuf(stderr, NULL, _IOLBF, 1024);
|
||||
- return node::Start(argc, argv);
|
||||
+ return reorder(argc, argv);
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
710
patches/node.v6.6.0.patch
Normal file
710
patches/node.v6.6.0.patch
Normal file
@ -0,0 +1,710 @@
|
||||
--- node/deps/v8/include/v8.h
|
||||
+++ node/deps/v8/include/v8.h
|
||||
@@ -6427,10 +6427,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
|
||||
@@ -541,10 +541,44 @@
|
||||
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::Probe(true);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+void V8::DisableCompilationForSourcelessUse() {
|
||||
+ i::FLAG_lazy = save_lazy;
|
||||
+ i::FLAG_predictable = save_predictable;
|
||||
+ i::FLAG_serialize_toplevel = save_serialize_toplevel;
|
||||
+ 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/parsing/parser.cc
|
||||
+++ node/deps/v8/src/parsing/parser.cc
|
||||
@@ -5054,10 +5054,11 @@
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Parser::Parse(ParseInfo* info) {
|
||||
+ if (info->script()->source()->IsUndefined()) return false;
|
||||
DCHECK(info->literal() == NULL);
|
||||
FunctionLiteral* result = NULL;
|
||||
// Ok to use Isolate here; this function is only called in the main thread.
|
||||
DCHECK(parsing_on_main_thread_);
|
||||
Isolate* isolate = info->isolate();
|
||||
--- node/deps/v8/src/snapshot/code-serializer.cc
|
||||
+++ node/deps/v8/src/snapshot/code-serializer.cc
|
||||
@@ -342,24 +342,36 @@
|
||||
}
|
||||
|
||||
SerializedCodeData::SanityCheckResult SerializedCodeData::SanityCheck(
|
||||
Isolate* isolate, String* source) const {
|
||||
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");
|
||||
+ 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 c1 = GetHeaderValue(kChecksum1Offset);
|
||||
uint32_t c2 = GetHeaderValue(kChecksum2Offset);
|
||||
- if (version_hash != Version::Hash()) return VERSION_MISMATCH;
|
||||
- if (source_hash != SourceHash(source)) 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 (!Checksum(Payload()).Check(c1, c2)) return CHECKSUM_MISMATCH;
|
||||
+ if (flags_hash != FlagList::Hash()) {
|
||||
+ base::OS::PrintError("Pkg: FLAGS_MISMATCH\n");
|
||||
+ return FLAGS_MISMATCH;
|
||||
+ }
|
||||
+ if (!Checksum(Payload()).Check(c1, c2)) {
|
||||
+ base::OS::PrintError("Pkg: CHECKSUM_MISMATCH\n");
|
||||
+ return CHECKSUM_MISMATCH;
|
||||
+ }
|
||||
return CHECK_SUCCESS;
|
||||
}
|
||||
|
||||
uint32_t SerializedCodeData::SourceHash(String* source) const {
|
||||
return source->length();
|
||||
--- node/lib/child_process.js
|
||||
+++ node/lib/child_process.js
|
||||
@@ -53,11 +53,11 @@
|
||||
throw new TypeError('Forked processes must have an IPC channel');
|
||||
}
|
||||
|
||||
options.execPath = options.execPath || process.execPath;
|
||||
|
||||
- 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
|
||||
@@ -72,10 +72,14 @@
|
||||
// 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.
|
||||
|
||||
+ if (NativeModule.exists('_pkg_bootstrap')) {
|
||||
+ NativeModule.require('_pkg_bootstrap');
|
||||
+ }
|
||||
+
|
||||
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
|
||||
@@ -6,12 +6,12 @@
|
||||
const internalUtil = require('internal/util');
|
||||
const vm = require('vm');
|
||||
const assert = require('assert').ok;
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
-const internalModuleReadFile = process.binding('fs').internalModuleReadFile;
|
||||
-const internalModuleStat = process.binding('fs').internalModuleStat;
|
||||
+const internalModuleReadFile = require('fs').internalModuleReadFile;
|
||||
+const internalModuleStat = require('fs').internalModuleStat;
|
||||
const preserveSymlinks = !!process.binding('config').preserveSymlinks;
|
||||
|
||||
// If obj.hasOwnProperty has been overridden, then calling
|
||||
// obj.hasOwnProperty(prop) will break.
|
||||
// See: https://github.com/joyent/node/issues/1707
|
||||
--- node/node.gyp
|
||||
+++ node/node.gyp
|
||||
@@ -491,11 +491,10 @@
|
||||
}],
|
||||
|
||||
[ 'OS=="win"', {
|
||||
'sources': [
|
||||
'src/backtrace_win32.cc',
|
||||
- 'src/res/node.rc',
|
||||
],
|
||||
'defines!': [
|
||||
'NODE_PLATFORM="win"',
|
||||
],
|
||||
'defines': [
|
||||
--- node/src/env.h
|
||||
+++ node/src/env.h
|
||||
@@ -193,10 +193,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(subject_string, "subject") \
|
||||
--- node/src/node.cc
|
||||
+++ node/src/node.cc
|
||||
@@ -3516,10 +3516,11 @@
|
||||
|
||||
|
||||
static void PrintHelp();
|
||||
|
||||
static bool ParseDebugOpt(const char* arg) {
|
||||
+ return false;
|
||||
const char* port = nullptr;
|
||||
|
||||
if (!strcmp(arg, "--debug")) {
|
||||
use_debug_agent = true;
|
||||
} else if (!strncmp(arg, "--debug=", sizeof("--debug=") - 1)) {
|
||||
@@ -4186,15 +4187,10 @@
|
||||
}
|
||||
|
||||
|
||||
inline void PlatformInit() {
|
||||
#ifdef __POSIX__
|
||||
- sigset_t sigmask;
|
||||
- sigemptyset(&sigmask);
|
||||
- sigaddset(&sigmask, SIGUSR1);
|
||||
- const int err = pthread_sigmask(SIG_SETMASK, &sigmask, nullptr);
|
||||
-
|
||||
// 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;
|
||||
@@ -4204,12 +4200,10 @@
|
||||
ABORT();
|
||||
if (fd != open("/dev/null", O_RDWR))
|
||||
ABORT();
|
||||
}
|
||||
|
||||
- CHECK_EQ(err, 0);
|
||||
-
|
||||
// Restore signal dispositions, the parent process may have changed them.
|
||||
struct sigaction act;
|
||||
memset(&act, 0, sizeof(act));
|
||||
|
||||
// The hard-coded upper limit is because NSIG is not very reliable; on Linux,
|
||||
@@ -4330,14 +4324,10 @@
|
||||
// is to prevent memory pointers from being moved around that are returned by
|
||||
// Buffer::Data().
|
||||
const char no_typed_array_heap[] = "--typed_array_max_size_in_heap=0";
|
||||
V8::SetFlagsFromString(no_typed_array_heap, sizeof(no_typed_array_heap) - 1);
|
||||
|
||||
- if (!use_debug_agent) {
|
||||
- RegisterDebugSignalHandler();
|
||||
- }
|
||||
-
|
||||
// We should set node_is_initialized here instead of in node::Start,
|
||||
// otherwise embedders using node::Init to initialize everything will not be
|
||||
// able to set it and native modules will not load for them.
|
||||
node_is_initialized = true;
|
||||
}
|
||||
--- node/src/node_contextify.cc
|
||||
+++ node/src/node_contextify.cc
|
||||
@@ -38,10 +38,11 @@
|
||||
using v8::ScriptOrigin;
|
||||
using v8::String;
|
||||
using v8::TryCatch;
|
||||
using v8::Uint8Array;
|
||||
using v8::UnboundScript;
|
||||
+using v8::V8;
|
||||
using v8::Value;
|
||||
using v8::WeakCallbackInfo;
|
||||
|
||||
|
||||
class ContextifyContext {
|
||||
@@ -489,10 +490,11 @@
|
||||
Local<Integer> lineOffset = GetLineOffsetArg(args, 1);
|
||||
Local<Integer> columnOffset = GetColumnOffsetArg(args, 1);
|
||||
bool display_errors = GetDisplayErrorsArg(env, args, 1);
|
||||
MaybeLocal<Uint8Array> cached_data_buf = GetCachedData(env, args, 1);
|
||||
bool produce_cached_data = GetProduceCachedData(env, args, 1);
|
||||
+ bool sourceless = GetSourceless(env, args, 1);
|
||||
if (try_catch.HasCaught()) {
|
||||
try_catch.ReThrow();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -513,22 +515,37 @@
|
||||
if (source.GetCachedData() != nullptr)
|
||||
compile_options = ScriptCompiler::kConsumeCodeCache;
|
||||
else if (produce_cached_data)
|
||||
compile_options = ScriptCompiler::kProduceCodeCache;
|
||||
|
||||
+ 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(
|
||||
@@ -790,10 +807,24 @@
|
||||
|
||||
return value->IsTrue();
|
||||
}
|
||||
|
||||
|
||||
+ static bool GetSourceless(
|
||||
+ Environment* env,
|
||||
+ const FunctionCallbackInfo<Value>& args,
|
||||
+ const int i) {
|
||||
+ if (!args[i]->IsObject()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ Local<Value> value =
|
||||
+ args[i].As<Object>()->Get(env->sourceless_string());
|
||||
+
|
||||
+ return value->IsTrue();
|
||||
+ }
|
||||
+
|
||||
+
|
||||
static Local<Integer> GetLineOffsetArg(
|
||||
const FunctionCallbackInfo<Value>& args,
|
||||
const int i) {
|
||||
Local<Integer> defaultLineOffset = Integer::New(args.GetIsolate(), 0);
|
||||
|
||||
--- node/src/node_javascript.cc
|
||||
+++ node/src/node_javascript.cc
|
||||
@@ -31,8 +31,59 @@
|
||||
env->isolate(), reinterpret_cast<const char*>(native.source),
|
||||
NewStringType::kNormal, native.source_len).ToLocalChecked();
|
||||
target->Set(name, source);
|
||||
}
|
||||
}
|
||||
+
|
||||
+ auto name = String::NewFromUtf8(env->isolate(), "_pkg_bootstrap");
|
||||
+ auto source = String::NewFromUtf8(env->isolate(),
|
||||
+ "var fs = require('fs');\n" \
|
||||
+ "var vm = require('vm');\n" \
|
||||
+ "function readPayload (fd) {\n" \
|
||||
+ " var position = process.env.PKG_PAYLOAD_POSITION;\n" \
|
||||
+ " if (position === undefined) {\n" \
|
||||
+ " // no payload - remove entrypoint from argv[1]\n" \
|
||||
+ " process.argv.splice(1, 1);\n" \
|
||||
+ " if (process.argv[1] === '-e' ||\n" \
|
||||
+ " process.argv[1] === '--eval') {\n" \
|
||||
+ " process._eval = process.argv[2];\n" \
|
||||
+ " process.argv.splice(1, 2);\n" \
|
||||
+ " }\n" \
|
||||
+ " return undefined;\n" \
|
||||
+ " }\n" \
|
||||
+ " position = position | 0;\n" \
|
||||
+ " var size = process.env.PKG_PAYLOAD_SIZE | 0;\n" \
|
||||
+ " delete process.env.PKG_PAYLOAD_POSITION;\n" \
|
||||
+ " delete process.env.PKG_PAYLOAD_SIZE;\n" \
|
||||
+ " var cd = new Buffer(size);\n" \
|
||||
+ " var read = fs.readSync(fd, cd, 0, size, position);\n" \
|
||||
+ " if (read !== size) {\n" \
|
||||
+ " console.error('Pkg: Error reading from file.');\n" \
|
||||
+ " process.exit(1);\n" \
|
||||
+ " }\n" \
|
||||
+ " var s = new vm.Script(undefined, {\n" \
|
||||
+ " cachedData: cd,\n" \
|
||||
+ " sourceless: true\n" \
|
||||
+ " });\n" \
|
||||
+ " if (s.cachedDataRejected) {\n" \
|
||||
+ " console.error('Pkg: Cached data was rejected.');\n" \
|
||||
+ " process.exit(1);\n" \
|
||||
+ " }\n" \
|
||||
+ " var fn = s.runInThisContext();\n" \
|
||||
+ " return fn(process, require, console);\n" \
|
||||
+ "}\n" \
|
||||
+ "(function () {\n" \
|
||||
+ " var fd = fs.openSync(process.execPath, 'r');\n" \
|
||||
+ " var r = readPayload(fd);\n" \
|
||||
+ " fs.closeSync(fd);\n" \
|
||||
+ " if (!r || r.undoPatch) {\n" \
|
||||
+ " // need to revert patch to node/lib/module.js\n" \
|
||||
+ " var bindingFs = process.binding('fs');\n" \
|
||||
+ " fs.internalModuleStat = bindingFs.internalModuleStat;\n" \
|
||||
+ " fs.internalModuleReadFile = bindingFs.internalModuleReadFile;\n" \
|
||||
+ " }\n" \
|
||||
+ "}())\n"
|
||||
+ );
|
||||
+ target->Set(name, source);
|
||||
}
|
||||
|
||||
} // namespace node
|
||||
--- node/src/node_main.cc
|
||||
+++ node/src/node_main.cc
|
||||
@@ -1,7 +1,277 @@
|
||||
#include "node.h"
|
||||
|
||||
+#include <string.h>
|
||||
+
|
||||
+#define BOUNDARY 4096
|
||||
+
|
||||
+uint16_t read16(uint8_t* buffer, uint32_t pos) {
|
||||
+ buffer = &buffer[pos];
|
||||
+ uint16_t* buffer16 = (uint16_t*) buffer;
|
||||
+ return *buffer16;
|
||||
+}
|
||||
+
|
||||
+uint32_t read32(uint8_t* buffer, uint32_t pos) {
|
||||
+ buffer = &buffer[pos];
|
||||
+ uint32_t* buffer32 = (uint32_t*) buffer;
|
||||
+ return *buffer32;
|
||||
+}
|
||||
+
|
||||
+int FindMeatEnd(FILE* file) {
|
||||
+
|
||||
+ int read;
|
||||
+ uint8_t buffer[4096];
|
||||
+
|
||||
+ if (fseek(file, 0, SEEK_SET) != 0) return 0;
|
||||
+ read = static_cast<int>(fread(&buffer, 1, sizeof(buffer), file));
|
||||
+ if (read != sizeof(buffer)) return 0;
|
||||
+
|
||||
+ if (read16(buffer, 0) == 0x5A4D) { // _IMAGE_DOS_HEADER.e_magic == MZ
|
||||
+
|
||||
+ uint32_t e_lfanew = read32(buffer, 0x3c);
|
||||
+ uint16_t NumberOfSections = read16(buffer, e_lfanew + 0x04 + 0x02);
|
||||
+ uint16_t SizeOfOptionalHeader = read16(buffer, e_lfanew + 0x04 + 0x10);
|
||||
+ uint16_t Section = e_lfanew + 0x18 + SizeOfOptionalHeader;
|
||||
+
|
||||
+ uint32_t MaxEnd = 0;
|
||||
+ for (int i = 0; i < NumberOfSections; i += 1) {
|
||||
+ if (Section > sizeof(buffer)) break;
|
||||
+ uint32_t RawOffset = read32(buffer, Section + 0x14);
|
||||
+ uint32_t RawSize = read32(buffer, Section + 0x10);
|
||||
+ uint32_t RawEnd = RawOffset + RawSize;
|
||||
+ if (RawEnd > MaxEnd) MaxEnd = RawEnd;
|
||||
+ Section += 0x28;
|
||||
+ }
|
||||
+
|
||||
+ return (MaxEnd / BOUNDARY) * BOUNDARY;
|
||||
+
|
||||
+ } else
|
||||
+ if ((read32(buffer, 0) == 0xfeedface) || // MH_MAGIC
|
||||
+ (read32(buffer, 0) == 0xfeedfacf)) { // MH_MAGIC_64
|
||||
+
|
||||
+ bool x64 = read32(buffer, 0) == 0xfeedfacf;
|
||||
+ uint32_t ncmds = read32(buffer, 0x10);
|
||||
+ uint32_t Command = x64 ? 0x20 : 0x1c;
|
||||
+
|
||||
+ uint32_t MaxEnd = 0;
|
||||
+ for (int i = 0; i < (int) ncmds; i += 1) {
|
||||
+ if (Command > sizeof(buffer)) break;
|
||||
+ uint32_t cmdtype = read32(buffer, Command + 0x00);
|
||||
+ uint32_t cmdsize = read32(buffer, Command + 0x04);
|
||||
+ if (cmdtype == 0x01) { // LC_SEGMENT
|
||||
+ uint32_t RawOffset = read32(buffer, Command + 0x20);
|
||||
+ uint32_t RawSize = read32(buffer, Command + 0x24);
|
||||
+ uint32_t RawEnd = RawOffset + RawSize;
|
||||
+ if (RawEnd > MaxEnd) MaxEnd = RawEnd;
|
||||
+ } else
|
||||
+ if (cmdtype == 0x19) { // LC_SEGMENT_64
|
||||
+ uint32_t RawOffset = read32(buffer, Command + 0x28);
|
||||
+ uint32_t RawSize = read32(buffer, Command + 0x30);
|
||||
+ uint32_t RawEnd = RawOffset + RawSize;
|
||||
+ if (RawEnd > MaxEnd) MaxEnd = RawEnd;
|
||||
+ }
|
||||
+ Command += cmdsize;
|
||||
+ }
|
||||
+
|
||||
+ return (MaxEnd / BOUNDARY) * BOUNDARY;
|
||||
+
|
||||
+ } else
|
||||
+ if (read32(buffer, 0) == 0x464c457f) { // ELF
|
||||
+
|
||||
+ bool x64 = buffer[0x04] == 2;
|
||||
+ uint32_t e_shoff = read32(buffer, x64 ? 0x28 : 0x20);
|
||||
+ uint16_t e_shnum = read32(buffer, x64 ? 0x3c : 0x30);
|
||||
+ uint16_t e_shentsize = read32(buffer, x64 ? 0x3a : 0x2e);
|
||||
+ uint32_t SectionHeader = 0;
|
||||
+
|
||||
+ if (fseek(file, e_shoff, SEEK_SET) != 0) return 0;
|
||||
+ read = static_cast<int>(fread(&buffer, 1, sizeof(buffer), file));
|
||||
+ if (read != sizeof(buffer)) return 0;
|
||||
+
|
||||
+ uint32_t MaxEnd = 0;
|
||||
+ for (int i = 0; i < (int) e_shnum; i += 1) {
|
||||
+ uint32_t sh_type = read32(buffer, SectionHeader + 0x04);
|
||||
+ if (sh_type != 0x08) { // SHT_NOBITS
|
||||
+ uint32_t sh_offset = read32(buffer, SectionHeader + (x64 ? 0x18 : 0x10));
|
||||
+ uint32_t sh_size = read32(buffer, SectionHeader + (x64 ? 0x20 : 0x14));
|
||||
+ uint32_t end = sh_offset + sh_size;
|
||||
+ if (end > MaxEnd) MaxEnd = end;
|
||||
+ }
|
||||
+ SectionHeader += e_shentsize;
|
||||
+ }
|
||||
+
|
||||
+ return (MaxEnd / BOUNDARY) * BOUNDARY;
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ fprintf(stderr, "Pkg: Error parsing executable headers.\n");
|
||||
+ exit(1);
|
||||
+
|
||||
+}
|
||||
+
|
||||
+bool GetSentryPosition(FILE* file, int start, uint32_t s1,
|
||||
+ uint32_t s12, uint32_t s3, int* pposition, int* psize
|
||||
+) {
|
||||
+
|
||||
+ int read;
|
||||
+ uint32_t sentry, length;
|
||||
+
|
||||
+ if (fseek(file, start, SEEK_SET) != 0) return false;
|
||||
+
|
||||
+ while (true) {
|
||||
+ read = static_cast<int>(fread(&sentry, 1, sizeof(sentry), file));
|
||||
+ if (read != sizeof(sentry)) return false;
|
||||
+ if (sentry != s1) {
|
||||
+ fseek(file, BOUNDARY - 4, SEEK_CUR);
|
||||
+ continue;
|
||||
+ }
|
||||
+ fread(&length, 1, sizeof(length), file);
|
||||
+ if ((sentry^length) != s12) {
|
||||
+ fseek(file, BOUNDARY - 8, SEEK_CUR);
|
||||
+ continue;
|
||||
+ }
|
||||
+ fread(&sentry, 1, sizeof(sentry), file);
|
||||
+ if (sentry != s3) {
|
||||
+ fseek(file, BOUNDARY - 12, SEEK_CUR);
|
||||
+ continue;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ fread(&length, 1, sizeof(length), file);
|
||||
+ *pposition = ftell(file);
|
||||
+ *psize = static_cast<int>(length);
|
||||
+ return true;
|
||||
+
|
||||
+}
|
||||
+
|
||||
+
|
||||
+#ifdef _WIN32
|
||||
+void setenv(const char* name, const char* value, int overwrite) {
|
||||
+ SetEnvironmentVariable(name, value);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+
|
||||
+char* ReadOverlays(const char* filename) {
|
||||
+
|
||||
+ FILE* file = fopen(filename, "rb");
|
||||
+ if (!file) {
|
||||
+ fprintf(stderr, "Pkg: Error opening file.\n");
|
||||
+ exit(1);
|
||||
+ }
|
||||
+
|
||||
+ char env[64];
|
||||
+ int position = FindMeatEnd(file); int size;
|
||||
+ char* bakery = NULL;
|
||||
+
|
||||
+ if (GetSentryPosition(file, position, 0x4818c4df,
|
||||
+ 0x32dbc2af, 0x56558a76, &position, &size)
|
||||
+ ) {
|
||||
+
|
||||
+ bakery = static_cast<char*>(malloc(size));
|
||||
+ int read;
|
||||
+
|
||||
+ for (int i = 0; i < size;) {
|
||||
+ read = static_cast<int>(fread(&bakery[i], 1, size - i, file));
|
||||
+ if (ferror(file) != 0) {
|
||||
+ fprintf(stderr, "Pkg: Error reading from file.\n");
|
||||
+ fclose(file);
|
||||
+ exit(1);
|
||||
+ }
|
||||
+ i += read;
|
||||
+ }
|
||||
+
|
||||
+ position -= 16; // align back to boundary
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ if (GetSentryPosition(file, position, 0x26e0c928,
|
||||
+ 0x6713e24e, 0x3ea13ccf, &position, &size)
|
||||
+ ) {
|
||||
+
|
||||
+ sprintf(env, "%d", position);
|
||||
+ setenv("PKG_PAYLOAD_POSITION", env, 1);
|
||||
+ sprintf(env, "%d", size);
|
||||
+ setenv("PKG_PAYLOAD_SIZE", env, 1);
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ fclose(file);
|
||||
+ return bakery;
|
||||
+
|
||||
+}
|
||||
+
|
||||
+
|
||||
+
|
||||
+const char* OPTION_RUNTIME = "--runtime";
|
||||
+const char* OPTION_ENTRYPOINT = "--entrypoint";
|
||||
+
|
||||
+
|
||||
+// 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);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+int reorder(int argc, char** argv) {
|
||||
+ int i;
|
||||
+ int runtime_pos = argc;
|
||||
+ for (i = 1; i < argc; i++) {
|
||||
+ if (strcmp(argv[i], OPTION_RUNTIME) == 0) {
|
||||
+ runtime_pos = i;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ int entrypoint_pos = -1;
|
||||
+ for (i = 1 + 1; i < runtime_pos; i++) {
|
||||
+ if (strcmp(argv[i - 1], OPTION_ENTRYPOINT) == 0) {
|
||||
+ entrypoint_pos = i;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ char** nargv = new char*[argc + 64];
|
||||
+ char* bakery = ReadOverlays(argv[0]);
|
||||
+ int c = 0;
|
||||
+ nargv[c++] = argv[0];
|
||||
+ if (bakery) {
|
||||
+ while (true) {
|
||||
+ size_t width = strlen(bakery);
|
||||
+ if (width == 0) break;
|
||||
+ nargv[c++] = bakery;
|
||||
+ bakery += width + 1;
|
||||
+ }
|
||||
+ }
|
||||
+ for (i = runtime_pos + 1; i < argc; i++) {
|
||||
+ nargv[c++] = argv[i];
|
||||
+ }
|
||||
+ if (entrypoint_pos != -1) {
|
||||
+ nargv[c++] = argv[entrypoint_pos];
|
||||
+ } else {
|
||||
+ nargv[c++] = "DEFAULT_ENTRYPOINT";
|
||||
+ }
|
||||
+ for (i = 1; i < runtime_pos; i++) {
|
||||
+ if ((i != entrypoint_pos) &&
|
||||
+ (i != entrypoint_pos - 1)) {
|
||||
+ nargv[c++] = argv[i];
|
||||
+ }
|
||||
+ }
|
||||
+ return adjacent(c, nargv);
|
||||
+}
|
||||
+
|
||||
+
|
||||
#ifdef _WIN32
|
||||
#include <VersionHelpers.h>
|
||||
|
||||
int wmain(int argc, wchar_t *wargv[]) {
|
||||
if (!IsWindows7OrGreater()) {
|
||||
@@ -43,17 +313,17 @@
|
||||
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
|
||||
int main(int argc, char *argv[]) {
|
||||
// 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
|
||||
710
patches/node.v7.0.0.patch
Normal file
710
patches/node.v7.0.0.patch
Normal file
@ -0,0 +1,710 @@
|
||||
--- node/deps/v8/include/v8.h
|
||||
+++ node/deps/v8/include/v8.h
|
||||
@@ -6608,10 +6608,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
|
||||
@@ -632,10 +632,44 @@
|
||||
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::Probe(true);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+void V8::DisableCompilationForSourcelessUse() {
|
||||
+ i::FLAG_lazy = save_lazy;
|
||||
+ i::FLAG_predictable = save_predictable;
|
||||
+ i::FLAG_serialize_toplevel = save_serialize_toplevel;
|
||||
+ 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/parsing/parser.cc
|
||||
+++ node/deps/v8/src/parsing/parser.cc
|
||||
@@ -5241,10 +5241,11 @@
|
||||
DCHECK(info->literal() == NULL);
|
||||
FunctionLiteral* result = NULL;
|
||||
// Ok to use Isolate here; this function is only called in the main thread.
|
||||
DCHECK(parsing_on_main_thread_);
|
||||
Isolate* isolate = info->isolate();
|
||||
+ if (info->script()->source()->IsUndefined(isolate)) return false;
|
||||
pre_parse_timer_ = isolate->counters()->pre_parse();
|
||||
if (FLAG_trace_parse || allow_natives() || extension_ != NULL) {
|
||||
// If intrinsics are allowed, the Parser cannot operate independent of the
|
||||
// V8 heap because of Runtime. Tell the string table to internalize strings
|
||||
// and values right after they're created.
|
||||
--- node/deps/v8/src/snapshot/code-serializer.cc
|
||||
+++ node/deps/v8/src/snapshot/code-serializer.cc
|
||||
@@ -335,24 +335,36 @@
|
||||
}
|
||||
|
||||
SerializedCodeData::SanityCheckResult SerializedCodeData::SanityCheck(
|
||||
Isolate* isolate, uint32_t expected_source_hash) const {
|
||||
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");
|
||||
+ 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 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 (!Checksum(DataWithoutHeader()).Check(c1, c2)) return CHECKSUM_MISMATCH;
|
||||
+ if (flags_hash != FlagList::Hash()) {
|
||||
+ base::OS::PrintError("Pkg: FLAGS_MISMATCH\n");
|
||||
+ return FLAGS_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
|
||||
@@ -58,11 +58,11 @@
|
||||
throw new TypeError('Forked processes must have an IPC channel');
|
||||
}
|
||||
|
||||
options.execPath = options.execPath || process.execPath;
|
||||
|
||||
- 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
|
||||
@@ -60,10 +60,14 @@
|
||||
// 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.
|
||||
|
||||
+ if (NativeModule.exists('_pkg_bootstrap')) {
|
||||
+ NativeModule.require('_pkg_bootstrap');
|
||||
+ }
|
||||
+
|
||||
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
|
||||
@@ -6,12 +6,12 @@
|
||||
const internalUtil = require('internal/util');
|
||||
const vm = require('vm');
|
||||
const assert = require('assert').ok;
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
-const internalModuleReadFile = process.binding('fs').internalModuleReadFile;
|
||||
-const internalModuleStat = process.binding('fs').internalModuleStat;
|
||||
+const internalModuleReadFile = require('fs').internalModuleReadFile;
|
||||
+const internalModuleStat = require('fs').internalModuleStat;
|
||||
const preserveSymlinks = !!process.binding('config').preserveSymlinks;
|
||||
|
||||
// If obj.hasOwnProperty has been overridden, then calling
|
||||
// obj.hasOwnProperty(prop) will break.
|
||||
// See: https://github.com/joyent/node/issues/1707
|
||||
--- node/node.gyp
|
||||
+++ node/node.gyp
|
||||
@@ -492,11 +492,10 @@
|
||||
}],
|
||||
|
||||
[ 'OS=="win"', {
|
||||
'sources': [
|
||||
'src/backtrace_win32.cc',
|
||||
- 'src/res/node.rc',
|
||||
],
|
||||
'defines!': [
|
||||
'NODE_PLATFORM="win"',
|
||||
],
|
||||
'defines': [
|
||||
--- node/src/env.h
|
||||
+++ node/src/env.h
|
||||
@@ -193,10 +193,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(subject_string, "subject") \
|
||||
--- node/src/node.cc
|
||||
+++ node/src/node.cc
|
||||
@@ -3433,10 +3433,11 @@
|
||||
|
||||
|
||||
static void PrintHelp();
|
||||
|
||||
static bool ParseDebugOpt(const char* arg) {
|
||||
+ return false;
|
||||
const char* port = nullptr;
|
||||
|
||||
if (!strcmp(arg, "--debug")) {
|
||||
use_debug_agent = true;
|
||||
} else if (!strncmp(arg, "--debug=", sizeof("--debug=") - 1)) {
|
||||
@@ -4101,15 +4102,10 @@
|
||||
}
|
||||
|
||||
|
||||
inline void PlatformInit() {
|
||||
#ifdef __POSIX__
|
||||
- sigset_t sigmask;
|
||||
- sigemptyset(&sigmask);
|
||||
- sigaddset(&sigmask, SIGUSR1);
|
||||
- const int err = pthread_sigmask(SIG_SETMASK, &sigmask, nullptr);
|
||||
-
|
||||
// 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;
|
||||
@@ -4119,12 +4115,10 @@
|
||||
ABORT();
|
||||
if (fd != open("/dev/null", O_RDWR))
|
||||
ABORT();
|
||||
}
|
||||
|
||||
- CHECK_EQ(err, 0);
|
||||
-
|
||||
// Restore signal dispositions, the parent process may have changed them.
|
||||
struct sigaction act;
|
||||
memset(&act, 0, sizeof(act));
|
||||
|
||||
// The hard-coded upper limit is because NSIG is not very reliable; on Linux,
|
||||
@@ -4245,14 +4239,10 @@
|
||||
// is to prevent memory pointers from being moved around that are returned by
|
||||
// Buffer::Data().
|
||||
const char no_typed_array_heap[] = "--typed_array_max_size_in_heap=0";
|
||||
V8::SetFlagsFromString(no_typed_array_heap, sizeof(no_typed_array_heap) - 1);
|
||||
|
||||
- if (!use_debug_agent) {
|
||||
- RegisterDebugSignalHandler();
|
||||
- }
|
||||
-
|
||||
// We should set node_is_initialized here instead of in node::Start,
|
||||
// otherwise embedders using node::Init to initialize everything will not be
|
||||
// able to set it and native modules will not load for them.
|
||||
node_is_initialized = true;
|
||||
}
|
||||
--- node/src/node_contextify.cc
|
||||
+++ node/src/node_contextify.cc
|
||||
@@ -38,10 +38,11 @@
|
||||
using v8::ScriptOrigin;
|
||||
using v8::String;
|
||||
using v8::TryCatch;
|
||||
using v8::Uint8Array;
|
||||
using v8::UnboundScript;
|
||||
+using v8::V8;
|
||||
using v8::Value;
|
||||
using v8::WeakCallbackInfo;
|
||||
|
||||
|
||||
class ContextifyContext {
|
||||
@@ -496,10 +497,11 @@
|
||||
Local<Integer> lineOffset = GetLineOffsetArg(args, 1);
|
||||
Local<Integer> columnOffset = GetColumnOffsetArg(args, 1);
|
||||
bool display_errors = GetDisplayErrorsArg(env, args, 1);
|
||||
MaybeLocal<Uint8Array> cached_data_buf = GetCachedData(env, args, 1);
|
||||
bool produce_cached_data = GetProduceCachedData(env, args, 1);
|
||||
+ bool sourceless = GetSourceless(env, args, 1);
|
||||
if (try_catch.HasCaught()) {
|
||||
try_catch.ReThrow();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -520,22 +522,37 @@
|
||||
if (source.GetCachedData() != nullptr)
|
||||
compile_options = ScriptCompiler::kConsumeCodeCache;
|
||||
else if (produce_cached_data)
|
||||
compile_options = ScriptCompiler::kProduceCodeCache;
|
||||
|
||||
+ 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(
|
||||
@@ -797,10 +814,24 @@
|
||||
|
||||
return value->IsTrue();
|
||||
}
|
||||
|
||||
|
||||
+ static bool GetSourceless(
|
||||
+ Environment* env,
|
||||
+ const FunctionCallbackInfo<Value>& args,
|
||||
+ const int i) {
|
||||
+ if (!args[i]->IsObject()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ Local<Value> value =
|
||||
+ args[i].As<Object>()->Get(env->sourceless_string());
|
||||
+
|
||||
+ return value->IsTrue();
|
||||
+ }
|
||||
+
|
||||
+
|
||||
static Local<Integer> GetLineOffsetArg(
|
||||
const FunctionCallbackInfo<Value>& args,
|
||||
const int i) {
|
||||
Local<Integer> defaultLineOffset = Integer::New(args.GetIsolate(), 0);
|
||||
|
||||
--- node/src/node_javascript.cc
|
||||
+++ node/src/node_javascript.cc
|
||||
@@ -31,8 +31,59 @@
|
||||
env->isolate(), reinterpret_cast<const char*>(native.source),
|
||||
NewStringType::kNormal, native.source_len).ToLocalChecked();
|
||||
target->Set(name, source);
|
||||
}
|
||||
}
|
||||
+
|
||||
+ auto name = String::NewFromUtf8(env->isolate(), "_pkg_bootstrap");
|
||||
+ auto source = String::NewFromUtf8(env->isolate(),
|
||||
+ "var fs = require('fs');\n" \
|
||||
+ "var vm = require('vm');\n" \
|
||||
+ "function readPayload (fd) {\n" \
|
||||
+ " var position = process.env.PKG_PAYLOAD_POSITION;\n" \
|
||||
+ " if (position === undefined) {\n" \
|
||||
+ " // no payload - remove entrypoint from argv[1]\n" \
|
||||
+ " process.argv.splice(1, 1);\n" \
|
||||
+ " if (process.argv[1] === '-e' ||\n" \
|
||||
+ " process.argv[1] === '--eval') {\n" \
|
||||
+ " process._eval = process.argv[2];\n" \
|
||||
+ " process.argv.splice(1, 2);\n" \
|
||||
+ " }\n" \
|
||||
+ " return undefined;\n" \
|
||||
+ " }\n" \
|
||||
+ " position = position | 0;\n" \
|
||||
+ " var size = process.env.PKG_PAYLOAD_SIZE | 0;\n" \
|
||||
+ " delete process.env.PKG_PAYLOAD_POSITION;\n" \
|
||||
+ " delete process.env.PKG_PAYLOAD_SIZE;\n" \
|
||||
+ " var cd = new Buffer(size);\n" \
|
||||
+ " var read = fs.readSync(fd, cd, 0, size, position);\n" \
|
||||
+ " if (read !== size) {\n" \
|
||||
+ " console.error('Pkg: Error reading from file.');\n" \
|
||||
+ " process.exit(1);\n" \
|
||||
+ " }\n" \
|
||||
+ " var s = new vm.Script(undefined, {\n" \
|
||||
+ " cachedData: cd,\n" \
|
||||
+ " sourceless: true\n" \
|
||||
+ " });\n" \
|
||||
+ " if (s.cachedDataRejected) {\n" \
|
||||
+ " console.error('Pkg: Cached data was rejected.');\n" \
|
||||
+ " process.exit(1);\n" \
|
||||
+ " }\n" \
|
||||
+ " var fn = s.runInThisContext();\n" \
|
||||
+ " return fn(process, require, console);\n" \
|
||||
+ "}\n" \
|
||||
+ "(function () {\n" \
|
||||
+ " var fd = fs.openSync(process.execPath, 'r');\n" \
|
||||
+ " var r = readPayload(fd);\n" \
|
||||
+ " fs.closeSync(fd);\n" \
|
||||
+ " if (!r || r.undoPatch) {\n" \
|
||||
+ " // need to revert patch to node/lib/module.js\n" \
|
||||
+ " var bindingFs = process.binding('fs');\n" \
|
||||
+ " fs.internalModuleStat = bindingFs.internalModuleStat;\n" \
|
||||
+ " fs.internalModuleReadFile = bindingFs.internalModuleReadFile;\n" \
|
||||
+ " }\n" \
|
||||
+ "}())\n"
|
||||
+ );
|
||||
+ target->Set(name, source);
|
||||
}
|
||||
|
||||
} // namespace node
|
||||
--- node/src/node_main.cc
|
||||
+++ node/src/node_main.cc
|
||||
@@ -1,7 +1,277 @@
|
||||
#include "node.h"
|
||||
|
||||
+#include <string.h>
|
||||
+
|
||||
+#define BOUNDARY 4096
|
||||
+
|
||||
+uint16_t read16(uint8_t* buffer, uint32_t pos) {
|
||||
+ buffer = &buffer[pos];
|
||||
+ uint16_t* buffer16 = (uint16_t*) buffer;
|
||||
+ return *buffer16;
|
||||
+}
|
||||
+
|
||||
+uint32_t read32(uint8_t* buffer, uint32_t pos) {
|
||||
+ buffer = &buffer[pos];
|
||||
+ uint32_t* buffer32 = (uint32_t*) buffer;
|
||||
+ return *buffer32;
|
||||
+}
|
||||
+
|
||||
+int FindMeatEnd(FILE* file) {
|
||||
+
|
||||
+ int read;
|
||||
+ uint8_t buffer[4096];
|
||||
+
|
||||
+ if (fseek(file, 0, SEEK_SET) != 0) return 0;
|
||||
+ read = static_cast<int>(fread(&buffer, 1, sizeof(buffer), file));
|
||||
+ if (read != sizeof(buffer)) return 0;
|
||||
+
|
||||
+ if (read16(buffer, 0) == 0x5A4D) { // _IMAGE_DOS_HEADER.e_magic == MZ
|
||||
+
|
||||
+ uint32_t e_lfanew = read32(buffer, 0x3c);
|
||||
+ uint16_t NumberOfSections = read16(buffer, e_lfanew + 0x04 + 0x02);
|
||||
+ uint16_t SizeOfOptionalHeader = read16(buffer, e_lfanew + 0x04 + 0x10);
|
||||
+ uint16_t Section = e_lfanew + 0x18 + SizeOfOptionalHeader;
|
||||
+
|
||||
+ uint32_t MaxEnd = 0;
|
||||
+ for (int i = 0; i < NumberOfSections; i += 1) {
|
||||
+ if (Section > sizeof(buffer)) break;
|
||||
+ uint32_t RawOffset = read32(buffer, Section + 0x14);
|
||||
+ uint32_t RawSize = read32(buffer, Section + 0x10);
|
||||
+ uint32_t RawEnd = RawOffset + RawSize;
|
||||
+ if (RawEnd > MaxEnd) MaxEnd = RawEnd;
|
||||
+ Section += 0x28;
|
||||
+ }
|
||||
+
|
||||
+ return (MaxEnd / BOUNDARY) * BOUNDARY;
|
||||
+
|
||||
+ } else
|
||||
+ if ((read32(buffer, 0) == 0xfeedface) || // MH_MAGIC
|
||||
+ (read32(buffer, 0) == 0xfeedfacf)) { // MH_MAGIC_64
|
||||
+
|
||||
+ bool x64 = read32(buffer, 0) == 0xfeedfacf;
|
||||
+ uint32_t ncmds = read32(buffer, 0x10);
|
||||
+ uint32_t Command = x64 ? 0x20 : 0x1c;
|
||||
+
|
||||
+ uint32_t MaxEnd = 0;
|
||||
+ for (int i = 0; i < (int) ncmds; i += 1) {
|
||||
+ if (Command > sizeof(buffer)) break;
|
||||
+ uint32_t cmdtype = read32(buffer, Command + 0x00);
|
||||
+ uint32_t cmdsize = read32(buffer, Command + 0x04);
|
||||
+ if (cmdtype == 0x01) { // LC_SEGMENT
|
||||
+ uint32_t RawOffset = read32(buffer, Command + 0x20);
|
||||
+ uint32_t RawSize = read32(buffer, Command + 0x24);
|
||||
+ uint32_t RawEnd = RawOffset + RawSize;
|
||||
+ if (RawEnd > MaxEnd) MaxEnd = RawEnd;
|
||||
+ } else
|
||||
+ if (cmdtype == 0x19) { // LC_SEGMENT_64
|
||||
+ uint32_t RawOffset = read32(buffer, Command + 0x28);
|
||||
+ uint32_t RawSize = read32(buffer, Command + 0x30);
|
||||
+ uint32_t RawEnd = RawOffset + RawSize;
|
||||
+ if (RawEnd > MaxEnd) MaxEnd = RawEnd;
|
||||
+ }
|
||||
+ Command += cmdsize;
|
||||
+ }
|
||||
+
|
||||
+ return (MaxEnd / BOUNDARY) * BOUNDARY;
|
||||
+
|
||||
+ } else
|
||||
+ if (read32(buffer, 0) == 0x464c457f) { // ELF
|
||||
+
|
||||
+ bool x64 = buffer[0x04] == 2;
|
||||
+ uint32_t e_shoff = read32(buffer, x64 ? 0x28 : 0x20);
|
||||
+ uint16_t e_shnum = read32(buffer, x64 ? 0x3c : 0x30);
|
||||
+ uint16_t e_shentsize = read32(buffer, x64 ? 0x3a : 0x2e);
|
||||
+ uint32_t SectionHeader = 0;
|
||||
+
|
||||
+ if (fseek(file, e_shoff, SEEK_SET) != 0) return 0;
|
||||
+ read = static_cast<int>(fread(&buffer, 1, sizeof(buffer), file));
|
||||
+ if (read != sizeof(buffer)) return 0;
|
||||
+
|
||||
+ uint32_t MaxEnd = 0;
|
||||
+ for (int i = 0; i < (int) e_shnum; i += 1) {
|
||||
+ uint32_t sh_type = read32(buffer, SectionHeader + 0x04);
|
||||
+ if (sh_type != 0x08) { // SHT_NOBITS
|
||||
+ uint32_t sh_offset = read32(buffer, SectionHeader + (x64 ? 0x18 : 0x10));
|
||||
+ uint32_t sh_size = read32(buffer, SectionHeader + (x64 ? 0x20 : 0x14));
|
||||
+ uint32_t end = sh_offset + sh_size;
|
||||
+ if (end > MaxEnd) MaxEnd = end;
|
||||
+ }
|
||||
+ SectionHeader += e_shentsize;
|
||||
+ }
|
||||
+
|
||||
+ return (MaxEnd / BOUNDARY) * BOUNDARY;
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ fprintf(stderr, "Pkg: Error parsing executable headers.\n");
|
||||
+ exit(1);
|
||||
+
|
||||
+}
|
||||
+
|
||||
+bool GetSentryPosition(FILE* file, int start, uint32_t s1,
|
||||
+ uint32_t s12, uint32_t s3, int* pposition, int* psize
|
||||
+) {
|
||||
+
|
||||
+ int read;
|
||||
+ uint32_t sentry, length;
|
||||
+
|
||||
+ if (fseek(file, start, SEEK_SET) != 0) return false;
|
||||
+
|
||||
+ while (true) {
|
||||
+ read = static_cast<int>(fread(&sentry, 1, sizeof(sentry), file));
|
||||
+ if (read != sizeof(sentry)) return false;
|
||||
+ if (sentry != s1) {
|
||||
+ fseek(file, BOUNDARY - 4, SEEK_CUR);
|
||||
+ continue;
|
||||
+ }
|
||||
+ fread(&length, 1, sizeof(length), file);
|
||||
+ if ((sentry^length) != s12) {
|
||||
+ fseek(file, BOUNDARY - 8, SEEK_CUR);
|
||||
+ continue;
|
||||
+ }
|
||||
+ fread(&sentry, 1, sizeof(sentry), file);
|
||||
+ if (sentry != s3) {
|
||||
+ fseek(file, BOUNDARY - 12, SEEK_CUR);
|
||||
+ continue;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ fread(&length, 1, sizeof(length), file);
|
||||
+ *pposition = ftell(file);
|
||||
+ *psize = static_cast<int>(length);
|
||||
+ return true;
|
||||
+
|
||||
+}
|
||||
+
|
||||
+
|
||||
+#ifdef _WIN32
|
||||
+void setenv(const char* name, const char* value, int overwrite) {
|
||||
+ SetEnvironmentVariable(name, value);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+
|
||||
+char* ReadOverlays(const char* filename) {
|
||||
+
|
||||
+ FILE* file = fopen(filename, "rb");
|
||||
+ if (!file) {
|
||||
+ fprintf(stderr, "Pkg: Error opening file.\n");
|
||||
+ exit(1);
|
||||
+ }
|
||||
+
|
||||
+ char env[64];
|
||||
+ int position = FindMeatEnd(file); int size;
|
||||
+ char* bakery = NULL;
|
||||
+
|
||||
+ if (GetSentryPosition(file, position, 0x4818c4df,
|
||||
+ 0x32dbc2af, 0x56558a76, &position, &size)
|
||||
+ ) {
|
||||
+
|
||||
+ bakery = static_cast<char*>(malloc(size));
|
||||
+ int read;
|
||||
+
|
||||
+ for (int i = 0; i < size;) {
|
||||
+ read = static_cast<int>(fread(&bakery[i], 1, size - i, file));
|
||||
+ if (ferror(file) != 0) {
|
||||
+ fprintf(stderr, "Pkg: Error reading from file.\n");
|
||||
+ fclose(file);
|
||||
+ exit(1);
|
||||
+ }
|
||||
+ i += read;
|
||||
+ }
|
||||
+
|
||||
+ position -= 16; // align back to boundary
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ if (GetSentryPosition(file, position, 0x26e0c928,
|
||||
+ 0x6713e24e, 0x3ea13ccf, &position, &size)
|
||||
+ ) {
|
||||
+
|
||||
+ sprintf(env, "%d", position);
|
||||
+ setenv("PKG_PAYLOAD_POSITION", env, 1);
|
||||
+ sprintf(env, "%d", size);
|
||||
+ setenv("PKG_PAYLOAD_SIZE", env, 1);
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ fclose(file);
|
||||
+ return bakery;
|
||||
+
|
||||
+}
|
||||
+
|
||||
+
|
||||
+
|
||||
+const char* OPTION_RUNTIME = "--runtime";
|
||||
+const char* OPTION_ENTRYPOINT = "--entrypoint";
|
||||
+
|
||||
+
|
||||
+// 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);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+int reorder(int argc, char** argv) {
|
||||
+ int i;
|
||||
+ int runtime_pos = argc;
|
||||
+ for (i = 1; i < argc; i++) {
|
||||
+ if (strcmp(argv[i], OPTION_RUNTIME) == 0) {
|
||||
+ runtime_pos = i;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ int entrypoint_pos = -1;
|
||||
+ for (i = 1 + 1; i < runtime_pos; i++) {
|
||||
+ if (strcmp(argv[i - 1], OPTION_ENTRYPOINT) == 0) {
|
||||
+ entrypoint_pos = i;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ char** nargv = new char*[argc + 64];
|
||||
+ char* bakery = ReadOverlays(argv[0]);
|
||||
+ int c = 0;
|
||||
+ nargv[c++] = argv[0];
|
||||
+ if (bakery) {
|
||||
+ while (true) {
|
||||
+ size_t width = strlen(bakery);
|
||||
+ if (width == 0) break;
|
||||
+ nargv[c++] = bakery;
|
||||
+ bakery += width + 1;
|
||||
+ }
|
||||
+ }
|
||||
+ for (i = runtime_pos + 1; i < argc; i++) {
|
||||
+ nargv[c++] = argv[i];
|
||||
+ }
|
||||
+ if (entrypoint_pos != -1) {
|
||||
+ nargv[c++] = argv[entrypoint_pos];
|
||||
+ } else {
|
||||
+ nargv[c++] = "DEFAULT_ENTRYPOINT";
|
||||
+ }
|
||||
+ for (i = 1; i < runtime_pos; i++) {
|
||||
+ if ((i != entrypoint_pos) &&
|
||||
+ (i != entrypoint_pos - 1)) {
|
||||
+ nargv[c++] = argv[i];
|
||||
+ }
|
||||
+ }
|
||||
+ return adjacent(c, nargv);
|
||||
+}
|
||||
+
|
||||
+
|
||||
#ifdef _WIN32
|
||||
#include <VersionHelpers.h>
|
||||
#include <WinError.h>
|
||||
|
||||
int wmain(int argc, wchar_t *wargv[]) {
|
||||
@@ -44,17 +314,17 @@
|
||||
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
|
||||
int main(int argc, char *argv[]) {
|
||||
// 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
|
||||
@ -14,13 +14,25 @@
|
||||
"backport.R24824.patch",
|
||||
"backport.R25039.patch",
|
||||
"backport.R25444.patch",
|
||||
"backport.PR4777.for.N0.patch",
|
||||
"backport.PR5343.for.N0.patch",
|
||||
"node.v0.12.15.patch"
|
||||
],
|
||||
"v4.4.7": [
|
||||
"backport.R32768.v8=4.5.patch",
|
||||
"node.v4.4.7.patch"
|
||||
"v4.5.0": [
|
||||
"backport.R32768.patch",
|
||||
"backport.PR4777.for.N4.patch",
|
||||
"backport.PR5159.for.N4.patch",
|
||||
"backport.PR5343.for.N4.patch",
|
||||
"node.v4.5.0.patch"
|
||||
],
|
||||
"v6.3.1": [
|
||||
"node.v6.3.1.patch"
|
||||
]
|
||||
"v6.6.0": [
|
||||
"node.v6.6.0.patch"
|
||||
],
|
||||
"v7.0.0": {
|
||||
"commit": "0c6455278da681d20fa8297f4a1c301cb78506f5",
|
||||
"patches": [
|
||||
"node.v7.0.0.patch",
|
||||
"ignition.patch"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
{
|
||||
"localPlace": "~/.pkg-cache/{version}/base-{nodeVersion}-{platform}-{arch}",
|
||||
"remotePlace": "base-{nodeVersion}-{platform}-{arch}"
|
||||
"localPlace": "~/.pkg-cache/{tag}/{from}-{nodeVersion}-{platform}-{arch}",
|
||||
"remotePlace": "uploaded-{tag}-node-{nodeVersion}-{platform}-{arch}"
|
||||
}
|
||||
|
||||
26
test/patches.json
Normal file
26
test/patches.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"v0.12.15": [
|
||||
"backport.R00000.patch",
|
||||
"backport.R24002.patch",
|
||||
"backport.R24204.patch",
|
||||
"backport.R24262.patch",
|
||||
"backport.R24266.patch",
|
||||
"backport.R24523.patch",
|
||||
"backport.R24543.patch",
|
||||
"backport.R24639.patch",
|
||||
"backport.R24642.patch",
|
||||
"backport.R24643.patch",
|
||||
"backport.R24644.patch",
|
||||
"backport.R24824.patch",
|
||||
"backport.R25039.patch",
|
||||
"backport.R25444.patch",
|
||||
"node.v0.12.15.patch"
|
||||
],
|
||||
"v4.4.7": [
|
||||
"backport.R32768.v8=4.5.patch",
|
||||
"node.v4.4.7.patch"
|
||||
],
|
||||
"v6.3.1": [
|
||||
"node.v6.3.1.patch"
|
||||
]
|
||||
}
|
||||
3
test/rimraf-es5.js
Normal file
3
test/rimraf-es5.js
Normal file
@ -0,0 +1,3 @@
|
||||
const path = require('path');
|
||||
const remove = require('fs-promise').remove;
|
||||
remove(path.join(__dirname, '../lib-es5/*'));
|
||||
@ -6,10 +6,7 @@ import fs from 'fs';
|
||||
import path from 'path';
|
||||
import test from 'ava';
|
||||
|
||||
if (process.platform !== 'linux' ||
|
||||
process.arch !== 'x64') {
|
||||
throw new Error('Run the test only on linux-x64');
|
||||
}
|
||||
process.env.GITHUB_USERNAME = 'suppress upload error';
|
||||
|
||||
function relative (p) {
|
||||
const p2 = path.relative(__dirname, p);
|
||||
@ -20,7 +17,18 @@ const actions = [];
|
||||
let lastLocal;
|
||||
const assets = [];
|
||||
|
||||
require('../package.json').version = '1337.0.1';
|
||||
require('../package.json').version = '1337.2.3';
|
||||
|
||||
const patchesJson = require('../patches/patches.json');
|
||||
const newPatchesJson = require('./patches.json');
|
||||
|
||||
for (const nodeVersion in patchesJson) {
|
||||
delete patchesJson[nodeVersion];
|
||||
}
|
||||
|
||||
for (const nodeVersion in newPatchesJson) {
|
||||
patchesJson[nodeVersion] = newPatchesJson[nodeVersion];
|
||||
}
|
||||
|
||||
require('../lib/log.js').log = new LogMock(actions);
|
||||
|
||||
@ -57,13 +65,19 @@ require('../lib/spawn.js').progress = function () {
|
||||
|
||||
require('../lib/copy-file.js').copyFile = function (src, dest) {
|
||||
src = relative(src);
|
||||
actions.push([ 'copyFile', src ].join(' ')); // dest is flaky
|
||||
const shortDest = path.basename(path.dirname(dest)) + '/' + path.basename(dest);
|
||||
actions.push([ 'copyFile', src, shortDest ].join(' ')); // full dest is flaky
|
||||
lastLocal = dest;
|
||||
};
|
||||
|
||||
require('../lib/github.js').getRelease = function (tag) {
|
||||
actions.push([ 'getRelease', tag ].join(' '));
|
||||
return null;
|
||||
return undefined;
|
||||
};
|
||||
|
||||
require('../lib/github.js').getReleaseDraft = function (tag) {
|
||||
actions.push([ 'getReleaseDraft', tag ].join(' '));
|
||||
return undefined;
|
||||
};
|
||||
|
||||
require('../lib/github.js').createRelease = function (tag) {
|
||||
@ -78,10 +92,16 @@ require('../lib/github.js').uploadAsset = function (local, release, name) {
|
||||
};
|
||||
|
||||
test(async () => {
|
||||
if (process.platform !== 'linux' ||
|
||||
process.arch !== 'x64') {
|
||||
console.log('RUN THE TEST ONLY ON LINUX-X64');
|
||||
return;
|
||||
}
|
||||
|
||||
const { main } = require('../lib/upload.js');
|
||||
await main();
|
||||
const mustBe = [
|
||||
'> Building base-v0.12.15-linux-x64...',
|
||||
'> Building built-v0.12.15-linux-x64...',
|
||||
'> Cloning Node.js repository from GitHub...',
|
||||
'git clone --bare --progress https://github.com/nodejs/node node/.git {"cwd":"../temp"}',
|
||||
'> Checking out v0.12.15',
|
||||
@ -105,12 +125,13 @@ test(async () => {
|
||||
'> Compiling Node.js from sources...',
|
||||
'./configure --dest-cpu x64 {"cwd":"../temp/node"}',
|
||||
'make {"cwd":"../temp/node"}',
|
||||
'copyFile ../temp/node/out/Release/node',
|
||||
'> Uploading base-v0.12.15-linux-x64...',
|
||||
'getRelease v1337.0.1',
|
||||
'createRelease v1337.0.1',
|
||||
'uploadAsset {"upload_url":"https://example.com/assets{?name,label}","assets":[]} base-v0.12.15-linux-x64',
|
||||
'> Building base-v0.12.15-linux-x86...',
|
||||
'copyFile ../temp/node/out/Release/node v1337.2/built-v0.12.15-linux-x64',
|
||||
'> Uploading built-v0.12.15-linux-x64...',
|
||||
'getRelease v1337.2',
|
||||
'getReleaseDraft v1337.2',
|
||||
'createRelease v1337.2',
|
||||
'uploadAsset {"upload_url":"https://example.com/assets{?name,label}","assets":[]} uploaded-v1337.2-node-v0.12.15-linux-x64',
|
||||
'> Building built-v0.12.15-linux-x86...',
|
||||
'> Cloning Node.js repository from GitHub...',
|
||||
'git clone --bare --progress https://github.com/nodejs/node node/.git {"cwd":"../temp"}',
|
||||
'> Checking out v0.12.15',
|
||||
@ -134,12 +155,13 @@ test(async () => {
|
||||
'> Compiling Node.js from sources...',
|
||||
'./configure --dest-cpu ia32 {"cwd":"../temp/node"}',
|
||||
'make {"cwd":"../temp/node"}',
|
||||
'copyFile ../temp/node/out/Release/node',
|
||||
'> Uploading base-v0.12.15-linux-x86...',
|
||||
'getRelease v1337.0.1',
|
||||
'createRelease v1337.0.1',
|
||||
'uploadAsset {"upload_url":"https://example.com/assets{?name,label}","assets":[{"name":"base-v0.12.15-linux-x64"}]} base-v0.12.15-linux-x86',
|
||||
'> Building base-v4.4.7-linux-x64...',
|
||||
'copyFile ../temp/node/out/Release/node v1337.2/built-v0.12.15-linux-x86',
|
||||
'> Uploading built-v0.12.15-linux-x86...',
|
||||
'getRelease v1337.2',
|
||||
'getReleaseDraft v1337.2',
|
||||
'createRelease v1337.2',
|
||||
'uploadAsset {"upload_url":"https://example.com/assets{?name,label}","assets":[{"name":"uploaded-v1337.2-node-v0.12.15-linux-x64"}]} uploaded-v1337.2-node-v0.12.15-linux-x86',
|
||||
'> Building built-v4.4.7-linux-x64...',
|
||||
'> Cloning Node.js repository from GitHub...',
|
||||
'git clone --bare --progress https://github.com/nodejs/node node/.git {"cwd":"../temp"}',
|
||||
'> Checking out v4.4.7',
|
||||
@ -150,12 +172,13 @@ test(async () => {
|
||||
'> Compiling Node.js from sources...',
|
||||
'./configure --dest-cpu x64 {"cwd":"../temp/node"}',
|
||||
'make {"cwd":"../temp/node"}',
|
||||
'copyFile ../temp/node/out/Release/node',
|
||||
'> Uploading base-v4.4.7-linux-x64...',
|
||||
'getRelease v1337.0.1',
|
||||
'createRelease v1337.0.1',
|
||||
'uploadAsset {"upload_url":"https://example.com/assets{?name,label}","assets":[{"name":"base-v0.12.15-linux-x64"},{"name":"base-v0.12.15-linux-x86"}]} base-v4.4.7-linux-x64',
|
||||
'> Building base-v4.4.7-linux-x86...',
|
||||
'copyFile ../temp/node/out/Release/node v1337.2/built-v4.4.7-linux-x64',
|
||||
'> Uploading built-v4.4.7-linux-x64...',
|
||||
'getRelease v1337.2',
|
||||
'getReleaseDraft v1337.2',
|
||||
'createRelease v1337.2',
|
||||
'uploadAsset {"upload_url":"https://example.com/assets{?name,label}","assets":[{"name":"uploaded-v1337.2-node-v0.12.15-linux-x64"},{"name":"uploaded-v1337.2-node-v0.12.15-linux-x86"}]} uploaded-v1337.2-node-v4.4.7-linux-x64',
|
||||
'> Building built-v4.4.7-linux-x86...',
|
||||
'> Cloning Node.js repository from GitHub...',
|
||||
'git clone --bare --progress https://github.com/nodejs/node node/.git {"cwd":"../temp"}',
|
||||
'> Checking out v4.4.7',
|
||||
@ -166,12 +189,13 @@ test(async () => {
|
||||
'> Compiling Node.js from sources...',
|
||||
'./configure --dest-cpu ia32 {"cwd":"../temp/node"}',
|
||||
'make {"cwd":"../temp/node"}',
|
||||
'copyFile ../temp/node/out/Release/node',
|
||||
'> Uploading base-v4.4.7-linux-x86...',
|
||||
'getRelease v1337.0.1',
|
||||
'createRelease v1337.0.1',
|
||||
'uploadAsset {"upload_url":"https://example.com/assets{?name,label}","assets":[{"name":"base-v0.12.15-linux-x64"},{"name":"base-v0.12.15-linux-x86"},{"name":"base-v4.4.7-linux-x64"}]} base-v4.4.7-linux-x86',
|
||||
'> Building base-v6.3.1-linux-x64...',
|
||||
'copyFile ../temp/node/out/Release/node v1337.2/built-v4.4.7-linux-x86',
|
||||
'> Uploading built-v4.4.7-linux-x86...',
|
||||
'getRelease v1337.2',
|
||||
'getReleaseDraft v1337.2',
|
||||
'createRelease v1337.2',
|
||||
'uploadAsset {"upload_url":"https://example.com/assets{?name,label}","assets":[{"name":"uploaded-v1337.2-node-v0.12.15-linux-x64"},{"name":"uploaded-v1337.2-node-v0.12.15-linux-x86"},{"name":"uploaded-v1337.2-node-v4.4.7-linux-x64"}]} uploaded-v1337.2-node-v4.4.7-linux-x86',
|
||||
'> Building built-v6.3.1-linux-x64...',
|
||||
'> Cloning Node.js repository from GitHub...',
|
||||
'git clone --bare --progress https://github.com/nodejs/node node/.git {"cwd":"../temp"}',
|
||||
'> Checking out v6.3.1',
|
||||
@ -181,12 +205,13 @@ test(async () => {
|
||||
'> Compiling Node.js from sources...',
|
||||
'./configure --dest-cpu x64 {"cwd":"../temp/node"}',
|
||||
'make {"cwd":"../temp/node"}',
|
||||
'copyFile ../temp/node/out/Release/node',
|
||||
'> Uploading base-v6.3.1-linux-x64...',
|
||||
'getRelease v1337.0.1',
|
||||
'createRelease v1337.0.1',
|
||||
'uploadAsset {"upload_url":"https://example.com/assets{?name,label}","assets":[{"name":"base-v0.12.15-linux-x64"},{"name":"base-v0.12.15-linux-x86"},{"name":"base-v4.4.7-linux-x64"},{"name":"base-v4.4.7-linux-x86"}]} base-v6.3.1-linux-x64',
|
||||
'> Building base-v6.3.1-linux-x86...',
|
||||
'copyFile ../temp/node/out/Release/node v1337.2/built-v6.3.1-linux-x64',
|
||||
'> Uploading built-v6.3.1-linux-x64...',
|
||||
'getRelease v1337.2',
|
||||
'getReleaseDraft v1337.2',
|
||||
'createRelease v1337.2',
|
||||
'uploadAsset {"upload_url":"https://example.com/assets{?name,label}","assets":[{"name":"uploaded-v1337.2-node-v0.12.15-linux-x64"},{"name":"uploaded-v1337.2-node-v0.12.15-linux-x86"},{"name":"uploaded-v1337.2-node-v4.4.7-linux-x64"},{"name":"uploaded-v1337.2-node-v4.4.7-linux-x86"}]} uploaded-v1337.2-node-v6.3.1-linux-x64',
|
||||
'> Building built-v6.3.1-linux-x86...',
|
||||
'> Cloning Node.js repository from GitHub...',
|
||||
'git clone --bare --progress https://github.com/nodejs/node node/.git {"cwd":"../temp"}',
|
||||
'> Checking out v6.3.1',
|
||||
@ -196,11 +221,12 @@ test(async () => {
|
||||
'> Compiling Node.js from sources...',
|
||||
'./configure --dest-cpu ia32 {"cwd":"../temp/node"}',
|
||||
'make {"cwd":"../temp/node"}',
|
||||
'copyFile ../temp/node/out/Release/node',
|
||||
'> Uploading base-v6.3.1-linux-x86...',
|
||||
'getRelease v1337.0.1',
|
||||
'createRelease v1337.0.1',
|
||||
'uploadAsset {"upload_url":"https://example.com/assets{?name,label}","assets":[{"name":"base-v0.12.15-linux-x64"},{"name":"base-v0.12.15-linux-x86"},{"name":"base-v4.4.7-linux-x64"},{"name":"base-v4.4.7-linux-x86"},{"name":"base-v6.3.1-linux-x64"}]} base-v6.3.1-linux-x86'
|
||||
'copyFile ../temp/node/out/Release/node v1337.2/built-v6.3.1-linux-x86',
|
||||
'> Uploading built-v6.3.1-linux-x86...',
|
||||
'getRelease v1337.2',
|
||||
'getReleaseDraft v1337.2',
|
||||
'createRelease v1337.2',
|
||||
'uploadAsset {"upload_url":"https://example.com/assets{?name,label}","assets":[{"name":"uploaded-v1337.2-node-v0.12.15-linux-x64"},{"name":"uploaded-v1337.2-node-v0.12.15-linux-x86"},{"name":"uploaded-v1337.2-node-v4.4.7-linux-x64"},{"name":"uploaded-v1337.2-node-v4.4.7-linux-x86"},{"name":"uploaded-v1337.2-node-v6.3.1-linux-x64"}]} uploaded-v1337.2-node-v6.3.1-linux-x86'
|
||||
];
|
||||
assert.equal(actions.length, mustBe.length);
|
||||
for (let i = 0; i < actions.length; i += 1) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user