0

I need to evaluate JavaScript expressions, in a browser, Chrome. To make it safe, I use a Blob and a Worker running my evaluator, until it posts back the result of a timeout cancels the wait. This is working fine. I also need to support an environment for my JavaScript. I do this as below:

function evalWorker () {
  let postResponse = function(expr, ...) {
    let presets = `var EnvObject = {};
                EnvObject.platform = "Chrome";
                EnvObject.pasteboard = "${clipboard}";
                EnvObject.baseDate = new Date();
                ...
                EnvObject._output = "";
                EnvObject.appendOutput = (str) => {EnvObject._output += str; };
                `
    postMessage(eval(presets + expr));
  };
  onmessage = function(e) {
    postResponse(e.data['expression'], e.data['clipboard'], ...);
  }
}

My problem is that if _output is not empty, I need to return that - _output instead of the evaluated expression, as in

EnvObject.appendOutput('hello');
var a = 0;
++a;

Should return hello; while without appendOutput, it should return 1.

How would I go about something like this?

Moshe Shmukler
  • 1,270
  • 2
  • 21
  • 43
  • `postMessage(selectValue(eval(expr), EnvObject._output))`? – Bergi Dec 05 '17 at 00:00
  • Evaluating arbitrary code in a worker is not safe at all. What makes you think the code is run in a sandboxed environment? – Derek 朕會功夫 Dec 05 '17 at 00:00
  • EnvObject lives within the expression, right? It would be `undefined`. – Moshe Shmukler Dec 05 '17 at 00:01
  • why would worker running in a blob be unsafe? – Moshe Shmukler Dec 05 '17 at 00:04
  • @MosheShmukler What are you trying to defend against? https://stackoverflow.com/q/16600607/1048572 – Bergi Dec 05 '17 at 00:09
  • @MosheShmukler No, `EnvObject` does not "live within the expression". It either lives in the global scope or in the local scope of `postResponse`, it should in any case be available there. – Bergi Dec 05 '17 at 00:10
  • @MosheShmukler It can make same origin requests, modify your local storage and probably even cookies. Think of workers as a separate thread that has access to everything except the DOM. – Derek 朕會功夫 Dec 05 '17 at 00:21
  • @Bergi you are wrong. `EnvObject` is not going to be defined anywhere outside the expression being evaluated. As far as `postResponse()` aware `EnvObject` is text. @Derek朕會功夫 `Blob`/`Worker` provide safety from damaging the executing process. That works for me. Let me know if you have ideas regarding my question. – Moshe Shmukler Dec 05 '17 at 06:59
  • 1
    @MosheShmukler Ah, in strict mode the `eval` creates its own scope. So either use global eval, or sloppy mode, or simply declare `var EnvObject` before the `eval` call in the function scope. – Bergi Dec 05 '17 at 09:32

1 Answers1

0

@Bergi had the right idea with pushing the scope out. The below works.

function evalWorker () {
  let postResponse = function(expr, TextExpander) {
    let result = eval(expr);
    if (EnvObject._output && EnvObject._output.length) {
      postMessage(EnvObject._output);
    } else {
      postMessage(result);
    }
  };
  onmessage = function(e) {
    var EnvObject = {};
    EnvObject.platform = "Chrome";
    EnvObject.pasteboardText = e.data['clipboard'];
    ...
    EnvObject._output = "";
    EnvObject.appendOutput = function(str) {EnvObject._output += str; };
    postResponse(e.data['expression'], EnvObject);
  }
}
Moshe Shmukler
  • 1,270
  • 2
  • 21
  • 43