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()の動作に落とし穴があるらしいのですが、それはまた落ちた時にでも書きます。今のところはこんな感じです。
