JS-Interpreterの勉強メモ


JS-Interpreterとは、JavaScriptで記述するサンドボックス化されたJavaScriptインタープリターです。Javascriptコードを実行する時には、任意のJavaScriptコードを1行ずつ実行に行きます。JavaScript環境から完全に分離されています。JS-Interpreterのインスタンスが複数に作られた場合は、Web稼働環境(ブラウザーなんとか)を使用せずに複数のJavaScriptコード同時にマルチスレッドで実行することが可能です。

環境準備

以下の2つのJavaScriptソースファイルをインポートします。

<script src="acorn.js"></script> 
<script src="interpreter.js"></script>

または、圧縮バンドルを使用します。

<script src = "acorn_interpreter.js"> </ script>

使い方1:外部API無し

外部APIが使わない場合は、JS-Interpreterの初期化関数を使用せずに、インスタンスを作ります。
Javascriptコードをステップごとに実行するには、step関数をfalseを返すまでに繰り返し呼び出します。
コードがが無限ループではなく安全なコードだって言うことが分かれば、run関数を1回のみ呼び出してコードを最後までに実行することが構わないです。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Blockly Demo: Step Execution with JS Interpreter</title>
  <script src="acorn_interpreter.js"></script>
</head>
<body>
    <button onclick="runCode()" id="runButton">Run JavaScript</button>
    <button onclick="stepCode()" id="stepButton">Step JavaScript</button>
 <script>
    var runButton = document.getElementById('runButton');
    var stepButton = document.getElementById('stepButton');
    var myInterpreter = null;
    var myCode = 'var a=1; for(var i=0; i<4; i++ ){a=a*i;};';
    myInterpreter = new Interpreter(myCode);
    function stepCode() {
        if(this.myInterpreter.step()){
            window.setTimeout(stepCode,0);
        }
    }
    function runCode() {
        myInterpreter.run();
    }
</script>
</body>
</html>

使い方2:外部APIあり(標準Javascriptコードの場合)

外部APIが使った場合は、JS-Interpreterの初期化関数を利用してインスタンスを作ります。
ただし、例えば、外部APIがalertようなJavascriptの標準コードであれば、JS-Interpreterの初期化関数を作成する時には、Javascriptのコードを定義することが必要だけです

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Blockly Demo: Step Execution with JS Interpreter</title>
  <script src="acorn_interpreter.js"></script>
</head>
<body>
    <button onclick="runCode()" id="runButton">Run JavaScript</button>
    <button onclick="stepCode()" id="stepButton">Step JavaScript</button>
 <script>
    var runButton = document.getElementById('runButton');
    var stepButton = document.getElementById('stepButton');
    var myInterpreter = null;
    var myCode = 'var a=1; for(var i=0; i<4; i++ ){a=a*i;alert(i);};';
    //初期化関数
    var initFunc = function(interpreter, scope) {
        var wrapper = function(text) {
            return alert(text);
        };
        interpreter.setProperty(scope, 'alert', interpreter.createNativeFunction(wrapper));     
    };
    myInterpreter = new Interpreter(myCode, initFunc);
    function stepCode() {
        if(this.myInterpreter.step()){
            window.setTimeout(stepCode,0);
        }
    }
    function runCode() {
        myInterpreter.run();
    }
</script>
</body>
</html>

使い方2:外部APIあり(関数が自分定義した場合)

外部APIがJavascriptの標準コードではなく、自分で定義した関数を実行する場合には、JS-Interpreterの初期化関数を作成する時に、自分の関数を定義することが必要で、さらに、この関数の処理の詳細も記述する関数も定義しないと行けません

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Blockly Demo: Step Execution with JS Interpreter</title>
  <script src="acorn_interpreter.js"></script>
</head>
<body>
    <button onclick="runCode()" id="runButton">Run JavaScript</button>
    <button onclick="stepCode()" id="stepButton">Step JavaScript</button>
 <script>
    var runButton = document.getElementById('runButton');
    var stepButton = document.getElementById('stepButton');
    var myInterpreter = null;

    var myCode = 'var a=1; for(var i=0; i<4; i++ ){a=a*i;console_log(i);};';

    var initFunc = function(interpreter, scope) {
        var wrapper = function(text) {
            return console_log(text);
        };
        interpreter.setProperty(scope, 'console_log', interpreter.createNativeFunction(wrapper));
    };
    myInterpreter = new Interpreter(myCode, initFunc);
    function stepCode() {
        if(this.myInterpreter.step()){
            window.setTimeout(stepCode,0);
        }
    }
    function runCode() {
        myInterpreter.run();
    }
    function console_log(value){
        console.log(value.data);
    }
</script>
</body>
</html>

実行結果は下記です。