I'm making a dynamic system that needs to execute JS code that is generated on the fly in a browser app (Edge or Chrome latest). From another example I've gotten this far:
async function doIt()
{
let code = "";
code += "import { MyClass } from './MyClass.js' ;\n";
code += 'export default function hello() { console.log( "Hello World" ); console.log( MyClass.test() ); }';
const dataUri = 'data:text/javascript;charset=utf-8,' + encodeURIComponent(code);
let module = await import(dataUri);
console.log(module); // property default contains function hello now
const myHello = module.default;
myHello(); // puts "Hello World" to console
}
Where MyClass.js has a trivial ES6 module class:
export class MyClass {
static test() { return 42; }
}
When I run the doIt() function without the second line with the import statement, it runs fine until it tries to call MyClass.test() which is unknown then, of course. With the 2nd import line enabled, it gives the error in Edge or Chrome:
"Uncaught TypeError: Failed to resolve module specifier './MyClass.js'.
Invalid relative url or base scheme isn't hierarchical."
I've tried to make an absolute path of the module reference, but the error remains the same. . So, how to make this work? Or maybe an alternative solution? But using ES6 modules is a hard requirement.
To answer my own question: import() seems to be somewhat crippled, but a workaround is to place the desired dynamic JavaScript in the innerHTML of a new temporary script node in the current HTML page. From there, the ES6 import statements are executed just fine:
var script = document.createElement( "script" );
script.setAttribute( 'type', 'module' );
script.innerHTML = 'import { MyClass } from "/App/MyClass.js"; \
someGlobalVar = MyClass.test();
Since it is running at the global scope, you need to store results in some global object. It could be refined by implementing a callback function on an object instance, but I leave that as an excercise for the reader. :-)