1

How do I load dynamic dependencies into an eval() call? (If at all possible)

I am trying to run a call to eval() using multiple functions but I can't seem to get it to work. ie:

function foo() {
    return bar;
}

function foo2() {
    return foo();
}

Ideally, what I want to work is:

eval("
    (function() { 
        function foo() {
            return bar;
        }

        return foo(); 
     }())
");

But I keep getting an error that foo is not defined.

I know that if foo() is defined in the html of my page, then I can use eval() to write a function that is basically foo2() and get the result I want:

eval("
    (function() { 
        return foo(); 
     }())
");

But I want to be able to change both functions and still be able to call foo2() which will always reference foo(). Is this possible? What are some ways I could get this working?

10
  • 4
    Why are you trying to use eval()? You may have heard this before, but its use is almost always discouraged. Commented Feb 17, 2017 at 23:21
  • 1
    eval is evil! Commented Feb 17, 2017 at 23:22
  • @HarrisWeinstein I have heard it before. I am using it to run user entered javascript and then evaluate it's return values. Basically a very simple programming contest like software without the contest part Commented Feb 17, 2017 at 23:23
  • 1
    @HarrisWeinstein I am also taking steps to make sure that the user entered JS will not be able to be sent to anyone else. The code a user writes isn't shareable unless they manually copy it. Commented Feb 17, 2017 at 23:25
  • 1
    "I can't seem to get it to work" - please post the exact code you are using, the input strings you are entering to be evaled, and the errors you are getting. Commented Feb 17, 2017 at 23:35

4 Answers 4

4

Try and type this into the textarea:

function hello(name) {
  alert("hello" + name);
}

Then func will be a reference to hello (func == hello). Then you can use func to test the testcases like it was hello for example.

var ta = document.getElementById("code");

function run() {
  var code = "(function() { return " + ta.value + "; })()"; // code that will return a reference to the function typed by the user
  
  var func = eval(code); // func will be the function the user typed in the textarea
  
  func("me"); // you can call it like you want
}
<textarea id="code"></textarea>
<button onclick="run()">Run</button>

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks! I ended up getting it working right before you posted. I really appreciate it though because I didn't know you could call functions outside the eval once they have been run through eval
@Chris eval will return the evaluated value of the code. Since the code will be an anounimous function that return a function, the return value of eval will be a reference to that function that you can use to test the test cases the way you want!
0

Yes, that is possible, just make sure that your evaled code overwrites the original functions with the new declarations, typically in the global scope.

3 Comments

I have tried pretty much any combination of adding 2 functions in a string form. usually I get an error "unexpected keyword 'function'" or something of the like. Does and eval call persist? i.e I call eval on a function, can I call that function outside the eval later? (possible through a call from another eval)
That sounds like a syntax error, from passing the wrong string. But yes, eval results persist, though of course the scope in which they get stored may vanish. eval("a = 1"); eval("alert(a)") works without problems.
I just realized I didn't try every possible combination. I kept leaving off the first '(' when building my eval query with 2 functions..........
0

try to use the syntax var foo = function(){} instead of function foo(){} in your eval, I don't know how you make multiline js string it doesn't exist, but an ";" beetween instruction for eval

2 Comments

Nah, that doesn't make any difference, though he needs to drop the IIFE
you code is working on my chrome it says bar is not defined but he use the new foo of the eval.
0

I know this is old, but I found a way to do it. You have to have \ at the end of each line and escape quotes:

var canvas = document.createElement('canvas')
canvas.id = 'dailyTotalUsersCreated';
canvas.setAttribute('class', `bar dailyChart`)
var container = document.querySelector(`#daily`)
container.appendChild(canvas)
eval(` \
    var ${canvas.id} = new Chart('${canvas.id}', { \
        type: 'bar', \
        data: { \
            labels: [${lastSevenDays.map(obj => `"${new Date(obj.Date).toDateString()}"`)}], \
            datasets: [
                { \
                    label: 'Total Voice Users Created', \
                    data: [${lastSevenDays.map(obj => `${obj.Values.filter(obj => { return obj.Name === "Users Created" }).map(obj => totalUsersCreated - obj.Value)}`)}], \
                    backgroundColor: ['#3e95cd','#8e5ea2','#3cba9f','#e8c3b9','#c45850','#facb48','#384d3f','#247BA0','#F3FFBD','#FF1654'], \
                } \
            ] \
        }, \
        options: { \
            plugins: { \
                datalabels: { \
                    labels: { \
                        title: { \
                            color: 'black' \
                        } \
                    } \
                } \
            }, \
            scales: { \
                yAxes: [{
                    stacked: false,
                    gridLines: {
                        display: true,
                        color: "rgba(255,99,132,0.2)"
                    },
                    ticks: {
                        beginAtZero: true
                    }
                }]
            } \
        } \
    }); \
`);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.