0

I will like my vue application to transform the following string:

const test = 'import { pi } from "MathPie"; function test() { console.log(pi); } export default test;'

into a function that I could call.

import { pi } from "MathPie";

function test() {
  console.log(pi);
}

export default test;

I already tried using eval (even if it's evil), but it doens't work because import statement aren't supported by it.

eval(test)()
> Cannot use import statement outside a module
> Should log '3.14159'

The snippet is for presentation only, I'm aware of Math.PI

My question is how I can evaluate a string with import statement?

marcXandre
  • 2,072
  • 2
  • 13
  • 21
  • 4
    This feels like an XY problem: why would you want to evaluate an arbitrary string? – Terry Dec 23 '21 at 20:49
  • Generally, you can't use module exports outside of a module unless at least one of those module exposes the exports to the global scope (e.g.: `window.test = test;`). Generally, you can't `import` inlined modules so injecting a string as an inline module doesn't really get you anywhere (though [this answer](https://stackoverflow.com/a/43834063/367865) might offer a path forward). – Ouroborus Dec 23 '21 at 21:30
  • You can't do that. `MathPie` is likely NPM package, while a browser is clueless about node_modules, native ESM support can't handle them. – Estus Flask Dec 24 '21 at 07:42

1 Answers1

2

In your case, you can use a combination of dynamic import() together with createObjectURL().

A test example is below:

(async() => { // <= if you don't support top level await.
  const jsCode = `
export default function defaultTest() { console.log('this is default test func'); };
export function primaryTest() { console.log('this is primary test func'); };
export function secondaryTest() { console.log('this is secondary test func'); };`;

  const blobData = new Blob([jsCode], {
    type: 'text/javascript'
  });
  const url = URL.createObjectURL(blobData);
  const {
    "default": defaultTest,
    primaryTest,
    secondaryTest
  } = await import(url);
  
  defaultTest();
  primaryTest();
  secondaryTest();
})()
Oleg Barabanov
  • 2,468
  • 2
  • 8
  • 17