In node.js vm module, i can execute some javascript in another node.js process. What i want to achieve is being able to catch logs performed in the script runned by the vm.
For example i want to catch the "foobar" log:
var vm = require('vm')
vm.runInThisContext('console.log("foobar");', 'myfile.vm');
// how can i get the "foobar" log?
Thanks in advance
EDIT: The answer below works well, although there's a shorter version:
function captureStdout(callback) {
    var output = '', old_write = process.stdout.write
    // start capture
    process.stdout.write = function(str, encoding, fd) {
        output += str
    }
    callback()
    // end capture
    process.stdout.write = old_write
    return output
}
                You can just wrap console.log directly:
function hook_consolelog(callback) {
    var old_log = console.log;
    console.log = (function(write) {
        return function() {
            write.apply(console, arguments)
            callback.apply(null, arguments);
        }
    })(console.log)
    return function() {
        console.log = old_log;
    }
}
var result;
var unhook = hook_consolelog(function(v) {
    result = v;
});
console.log('hello');
unhook();
console.log('goodbye');
console.log('the result is ', result);
Since console.log simply calls process.stdout, another approach would be to capture the stdout events using a bit of wrapper magic like this:
var util = require('util')
function hook_stdout(callback) {
    var old_write = process.stdout.write
    process.stdout.write = (function(write) {
        return function(string, encoding, fd) {
            write.apply(process.stdout, arguments)
            callback(string, encoding, fd)
        }
    })(process.stdout.write)
    return function() {
        process.stdout.write = old_write
    }
}
var unhook = hook_stdout(function(string, encoding, fd) {
    util.debug('stdout: ' + util.inspect(string))
    if( string == 'foobar' ) { unhook(); }
});
                        Maybe it's better so just forward the current console to the newly created context object:
let contextObj = {
    console: console
};
                        I found another, IMHO simpler solution: we just need to overwrite the console.log() function inside the VM context to use the function from the outer context.
import { Script, createContext } from 'vm';
let contextObj = {
    console: {
        log: (...args) => {
            console.log(...args);
        }
    }
};
const vmContext = createContext(contextObj);
const script = new Script("console.log('hello from the other side');");
script.runInContext(vmContext);
Hope it helps anyone looking for a stupidly simple solution!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With