From 5a155e25495834c49a260cbcbca158d43fc4b7d9 Mon Sep 17 00:00:00 2001 From: Nick Romito Date: Mon, 29 Aug 2022 16:38:55 -0500 Subject: [PATCH] Adding support for _third_party_main.js - support was removed in v15 and beyond --- src/NodeBuilder.js | 17 +++++++--- src/patch/16.16.0/node.cc.patch | 16 ++++++++++ .../16.16.0/run_third_party_main.js.patch | 16 ++++++++++ src/util.js | 32 ++++++++++++++++++- 4 files changed, 76 insertions(+), 5 deletions(-) create mode 100644 src/patch/16.16.0/node.cc.patch create mode 100644 src/patch/16.16.0/run_third_party_main.js.patch diff --git a/src/NodeBuilder.js b/src/NodeBuilder.js index 5e478d7..6cbea8c 100644 --- a/src/NodeBuilder.js +++ b/src/NodeBuilder.js @@ -1,8 +1,7 @@ -const { log, download, upload, fetch, mkdirp, rmrf, copyFileAsync, runCommand, renameAsync } = require('./util'); +const { log, download, upload, fetch, mkdirp, rmrf, copyFileAsync, runCommand, renameAsync, patchFile } = require('./util'); const { gzipSync, createGunzip } = require('zlib'); const { join, dirname, basename, resolve } = require('path'); -const { execSync } = require('child_process'); const fs = require('fs'); const path = require('path'); const os = require('os'); @@ -43,8 +42,7 @@ function buildName(platform, arch, placeHolderSizeMB, version) { } class NodeJsBuilder { - constructor(cwd, version, mainAppFile, appName) { - + constructor(cwd, version, mainAppFile, appName, patchDir) { this.version = version; this.appFile = resolve(mainAppFile); this.appName = appName; @@ -61,6 +59,7 @@ class NodeJsBuilder { this.make = isWindows ? 'vcbuild.bat' : isBsd ? 'gmake' : 'make'; this.configure = isWindows ? 'configure' : './configure'; this.srcDir = join(__dirname); + this.patchDir = patchDir || join(this.srcDir, 'patch', version); this.buildDir = join(cwd || process.cwd(), 'build'); this.nodeSrcFile = join(this.buildDir, `node-v${version}.tar.gz`); this.nodeSrcDir = join(this.buildDir, `node-v${version}`); @@ -190,6 +189,15 @@ class NodeJsBuilder { }); } + async patchThirdPartyMain() { + await patchFile( + this.nodePath('lib', 'internal', 'main', 'run_third_party_main.js'), + join(this.patchDir, 'run_third_party_main.js.patch')); + await patchFile( + this.nodePath('src', 'node.cc'), + join(this.patchDir, 'node.cc.patch')); + } + printDiskUsage() { if (isWindows) { return runCommand('fsutil', ['volume', 'diskfree', 'd:']); } return runCommand('df', ['-h']); @@ -234,6 +242,7 @@ class NodeJsBuilder { return this.printDiskUsage() .then(() => this.downloadExpandNodeSource()) .then(() => this.prepareNodeJsBuild()) + .then(() => this.version.split('.')[0] >= 15 ? this.patchThirdPartyMain() : Promise.resolve()) .then(() => { if (isWindows) { return runCommand(this.make, makeArgs, this.nodeSrcDir); } if (isDarwin) { diff --git a/src/patch/16.16.0/node.cc.patch b/src/patch/16.16.0/node.cc.patch new file mode 100644 index 0000000..2c84544 --- /dev/null +++ b/src/patch/16.16.0/node.cc.patch @@ -0,0 +1,16 @@ +--- src/node.cc 2022-08-26 13:05:24.458396341 -0500 ++++ src/node.cc 2022-08-26 13:06:12.179824998 -0500 +@@ -479,6 +479,13 @@ + return scope.EscapeMaybe(cb(info)); + } + ++ // 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. ++ if (NativeModuleEnv::Exists("_third_party_main")) { ++ return StartExecution(env, "internal/main/run_third_party_main"); ++ } ++ + if (env->worker_context() != nullptr) { + return StartExecution(env, "internal/main/worker_thread"); + } diff --git a/src/patch/16.16.0/run_third_party_main.js.patch b/src/patch/16.16.0/run_third_party_main.js.patch new file mode 100644 index 0000000..e92efb4 --- /dev/null +++ b/src/patch/16.16.0/run_third_party_main.js.patch @@ -0,0 +1,16 @@ +--- /dev/null 2022-08-18 11:11:24.665352687 -0500 ++++ lib/internal/main/run_third_party_main.js 2022-08-26 13:55:53.482283827 -0500 +@@ -0,0 +1,13 @@ ++'use strict'; ++ ++const { ++ prepareMainThreadExecution ++} = require('internal/bootstrap/pre_execution'); ++ ++prepareMainThreadExecution(); ++markBootstrapComplete(); ++ ++// Legacy _third_party_main.js support ++process.nextTick(() => { ++ require('_third_party_main'); ++}); diff --git a/src/util.js b/src/util.js index 2c8f12c..3d7260c 100644 --- a/src/util.js +++ b/src/util.js @@ -5,6 +5,7 @@ const { join, dirname } = require('path'); const { promisify } = require('util'); const fs = require('fs'); const { URL } = require('url'); +const { pipeline } = require('stream'); const mkdirAsync = promisify(fs.mkdir); const copyFileAsync = promisify(fs.copyFile); @@ -78,6 +79,34 @@ function runCommand(command, args = [], cwd = undefined, env = undefined, verbos }); } +async function patchFile(file, patchFile) { + await new Promise((resolve, reject) => { + const proc = spawn( + 'patch', + [ + '-uN', + file + ], + { + stdio: [ + null, + 'inherit', + 'inherit' + ] + }) + .once('exit', code => { + if (code !== 0) return reject(new Error(`falied to patch file=${file} with patch=${patchFile} code=${code}`)); + return resolve(); + }) + .once('error', reject); + pipeline( + fs.createReadStream(patchFile), + proc.stdin, + err => err ? reject(err) : undefined + ); + }); +} + function fetch(url, headers) { return new Promise((resolve, reject) => { if (!url || url.length === 0) { @@ -225,5 +254,6 @@ module.exports = { mkdirp, rmrf, copyFileAsync, - renameAsync + renameAsync, + patchFile };