ogochan
あれからちょこちょこといじって、JavascriptのREPL(Read Eval Print Loop)がフロントで動くようになりました。
今回はRiot.jsではなくてSvelteを使っています。
Jupyter Notebookで言うところの「セル」の実装の途中です。
とりあえずこんな感じで動いています。
薄い外枠がセルの枠、その中のコードが書かれているのが入力エリアでMonacoを使っています。下にチョロっと出ているのが、実行結果ですね(厳密に言うと違う)。
動作の説明
やっていることは大したことではなく、Monacoで作られた入力領域にコードを入力して、トリガー(CTRL + Enter)を入れるとコードを取り込んで、eval()
して、その結果を表示しているだけです。まぁ「だけ」ですよ。だけ。
「だけ」なんですが、この処理を骨だけ切り出した、
let input = "console.log('Hello')";
let output = eval(input);
とやった時に何が起きるかと言えば、output
にはinput
をeval
した結果が入る「だけ」です。
つまり、outputに入るものは、
undefined
だけです。では'Hello'
はどこに行ったかと言えば、デバッグコンソールに出力されているだけです。
これは正しいっちゃー正しい(だからどこかで出して欲しい)のですが、せっかくconsole.log()
を実行したのですから、デバッグコンソールではなくてREPL環境のどこかに出て欲しいわけです。ちなみに、Starboardでは、
こんなふうに出来ます。
console.logの解決
まず考えることは、「consoleをどこかにリダイレクトできないか」ということです。
これは私の調べた範囲では、汎用的かつ一般的な解決手段はないようです。もちろんブラウザの中身に手を入れれば何だってありですが、それで解決しても何の解決にもなりませんね。
次に考えたのは、「どこかにそんなライブラリは存在しないか」ということです。どんな手段であれ、ライブラリ化していればそれを使えば良いだけですからね。
ということで、Starboardのpackge.json
を調べます。そうするとconsole-feed-modern
というそれっぽいものを発見します。
console-feed-modernというのはconsole-feedをちょっといじったもので、
A React component that displays console logs from the current page, an iframe or transported across a server.
This fork, intended for use in Starboard Notebook updates the dependencies and removes ES3 transpilation.
と書かれています。
つまり、console
を代替するReactのコンポーネントだということですね。試しにStarboardの中でconsole
を出力させると、素のconsole
とはいろいろ違うことがわかります。ソースを見ると、「車輪の再発明」ならぬ「consoleの再実装」がされています。
と言うことで、一見console
がリダイレクトされているように見えるStarboardは、実は自前のconsole
を定義してすげ換えてることがわかりました。
そこで、
class Console {
log(arg) {
return(arg);
}
}
雑にこんなものを作ってやって、
const console = new Console();
let input = "console.log('Hello')";
let output = eval(input);
というようなことをしてやれば、めでたくoutput
には'Hello'
が入るわけです。これが最初に示した結果です。
もちろんconsole
にはもっといろんなメソッドがあるわけですが、そういったものは追い追い実装してやれば良いし、またもっと便利なものをつけ加えても良いわけです。
まぁそんなこんなで、なんとなく期待した感じでREPLが動く目処が立ちました。
次はeval()
の動作に落とし穴があるらしいのですが、それはまた落ちた時にでも書きます。今のところはこんな感じです。