1

I get Js as a string and I need to execute that script and compare the output to something. I'm using eval() here but can be anything. It runs on client side in the browser.

Is there any way to do this without changing the string a?

let a = "console.log(\"a\")";
eval(a);
let stdout = ???
Fee
  • 719
  • 9
  • 24
  • 1
    Never use eval(): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#never_use_eval! – Emil Karlsson Aug 18 '22 at 10:06
  • "Is there any way to do this without changing the string a?" why do you need to change that? – GrafiCode Aug 18 '22 at 10:14
  • 1
    `"Without changing a"`, I guess you want to keep `console.log` in the string, but will have to change the actual `console.log` function. But that may affect unrelated parts of the program. – qrsngky Aug 18 '22 at 10:17
  • 1
    Does this answer your question? [How to read from Chrome's console in JavaScript](https://stackoverflow.com/questions/19846078/how-to-read-from-chromes-console-in-javascript) – albjerto Aug 18 '22 at 10:18
  • The "output" (i.e return value) of the script in the string is `undefined`. That's what `eval()` will return to you. – Kaiido Aug 18 '22 at 11:14

3 Answers3

2

Using:

  • bind()
  • call()

you can extend console.log so that an additonal, separate live record is kept of all the log entries.

In the working example below, you can see that every time something is logged to the console, it is simultaneously added to the console.stdout array.


Working Example:

console.stdout = [];
console.logInclStdout = console.log.bind(console);

console.log = (logEntry) => {
    console.stdout.push(logEntry);
    console.logInclStdout.call(console, logEntry);
}


let a = "console.log('a')";
let b = "console.log('b')";
let c = "console.log('c')";

let saferFasterEval = (input) => Function(`"use strict"; ${input}`)();

saferFasterEval(a);
saferFasterEval(b);
saferFasterEval(c);

// When you want to see what has been logged via console.log
console.info(console.stdout);
Rounin
  • 27,134
  • 9
  • 83
  • 108
1

If you want to save the messages executed with console.log inside the eval one way would be to overwrite the console.log however I would not recommend overwriting or using eval

// Store the original console.log function
const temp = console.log;

// Create an array to hold the commands
const cmds = []

// Overwrite the console.log to store the logs
console.log = (msg) => { cmds.push(msg) };

// Run A
let a = "console.log(\"a\")";
eval(a);

// Run B
let b = "console.log(\"b\")";
eval(b);

// Run C
let c = "console.log(\"c\")";
eval(c);

// Get the logs; You can use `cmd.join('\n')` to get the messages as a string
let stdout = cmds;

// Revert to orignal console.log
console.log = temp

Example: https://jsfiddle.net/x0w2q4Le/4/

TryingToImprove
  • 7,047
  • 4
  • 30
  • 39
0

Eval returns the output if you pass it to a variable:

let a = `
    let test = 10
    test++
    test
`
let stdout = eval(a)

Just put the value you want to return at the end

Shiedix
  • 58
  • 5