Ste*_*fan 6 javascript eval dynamic-execution es6-modules
我希望我的用户能够在我的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;
}
Run Code Online (Sandbox Code Playgroud)
示例应用程序代码,用于说明该动态代码的可能用法:
a)使用eval
var sourceCode = editor.getText();
window.createTreeModel = undefined;
eval(sourceCode);
var model = window.createTreeModel();
treeView.setModel(model);
Run Code Online (Sandbox Code Playgroud)
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);
Run Code Online (Sandbox Code Playgroud)
如果我没有指定脚本类型或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);
}
Run Code Online (Sandbox Code Playgroud)
-
loadScript(sourceCode, function(){
var model = window.createModel();
console.log('model:' + model);
});
Run Code Online (Sandbox Code Playgroud)
如果我使用index.html对用户源代码进行硬编码<source type="module">,则执行模块代码.动态加载模块代码似乎不起作用.我使用Chrome版本63.0.3239.108.
=> I.如何在将<script type="module">标签动态添加到DOM后强制执行标签?要么
=> II.如何评估包含import(也可能是导出)语句的脚本?要么
=> III.允许用户源代码定义可以动态解析的依赖项的好方法是什么?
相关问题和文章:
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并不理想.我在这里使用它因为代码很容易理解.我将改进我的所有工作流程并考虑安全问题之类的东西......在我以某种方式管理用户源代码(包括其依赖项)之后.
小智 9
使用数据 uri 或 objectUrls 和动态导入:
const code = 'export default function hello() { console.log("Hello World"); }';
const dataUri = 'data:text/javascript;charset=utf-8,' + encodeURIComponent(code);
const module = await import(dataUri);
console.log(module); // property default contains function hello now
const myHello = module.default;
myHello(); // puts "Hello World" to console
Run Code Online (Sandbox Code Playgroud)
const code = 'export default function hello() { console.log("Hello World"); }';
const objectURL = URL.createObjectURL(new Blob([code], { type: 'text/javascript' }));
const module = await import(objectURL);
console.log(module); // property default contains function hello now
const myHello = module.default;
myHello(); // puts "Hello World" to console
Run Code Online (Sandbox Code Playgroud)
导入在我的测试中起作用,只是如果您使用相对路径,您可能必须更改目录更改前缀(如 ./ 或 ../),但由于您必须首先以文本形式编码,所以您只需先将其替换为正则表达式效仿。
| 归档时间: |
|
| 查看次数: |
1404 次 |
| 最近记录: |