new Function() return last value?

194 views Asked by At

How do I return the last value from the new Function() constructor? Seems eval() does this by default, as well as vm.Script#runInContext.

I just want to create a REPL in the browser (where I can do something like 2+2; and it returns 4 in the output) like eval, but without the drawbacks of eval (local function scope access, AsyncFunction, etc...)

2

There are 2 answers

0
Cobertos On

There is no way to do this.

new Function() does not provide any way to access the "Completion Records" of it's invocation, according to the ECMAScript specification part on Function objects.

So if you need the last value, you have to use eval()

1
Vadim On

You can use Web Worker to run something in isolated scope. There you can safely use eval without worrying about access to local scope variables of your page. Try something like this:

function run() {
  const code = `
  self.onmessage = async (evt) => {
    let result;
    try {
      result = await eval(evt.data);
    } catch(err) {
      result = 'Error: ' + err.message;
    }  
    self.postMessage(result);
  };
  `;
  const blob = new Blob([code], {
    type: "text/javascript"
  });
  const worker = new Worker(window.URL.createObjectURL(blob));
  worker.onmessage = function(e) {
    document.getElementById('out').value = e.data;
  }
  worker.postMessage(document.getElementById('repl').value);
}
<label for="repl">REPL:</label>
<input type="text" id="repl">
<button onclick="run()">Execute</button>
<p/>
<label for="out">Output:</label>
<input type="text" id="out" readonly>

Inspired by this answer :)