コードが反映されない問題
目標
ブロックを置いてもコードが表示されない問題の原因を探り,解決する.
現状
自分が作ったブロックの中でコードで出力されるものとされないものがある
この記事ではコードを反映させることが出来ている.
しかし,新しく作成した,次の画像にあるようなrandom,gaussブロックではコードが出力されない.
原因究明
入力方法の違い?
一目見てみて,明らかに違うところはplayがブロックの中に引数が埋め込まれているのに対して,random, gaussは外からブロックを当てはめるものになっている.
一旦,gaussでplayと同じように引数を設定してみる.
設定した通りにコードが反映されていた.
原因特定
teratailにて適切な回答があったので,それを改めてここにまとめる.
まず,randomブロックを配置するとブラウザのデベロッパツールで次のようなエラーが発生する.
これによりコードの出力処理が正常に働かなくなる.
random.js:7 Uncaught TypeError: Cannot read properties of undefined (reading 'ORDER_NONE')
at Blockly.JavaScript.random (random.js:7:36)
at Blockly.Generator.blockToCode (blockly_compressed.min.js:1324:268)
at Blockly.Generator.valueToCode (blockly_compressed.min.js:1326:187)
at Blockly.JavaScript.text_print (javascript_compressed.min.js:94:429)
at Blockly.Generator.blockToCode (blockly_compressed.min.js:1324:268)
at Blockly.Generator.workspaceToCode (blockly_compressed.min.js:1322:246)
at myUpdateFunction (script.js:17:33)
at Blockly.Workspace.fireChangeListener (blockly_compressed.min.js:893:446)
at Blockly.Events.fireNow_ (blockly_compressed.min.js:1250:203)
このエラーが発生する原因はgenerators/danrom.js 7行目の
return [code, Blockly.javascript.ORDER_NONE];
エラーが発生する理由はエラー文より,
Cannot read properties of undefined (reading 'ORDER_NONE')
なぜこれがundefinedなのかは,Blocklyオブジェクトが持っているプロパティは"javascript"ではなく"JavaScript"だからである.
"javascript"としているのは公式のコードGeneratorなので,きちんと自分の環境に合ったものに変更しないといけないのは注意が必要である.
gauss2やplay2のように埋め込み式のものが正常に動く理由は,return code;のようにcodeしか返していないからである.
// generators/gauss2.js
Blockly.JavaScript['gauss'] = function(block, generator) {
var number_num_of_note = block.getFieldValue('num_of_note');
var number_ave_of_noteno = block.getFieldValue('ave_of_noteNo');
var number_var = block.getFieldValue('var');
// TODO: Assemble javascript into code variable.
var code = number_num_of_note + number_ave_of_noteno + number_var + '\n';
return code; // code しか返していない。
};
また,これだけでは外ハメのものがうまく動かない理由を全ては挙げきれていない.
上記のgauss2.jsでは,varの変数はblock.getFieldValueによって初期化されていて,これは正しく動く.
// generators/gauss.js
Blockly.JavaScript['gauss'] = function(block, generator) {
var value_number_of_note = generator.valueToCode(block, 'number_of_note', javascript.Order.ATOMIC);
var value_ave_of_noteno = generator.valueToCode(block, 'ave_of_noteNo', javascript.Order.ATOMIC);
var value_var = generator.valueToCode(block, 'var', javascript.Order.ATOMIC);
// TODO: Assemble javascript into code variable.
var code = value_number_of_note + value_ave_of_noteno + value_var + '\n';
return code;
};
このgauss.jsのvar変数はgenerator.valueToCodeによって初期化されているが,これは正しく動かない.
それは本環境において,valueToCodeがあるのはgeneratorではないからだ.
この"generator"を"Blockly.JavaScript"に置き換えることで適切に動く.
また,"javascript.Order.ATOMIC"の"javascript"は前述のように"Blockly.JavaScript" に,またその参照先に合わせて"ATOMIC" を次のよう "ORDER_ATOMIC" にすれば想定通り動く.
// generators/gauss.js
Blockly.JavaScript['random'] = function(block, generator) {
var value_min = Blockly.JavaScript.valueToCode(block, 'min', Blockly.JavaScript.ORDER_ATOMIC);
var value_max = Blockly.JavaScript.valueToCode(block, 'max', Blockly.JavaScript.ORDER_ATOMIC);
// TODO: Assemble javascript into code variable.
var code = 'Math.floor( Math.random() * (' + value_max + ' - ' + value_min + ' + 1 )) + ' + value_min + "\n";
// TODO: Change ORDER_NONE to the correct strength.
return [code, Blockly.JavaScript.ORDER_NONE];
};
javascript.javascriptGenerator.forBlockをBlockly.JavaScriptに書き換えなければならない理由についても,自分の開発環境に適応させなくてはいけないからであある.