Fable から JavaScript のコードを実行
Fable から JavaScript のコードを実行したくなることがある。
刹那的なデバッグをするために、Fable の正しいやり方を置いておいて、ひとまず JavaScript の alert
を呼びたいときとか。
きちんとしたことは Fable のドキュメント (link) あたり見るべきなのは分かっているけど……。
やりたいことは Fable.Core.JS.eval
を使ってできた。
alert
くらいはこれで動く。
試したのは SAFE Stack の環境だけど、通常の Fable のアプリケーションでも同じだと期待している。
このコードがブラウザにロードされると、アラートのダイアログが出て “test jsAlert” というメッセージが表示される。
注意したのは JavaScript を実行するために eval
を使っていること。
意図しないコードが eval
に渡らないようにした。
例1 (雑に文字列を安全化)
文字列を安全にするため、英数字、空白、ピリオド、カンマでない文字は削除している。
使える文字を過剰なくらい制限しているけど、このような縛りをしたくないなら安直に eval
を使わないで、真っ当なやり方を調べて使うのがよい。
元の F# コード
open System.Text.RegularExpressions
let jsAlert (msg: string) =
let msg = Regex.Replace(msg, "[^ 0-9A-Za-z.,]", "")
Fable.Core.JS.eval $"alert('{msg}')" |> ignore
jsAlert "test jsAlert"
Fable で変換後の JavaScript コード
export function jsAlert(msg) {
const msg_1 = replace(msg, "[^ 0-9A-Za-z.,+\\-*/()]", "");
void eval(toText(interpolate("alert(\u0027%P()\u0027)", [msg_1])));
}
jsAlert("test jsAlert");
例2 (あからさまに危険)
もし任意に文字列を eval
に渡せると、 alert
にメッセージを渡すだけでは済まず、コードの実行を許してしまう。
以下では F# の jsAlert_Danger
関数には文字列を一つ渡しているけど、JavaScritp を実行すると alert
が呼ばれてから、後続のコード (ここでは confirm('Do you see another behavior that is not an alert?')
) が実行される。
元の F# コード
let jsAlert_Danger (msg: string) =
Fable.Core.JS.eval $"alert('{msg}')" |> ignore
jsAlert_Danger "test jsAlert_Danger'); confirm('Do you see another behavior that is not an alert?"
Fable で変換後の JavaScript コード
export function jsAlert_Danger(msg) {
void eval(toText(interpolate("alert(\u0027%P()\u0027)", [msg])));
}
jsAlert_Danger("test jsAlert_Danger\u0027); confirm(\u0027Do you see another behavior that is not an alert?");