Skip to content

Commit

Permalink
js-eval: remove h>, simplify stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
caub committed Dec 28, 2020
1 parent 4437291 commit 2a072e8
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 157 deletions.
9 changes: 2 additions & 7 deletions .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,14 @@ on: [push, pull_request]

jobs:
build:

runs-on: ubuntu-latest

strategy:
matrix:
node-version: [10.x, 12.x]

steps:
- uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
- name: Tests
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
node-version: 15.x
- name: npm install and test
run: |
npm install
Expand Down
4 changes: 0 additions & 4 deletions .travis.yml

This file was deleted.

14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

82 changes: 0 additions & 82 deletions src/plugins/js-eval/jsEval.js

This file was deleted.

112 changes: 74 additions & 38 deletions src/plugins/js-eval/jsEvalPlugin.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,34 @@
const cp = require('child_process');
const crypto = require('crypto');
const { setTimeout } = require('timers/promises');
const babel = require('@babel/core');
const babelGenerator = require('@babel/generator').default;
const jsEval = require('./jsEval');
const processTopLevelAwait = require('./processTopLevelAwait');
const { transformPlugins } = require('./babelPlugins');

const helpMsg = `n> node stable, h> node --harmony, b> babel, s> node vm.Script, m> node vm.SourceTextModule, e> engine262`;

// default jseval run command
const CMD = ['node', '--no-warnings', '/run/run.js'];
const CMD_SHIMS = [
'node',
'-r',
'/run/node_modules/airbnb-js-shims/target/es2019',
'--no-warnings',
'/run/run.js',
];
const CMD_HARMONY = [
'node',
'--harmony',
'--experimental-vm-modules',
'--experimental-modules',
'--no-warnings',
'/run/run.js',
];

const jsEvalPlugin = async ({ mentionUser, respond, message, selfConfig = {} }) => {
if (!/^[nhbsme?]>/.test(message)) return;
const mode = message[0];
const helpMsg = `n> node stable, b> babel, s> node vm.Script, m> node vm.SourceTextModule, e> engine262`;

const timeoutMs = 5000;
const envs = {
e: 'engine262',
s: 'script',
m: 'module',
n: 'node-cjs',
b: 'node-cjs',
};

module.exports = async function jsEvalPlugin({
mentionUser,
respond,
message,
selfConfig = {},
}) {
const mode = message.charAt(0);

if (mode === '?') return respond((mentionUser ? `${mentionUser}, ` : '') + helpMsg);

if (!envs[mode]) return;

let code = message.slice(2);

const hasMaybeTLA = /\bawait\b/.test(code);
Expand All @@ -53,18 +53,56 @@ const jsEvalPlugin = async ({ mentionUser, respond, message, selfConfig = {} })
}

try {
const result = await jsEval(
code,
mode === 'e'
? 'engine262'
: mode === 's'
? 'script'
: mode === 'm'
? 'module'
: 'node-cjs',
selfConfig.timer || 5000,
mode === 'b' ? CMD_SHIMS : mode === 'n' ? CMD : CMD_HARMONY,
);
const name = `jseval-${crypto.randomBytes(8).toString('hex')}`;
const args = [
'run',
'-i',
'--rm',
`--name=${name}`,
`--net=none`,
`-eJSEVAL_ENV=${envs[mode]}`,
`-eJSEVAL_TIMEOUT=${timeoutMs}`,
'brigand/js-eval',
'node',
'--experimental-vm-modules', // used by m>
'--experimental-modules',
'--no-warnings',
'/run/run.js',
];

const timeoutCtrl = new AbortController();
let data = '';

const result = await Promise.race([
new Promise((resolve, reject) => {
const proc = cp.spawn('docker', args);

proc.stdin.write(code);
proc.stdin.end();

proc.stdout.on('data', (chunk) => {
data += chunk;
});

proc.stderr.on('data', (chunk) => {
data += chunk;
});

proc.on('error', reject);

proc.on('exit', (status) => {
if (status !== 0) {
reject(new Error(data));
} else {
resolve(data.trim());
}
});
}).finally(() => timeoutCtrl.abort()),
setTimeout(timeoutMs + 10, timeoutCtrl).then(() => {
cp.execSync(`docker kill --signal=9 ${name}`);
throw Object.assign(new Error(data), { reason: 'timeout' }); // send data received so far in the error msg
}),
]);

let clean = result.trim();

Expand Down Expand Up @@ -92,5 +130,3 @@ if (process.env.NODE_ENV !== 'test') {
});
});
}

module.exports = jsEvalPlugin;
29 changes: 12 additions & 17 deletions src/plugins/js-eval/run.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
const { Script, SourceTextModule, createContext } = require('vm');
const util = require('util');
const builtinModules = require('module').builtinModules.filter(
(a) => !/^_|\//.test(a),
(s) => !/^_|\//.test(s),
);
const { setTimeout } = require('timers/promises');

const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

// copied from https://github.com/devsnek/docker-js-eval/run.js
// code taken from https://github.com/devsnek/docker-js-eval/run.js

const inspect = (val) => {
try {
Expand Down Expand Up @@ -46,7 +45,7 @@ function exposeBuiltinInGlobal(name) {
});
}

const run = async (code, environment, timeout) => {
async function run(code, environment, timeout) {
switch (environment) {
case 'node-cjs': {
const script = new Script(code);
Expand All @@ -71,18 +70,14 @@ const run = async (code, environment, timeout) => {
throw new Error('Unable to resolve import');
});

const [error, result] = await Promise.race([
module.evaluate({ timeout }).then((r) => [null, r]),
delay(Math.floor(timeout * 1.5)).then(() => [
new Error('The execution timed out'),
null,
]),
const timeoutCtrl = new AbortController();
const result = await Promise.race([
module.evaluate({ timeout }).finally(() => timeoutCtrl.abort()),
setTimeout(Math.floor(timeout * 1.5), timeoutCtrl).then(() => {
throw new Error('The execution timed out');
}),
]);

if (error) {
throw error;
}

return inspect(result);
}

Expand Down Expand Up @@ -136,9 +131,9 @@ const run = async (code, environment, timeout) => {
default:
throw new RangeError(`Invalid environment: ${environment}`);
}
};
}

if (!module.parent) {
if (require.main === module) {
(async () => {
let code = process.argv[2];
if (!code) {
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/mdn/mdnPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ async function fixLanguage(origRes, lastRedirect) {

async function fixRedirect(res) {
const $ = cheerio.load(res.text);
const meta = $('meta[http-equiv="refresh"]').attr("content")
const reg = /url=\/l\/\?uddg=(.*)/
const meta = $('meta[http-equiv="refresh"]').attr('content');
const reg = /url=\/l\/\?uddg=(.*)/;
const match = meta.match(reg);
if (!match) {
return res;
Expand Down

0 comments on commit 2a072e8

Please sign in to comment.