JavaScript の生成と実行

ブロック的なアプリケーションは、出力言語として JavaScript を生成することが多く、 通常はウェブページ内で実行します(同じまたは埋め込みの WebView)。 他の生成ツールと同様に、まず JavaScript 生成ツールを読み込みます。

import {javascriptGenerator} from 'blockly/javascript';

ワークスペースから JavaScript を生成するには、以下を呼び出します。

javascriptGenerator.addReservedWords('code');
var code = javascriptGenerator.workspaceToCode(workspace);

作成されたコードは、リンク先の Web ページで直接実行できます。

try {
  eval(code);
} catch (e) {
  alert(e);
}

基本的に、上記のスニペットはコードを生成して評価するだけです。ただし、 いくつかの改良点があります改良点の一つは、eval を 失敗するのではなくランタイム エラーを表示する try/catch 抑えることができます。もう 1 つの絞り込みでは、予約済みのリストに code が追加されることです。 変数を使用することで、ユーザーのコードにその名前の変数が含まれている場合に 自動的に名前が変更されます。ローカル変数はすべて、 できません。

ブロックを強調

コードの実行中に現在実行中のブロックをハイライト表示すると、 プログラムの動作を理解できますハイライト表示は、JavaScript コードを生成する前に STATEMENT_PREFIX を設定することで、ステートメント単位で行うことができます。

javascriptGenerator.STATEMENT_PREFIX = 'highlightBlock(%1);\n';
javascriptGenerator.addReservedWords('highlightBlock');

highlightBlock を定義して、ワークスペース上のブロックにマークを付けます。

function highlightBlock(id) {
  workspace.highlightBlock(id);
}

これにより、ステートメント highlightBlock('123'); が前に追加されます。 すべてのステートメント(123 は、変換されるブロックのシリアル番号) ハイライト表示されます。

無限ループ

生成されるコードは常に構文が正しいことが保証されますが、無限ループが含まれている可能性があります。2024 年に 問題の停止は Blockly のスコープです カウンタを維持し、反復処理が行われるたびに減らします。 これを行うには、javascriptGenerator.INFINITE_LOOP_TRAP をコードに すべてのループとすべての関数に挿入されます。以下に例を示します。

window.LoopTrap = 1000;
javascriptGenerator.INFINITE_LOOP_TRAP = 'if(--window.LoopTrap == 0) throw "Infinite loop.";\n';
var code = javascriptGenerator.workspaceToCode(workspace);

こちらの ライブデモ 基本的なスキルを習得できます。

JS インタープリタ

ユーザーのブロックを適切に実行することを真剣に考えている場合は、JS-Interpreter プロジェクトが適しています。このプロジェクトは Blockly とは別個ですが、Blockly 用に特別に作成されています。

  • 任意の速度でコードを実行できます。
  • 一時停止/再開/ステップスルーの実行。
  • 実行時にブロックをハイライト表示します。
  • ブラウザの JavaScript から完全に分離されています。

インタープリタを実行する

まず、GitHub から JS-Interpreter をダウンロードします。

ZIP ファイルをダウンロード TAR Ball をダウンロード GitHub で表示

次に、これをページに追加します。

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

最も簡単な呼び出す方法は、JavaScript を生成し、 コードを実行します。

var code = javascriptGenerator.workspaceToCode(workspace);
var myInterpreter = new Interpreter(code);
myInterpreter.run();

通訳者をステップさせる

コードをより遅く、またはより制御された方法で実行するには、run の呼び出しをステップするループに置き換えます(この場合は 10 ミリ秒ごとに 1 ステップ)。

function nextStep() {
  if (myInterpreter.step()) {
    setTimeout(nextStep, 10);
  }
}
nextStep();

各ステップは行でもブロックでもなく、セマンティック単位です。 非常に詳細です。

API を追加する

JS インタープリタは、ブラウザから完全に隔離されたサンドボックスです。 外部とアクションを実行するブロックには、API を 説明します。詳細については、 JS Interpreter のドキュメント まず、アラート ブロックとプロンプト ブロックをサポートするために必要な API を紹介します。

function initApi(interpreter, globalObject) {
  // Add an API function for the alert() block.
  var wrapper = function(text) {
    return alert(arguments.length ? text : '');
  };
  interpreter.setProperty(globalObject, 'alert',
      interpreter.createNativeFunction(wrapper));

  // Add an API function for the prompt() block.
  wrapper = function(text) {
    return prompt(text);
  };
  interpreter.setProperty(globalObject, 'prompt',
      interpreter.createNativeFunction(wrapper));
}

次に、initApi 関数を渡すようにインタープリタの初期化を変更します。

var myInterpreter = new Interpreter(code, initApi);

デフォルトのブロックセットで、インタープリタのカスタム API が必要なブロックは、アラート ブロックとプロンプト ブロックの 2 つだけです。

highlightBlock() を接続中

JS Interpreter で実行する場合、highlightBlock() を実行する必要がある ユーザーがプログラムをステップ実行すると、すぐにサンドボックスの外に現れます。タスク 関数を取得するラッパー関数 highlightBlock() を作成します。 ネイティブ関数として登録します。

function initApi(interpreter, globalObject) {
  // Add an API function for highlighting blocks.
  var wrapper = function(id) {
    return workspace.highlightBlock(id);
  };
  interpreter.setProperty(globalObject, 'highlightBlock',
      interpreter.createNativeFunction(wrapper));
}

より高度なアプリケーションでは、コードを使わずにステップを繰り返し実行 ハイライト コマンドに到達するまで一時停止し、一時停止します。この戦略では、 行ごとに行われます。次の例ではこの方法を使用しています。

JS インタープリタの例

こちらの ライブデモ 一つひとつ解説しますそして こちらのデモ 他の非同期動作に使用するのに適した例として、wait ブロックが含まれている (音声や音声、ユーザー入力など)。