Search code examples
javascripttypescriptimportevaljavascript-import

Access imported functions from evaled code


I have a TypeScript file with the following code:

import { functionTest } from './function_test'

function runnerFunctionTest() {
    console.log("Test");
}

export class Runner {
    run(source : string) {
        eval(source);
    }
}

If I instantiate a Runner and call run("runnerFunctionTest();") the function runs correctly, but if I call run("functionTest();") (which should run the imported function) I get an error saying functionTest is undefined.

How can I fix this?

One thing I tried was replacing the code in run with new Function('functionTest', source).(functionTest); which worked but it will be really annoying to have to add all the imported functions like that - there are around 20 of them and that number will only increase as time goes on.

Also, I am aware of the security implications of calling eval - it is the only way (at least that I know of) to do what I want, which is running arbitrary JavaScript code generated by the user in the user's browser.


Solution

  • Because import is not a native operator, webpack (or something else) transform it for you. After compiled by webpack, you code becomes:

    /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Runner", function() { return Runner; });
    /* harmony import */ var _function_test__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2);
    
    function runnerFunctionTest() {
        console.log("Test");
    }
    
    class Runner {
        run(source) {
            eval(source);
        }
    }
    

    The name functionTest is not existed anymore, that why you can't eval it.

    One possible solution is to give it a local name:

    import { functionTest } from './function_test'
    const function_test = functionTest;
    function runnerFunctionTest() {
        console.log("Test");
    }
    
    export class Runner {
        run(source : string) {
            eval(source);
        }
    }
    

    Then you can run runner.run('function_test()')