Как динамически выполнять / оценивать код JavaScript, который содержит модуль ES6 / требует некоторых зависимостей?
Я хочу, чтобы мои пользователи могли использовать JavaScript в качестве языка сценариев внутри моего приложения JavaScript. Для этого мне нужно динамически выполнить исходный код.
Кажется, есть два основных варианта динамического выполнения JavaScript:
а) использовать eval(...)
метод (или var func = new Function(...);
)
б) Добавить <script>
узел к DOM (например, с помощью $('body').append(...)
) .
Оба метода работают нормально, пока я не использую import
операторы в динамически выполняемом исходном коде. Если я включу import
заявления я получаю сообщение об ошибке Unexpected identifier
,
Пример исходного кода пользователя для выполнения:
import Atom from './src/core.atom.js':
window.createTreeModel = function(){
var root = new Atom('root');
root.createChildAtom('child');
return root;
}
Пример кода приложения для иллюстрации возможного использования этого динамического кода:
а) Использование eval
var sourceCode = editor.getText();
window.createTreeModel = undefined;
eval(sourceCode);
var model = window.createTreeModel();
treeView.setModel(model);
б) Использование модификации DOM:
var sourceCode = editor.getText();
window.createTreeModel = undefined;
var script = "<script >\n"+
sourceCode + "\n" +
"</script>";
$('body').append(script);
var model = window.createTreeModel();
treeView.setModel(model);
Если я не укажу тип сценария или использовать type="application/javascript"
для варианта б) я получаю Unexpected identifier
ошибка. Если я использую type="module"
Я не получаю ошибки. Тег сценария успешно добавлен в DOM, но код модуля не выполняется.
Сначала я подумал, что это может быть связано с асинхронной загрузкой. Однако ожидание завершения загрузки тега сценария не работало с type='module'
, Механизм загрузки работает с type="application/javascript"
но затем снова... import
не работает.
Пример кода для асинхронного выполнения после загрузки тега скрипта:
function loadScript(sourceCode, callback){
// Adding the script tag to the head as suggested before
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'application/javascript';
script.innerHTML = sourceCode;
//script.async=false;
// Then bind the event to the callback function.
// There are several events for cross browser compatibility.
script.onreadystatechange = callback;
script.onload = callback;
// Fire the loading
head.appendChild(script);
}
-
loadScript(sourceCode, function(){
var model = window.createModel();
console.log('model:' + model);
});
Если я жестко закодирую исходный код пользователя в моем index.html, используя <source type="module">
код модуля выполнен. Динамическая загрузка кода модуля, похоже, не работает. Я использую Chrome версии 63.0.3239.108.
=> I. Как я могу форсировать исполнение <script type="module">
тег после динамического добавления его в DOM? или же
=> II. Как я могу оценить скрипт, который содержит import
(и, возможно, экспорт) заявления? или же
=> III. Что может быть хорошим способом разрешить пользовательскому исходному коду определять зависимости, которые могут быть разрешены динамически?
Связанные вопросы и статьи: