2

I am trying to replicate what leetcode does, as my React learning project. Below is my current UI setup.

I am using AceEditor as my text editor, right now I can read the value from the editor on change.

I want to execute the function containsDuplicate when I click the Run code button.

What I have right now is a string codeValue represent the user's input in the string format, and the testCase as the functions params in the string format as well,

  // the codeValue is the complete text in the Ace Editor are
  const [codeValue, setCodeValue] = useState('');

  // The testCase is [1,2,3,1] which reads from the TestCase section
  const [testCase, setTextCaseValue] = useState('');

  const submitHandler = (inputParams) => {
    console.log(codeValue); 
  };

What should I do to run the function containsDuplicate with the params testCase ? Assume the function name is always containsDuplicate?

Eval() will run the string as JS function, but what I need is, when the string is just function declaration, and there are multiple function declarations, I need to find the correct function from string, and run that function with give input.

Let's say the input string is

functionA() {
  functionB();
}

functionB() {
}

I need to read that string and run functionA([1,2,3,4])

I don't have a good way to do this right now.

Thanks!

enter image description here

Xinrui Ma
  • 2,065
  • 5
  • 30
  • 52
  • You can use [`eval()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval) for that. –  Sep 20 '21 at 07:12
  • But the input string can contains multiple functions, and I want to execute only one function inside the user's input string – Xinrui Ma Sep 20 '21 at 07:13
  • You have to call the function yourself anyway. You need `eval(codeValue);` to run the function definition code, then `containsDuplicate(...);`. –  Sep 20 '21 at 07:15
  • I was going to suggest `eval()` too, but the MDN site claims it should be used with caution here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#never_use_eval! I guess for learning purposes will be fine – Ricardo Sanchez Sep 20 '21 at 07:16
  • @RicardoSanchez It should be used with caution, yes. –  Sep 20 '21 at 07:16
  • 1
    [Why is using the JavaScript eval function a bad idea?](https://stackoverflow.com/questions/86513/why-is-using-the-javascript-eval-function-a-bad-idea). Whenever possible, avoid using `eval`. – Cerbrus Sep 20 '21 at 07:18
  • 1
    The problem here is that you have no idea what users are going to put into that text area. This means you can't reliably extract a function, without parsing / interpreting the _whole_ text as JavaScript. Ideally, you'd be running the text in a sandbox, from which you can then somehow extract the function, but this isn't exactly a "trivial" issue to solve. – Cerbrus Sep 20 '21 at 07:21
  • @Cerbrus That's correct, user can define multiple functions in the textarea, and I need a way, somehow to read that entire string, let my code understand all the function declaration in it, and be able to run the main function in it. – Xinrui Ma Sep 20 '21 at 07:23
  • Have a look at the answers [here](https://stackoverflow.com/questions/6588977/how-to-to-extract-a-javascript-function-from-a-javascript-file) to get an idea of how __very__ complicated parsing like that is. – Cerbrus Sep 20 '21 at 07:26

1 Answers1

7

If the function name is fixed*, you can "extract" the right function by wrapping the user code into yet another function and simply return that function from it:

const codeInput = `
function foo() {
  console.log('foo');
}
function containsDuplicate(input) {
  foo();
  console.log('input', input);
  return 42;
}
`;
const code = new Function(codeInput + '; return containsDuplicate;')()
const result = code([1,2,3]);
console.log('result', result);

You can also add additional logic that verifies that containsDuplicate exists before trying to return it.


If you don't want to dictated the function name, there a couple of solutions, more or less complicated:

  • You can provide a small CommonJS like wrapper and have the user assign the function to module.exports.
  • If you wanted to allow ES module syntax, you could use a bundler like https://rollupjs.org and run it in the browser to convert the code into something runnable for you (you would still have to eval/new Function it) (there might also be lighter solutions for just convert ES module syntax to e.g. an IIFE).

*: Which is a reasonable assumption to make IMO. Since it's a special purpose environment you can dictate the structure of the code and require that there has to be a function with a specific name.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143