我希望我的用户能够在我的 JavaScript 应用程序中使用 JavaScript 作为脚本语言。为此,我需要动态执行源代码。
动态执行 JavaScript 似乎有两个主要选项:
a) 使用eval(...)
方法(或var func = new Function(...);
)。
b)<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;
}
示例应用程序代码来说明该动态代码的可能用法:
a) 使用评估
var sourceCode = editor.getText();
window.createTreeModel = undefined;
eval(sourceCode);
var model = window.createTreeModel();
treeView.setModel(model);
b) 使用 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"
如果我没有为选项 b) 指定脚本类型或使用,我会收到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。
<script type="module">
=> I.动态添加到 DOM 后如何强制执行标签?或者
=> 二。如何评估包含import
(可能还有导出)语句的脚本?或者
=> 三。允许用户源代码定义可以动态解析的依赖关系的好方法是什么?
相关问题和文章:
https://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/#safely-sandboxing-eval
https://javascriptweblog.wordpress.com/2010/04/19/how-evil-is-eval/
进一步说明:
我知道使用示例的工作流程window.createTreeModel
并不理想。我在这里使用它是因为代码易于理解。在我设法以某种方式运行用户源代码(包括其依赖项)之后,我将改进我的所有工作流程并考虑诸如安全问题之类的问题。