JavaScriptアプリケーションでJavaScriptをスクリプト言語として使用できるようにしたいと考えています。そのためには、ソースコードを動的に実行する必要があります。動的に実行する/ eval ES6モジュールを含むJavaScriptコード/いくつかの依存関係が必要ですか?
動的にJavaScriptを実行するための2つの主要なオプションがあるように思える:
A)eval(...)
法(またはvar func = new Function(...);
)を使用します。
b)DOMに<script>
ノードを追加します(たとえば、$('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);
スクリプトの種類を指定しないか、オプションb)にtype="application/javascript"
を使用すると、Unexpected identifier
というエラーが発生します。 type="module"
を使用してもエラーは発生しません。 scriptタグは正常に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。ユーザーソースコードで動的に解決できる依存関係を定義できるようにするにはどうすればよいでしょうか?
関連の質問と記事:
https://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/#safely-sandboxing-eval
https://javascriptweblog.wordpress.com/2010/04/19/how-evil-is-eval/
How do I include a JavaScript file in another JavaScript file?
How to import es6 module that has been defined in <script type="module"> tag inside html?
私は例のワークフロー、使用して、window.createTreeModel
が理想的ではないことを知っています。コードは分かりやすいのでここで使用しました。すべての作業フローを改善し、セキュリティ問題のようなものについて考えてみましょう...私はどうにかしてその依存関係を含むユーザーソースコードを実行するように管理しました。
トランスファーを使用してください。エクスポートに 'window'を使用せず、' export'宣言を使用してください。そして、特に動的に依存関係を読み込んでいるときは、コード評価が非同期になる可能性があるので注意してください。 – Bergi
@Bergi:モジュールコードが実行されていない限り、エクスポートは機能しません。 「その他の注意事項」も参照してください。私はローディングが完了するのを待つことができたが、それは役に立たなかった。私は非同期読み込みを考慮した例を使って質問を更新しました。私は、蒸散器が私の問題を解決できるかどうかの例を教えてください。 – Stefan
@Stefan彼は、トランスバータを使ってES6コードをES5にコンパイルし、次にES5コードを実行することを意味します。私はブラウザで動作する蒸散器は認識していません。ほとんどの場合、PCでコンパイルし、ブラウザにのみES5コードをデプロイします。 – slebetman