How to lie to program about `process.platform`?

99封情书 提交于 2019-12-24 12:55:00

问题


There is a CLI that runs on Node and can be executed via command on the command line. In its code, some functionality is deactivated for Windows users by if (process.platform === 'win32') { process.exit(1); }. Now I want to disable this check, and allow Windows users to use the "hidden" functionality (usually the the required software is not installed on Windows, but I have a special setup where it is).

Is there some way, to lie to this CLI and simulate that it is running on e.g. Linux or macOS?

Of course I could fork the CLI, remove the check and work with my own version - but this would require repeating this process for each release. As this functionality should also be available to other users, I would have to publish the forked and modified CLI which could be a frequent source of confusion for its users (What about version numbers? Do I use the same command?) - 99.9% of the code will stay untouched.

Could I maybe write my own CLI, that does something to "fake" the environment, then executes the installed, original CLI, and cleans up afterwards?


I created an example package that works identical to the CLI, but only does exactly that part that I am investigating:

  • https://github.com/janpio/nodejs-cli-nowin
  • https://www.npmjs.com/package/nodejs-cli-nowin

Install via npm i -g nodejs-cli-nowin.


回答1:


Basically, wrapper package should be used to provide entry point instead of original package. process.platform should be mocked with new value before original package runs.

wrapper-package/index.js

Object.defineProperty(process, 'platform', { value: 'linux' });

require('original-package/bin/entry-point.js');

This won't affect child processes if original package spawns them.

This doesn't guarantee that the package will work as intended with mocked platform, there's a good chance that it won't. Even if the package itself works correctly, this may result in unpredictable behaviour in package dependencies that rely on process.platform.

In order to affect process.platform only for specific module, platform global should be shadowed with local variable. To do this, module wrapper function should be modified:

const Module = require('module')

const escapedPatchedModulePath = require.resolve('original-package/module-to-patch.js')
  .replace(/\\/g, '\\\\');

Module.wrapper[0] += `
const isPatchedModule = __filename === "${escapedPatchedModulePath}";
let process = isPatchedModule
  ? Object.create(global.process, { platform: { value: 'linux' } })
  : global.process;
`;

require('original-package/bin/entry-point.js');


来源:https://stackoverflow.com/questions/54374379/how-to-lie-to-program-about-process-platform

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!