Search code examples
javascriptfunctionimportscopesvelte

Is there a way to run JavaScript from a string in browser with imported libraries?


I have a function that lets me run a JavaScript function in the browser:

export async function executeFunction(data: LoadOutput, input: Record<string, any>): Promise<any> {
    let args = [];
    for (let param of data.functionTree[0].parameters) {
        let value = input[param.name];

        if(!value) {
            return undefined;
        }

        args.push(value);
    }

    let func = new Function('return ' + data.jsCode)();
    return await func.call(null, ...args);
}

It all works, but now I want to add more functionality by being able to use external libraries. I tried adding imports in the string but this didn't work and resulted in errors

There was an error: Module name, 'image-conversion' does not resolve to a valid URL.

Is there a way I can import external libraries? Preferably by not having to pass them as a parameter (That's what ChatGPT suggested but would require a massive refactor of my code)

Is there maybe a library that does the same thing as Function but lets me add external libraries to the scope?

For additional information: I'm using SvelteKit


Solution

  • I now managed to do it. I imported a library (I used lodash as an example for testing) and saved it into a const

    import lodash from 'lodash';
    const libraries = { lodash }
    

    I pass it into the Function call like this

    let func = new Function(...Object.keys(libraries), 'return ' + data.jsCode)(...Object.values(libraries));
    return await func.call(null, ...args);
    

    And now I can use lodash when calling a function from a string.

    Here is my testing example:

    "libraryTest": "function libraryTest(text: string): { result: string } {\n" +
        "    const result = lodash.toUpper(text);\n" +
        "    return { result };\n" +
        "}"