0

I currently have two files:

file1.js

class helper {
    static wrap(code) {
        eval(`console.log("start"); ${code} console.log("stop");`);
    }
}

file2.js

import { helper } from "./file1.js"; //(using typescript on nodejs)

function somethingCool() {
    console.log("middle");
}
helper.wrap("somethingCool();");

This will not work because somethingCool is not in the scope of file1. Is there anyway to get the eval to use the scope of where the function was called as opposed to the local scope?

The only way I have come up with is to pass an anonymous function as an anchor like this:

helper.wrap("somethingCool();", (val) => eval(val));

but that isn't very clean looking and would require the end developer to constantly add that anchor.

Nick Frev
  • 115
  • 1
  • 7
  • I don't know if this is helpful but you can do something like this: `helper.wrap(\`(${somethingCool.toString()})()\`)`. This won't work if inside `somethingCool` you use any variables from the outer scope. – Titus Jun 30 '23 at 23:53
  • You should instead pass `somethingCool` as a callback to `.wrap()` and also enclose preceding/succeeding code in functions. This helps avoiding the use of `eval()` and, in general, makes code more readable/maintainable. If you also need scope injecting, pass an object of arguments to those functions. – InSync Jul 01 '23 at 01:07
  • Sadly the issue is that I don't know what `somethingCool` might be, it could be anything in that current scope. In the real code that I'm writing I'm trying to reference a class using it's classname with eval. I have a "registerClass" function that I've been using but it would be easier for the end developer to not have to register every class that might be used. I'm trying to make my code as minimally impactful as possible to reduce boilerplate code. – Nick Frev Jul 01 '23 at 01:49
  • If you [don't use `eval` but `new Function`, you can more or less easily inject arbitrary values in the scope of the code](https://stackoverflow.com/a/24032179/1048572) - and give the caller control over those. Is that what you want? It would require changing the call to something like `helper.wrap("somethingCool();", {somethingCool})` though. – Bergi Jul 01 '23 at 04:46
  • That's a really good solution @Bergi, it doesn't fully solve my issues but it lead me down a google search that has me realizing the reason what I want to do is so difficult is because it's considered a security issue ["walking the stack"](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/caller). I think any solution I find is going to require me to abandon the syntax I am after. – Nick Frev Jul 01 '23 at 07:08
  • It's not necessarily a security issue, but few languages do [dynamic scoping](https://en.wikipedia.org/wiki/Scope_(computer_science)#Dynamic_scope) because it's rather messy and confusing – Bergi Jul 01 '23 at 13:03

0 Answers0