ハードウェアからサーバ・アプリまでワンストップで開発

Javascriptのeval(2)

ogochan

前回のエントリで「とりあえず現段階としてはこれで良いことに」とか言ってたんですが、使っているうちにいろいろ不満があったので何とかならないかと、もうちょっと調べてみました。

どうやらちゃんと動くものが作れたので、メモとして。

前回同様、evalについての問題そのものはここでは触れません。てか、ブラウザでREPLなんてものを作る時点で、多少安全にしようとしたところで、そんなに意味があるとも思えません。

今のところ方法が2つあります。

safe-evalを使う

1つは実は前回既に自分で答えを書いてしまっているのですが、「safe-evalを使う」ということです。ただ、前回も書いたように、これはNode.jsのvm moduleを使いますので、ブラウザでは動きません。ブラウザにはvm moduleは存在しませんから。

ということで諦めていたのですが、よく考えてみるとbrowserifyを使うという手がありましたね。vm moduleはNode.jsの深いところに関係があるものなので、勝手にないものだと思ってたんですが、vm moduleもありました。

vm-browserify

これを使えば、多分safe-evalも動くでしょう(試してない)。

もっとも、safe-evalにしろvm moduleにしろ「巨大なブラックボックス」ですし、やっていることが大袈裟なので、もっと他に方法がないものかと考えます。

evalをhackする

この前諦めてからも、「要するにスコープだけの問題だよなぁ」ということでいろいろ書いては諦めを繰り返していたのですが、stackoverflowにエントリがあるのを発見しました。

Context-preserving eval

まさにこれです。つまり、

var __EVAL = s => eval(`void (__EVAL = ${__EVAL.toString()}); ${s}`);

function evaluate(expr) {
    try {
        const result = __EVAL(expr);
        console.log(expr, '===>', result)
    } catch(err) {
        console.log(expr, 'ERROR:', err.message)
    }
}

こんな感じでいけるわけです。

何が起きるかはコードを見るとわかりますが、evalマトリョーシカのようになって行くわけです。並べることが出来ないので、内側に内側にevalを入れて行く、内側はスコープの中なので... という感じですね。

実際に動かしてみると、

という感じでちゃんと動きました。

この前から画面の中身がちょっと変わっていることについては、またエントリを書きます。

既に書いてるように、実際にコードを書いて試したのは後の方だけです。前のやり方でも多分動くだろうと思うのですが、そこで書いたように

ブラックボックスは小さい方がいい

という考えがあるので、後の方がちゃんと動いたので満足したわけです。同じ理由で、Starboardのevalのロジック(TypeScriptで書いてあります)とかもあるのですが、あれもbabelという巨大なブラックボックスがあるので、あまり深入りしていません。まぁ何にしろ動いて満足です。

最近のエントリー

現在の営業品目(2)

現在の営業品目(1)

SPDX License Listをデータ化した

Orange Pi5でC3TR-Adapterを試す

CasaOS上で会計システム「Hieronymus」を動かす

会計システム「Hieronymus」v1.0.0 リリースしました

CasaOSでファイル同期アプリSyncthingをセットアップする

第11回 Freshmeat

オープンソースノーコード「Activepieces」でワークフローを作る

RaspberryPiにパーソナルクラウドOS「CasaOS」を導入する

sequelize-cliでdb:migrateすると「SyntaxError: Unexpected token ':'」が出る

LED行燈の試作(2)

CMSの社内向けサービスのリニューアル

LED行燈の試作(1)

エントリを書くこと

お手軽ポップコーン

VR徘徊(5) StereoPi V1でROSを動かす

VR徘徊(4) StereoPi Ver 1でUbuntu 22.04を動かす

新しいおもちゃ

執筆進捗