Electronでのアプリケーションの開発中、特定のWebページを表示する必要が出てきたので<webview>
タグを利用した。
その時に、<webview>
側からElectron側のウィンドウへデータを受け渡す必要が出てきたため、executeJavaScript
をを利用したものの、うまくコールバックが発火せず、データの受け渡しに苦戦したのでメモ。
問題のコード
<webview>
側のページから特定のセレクタに付与されているCSSを取得したいというニーズだったのでそのまま掲載。
electron.js
const $ = e=>document.querySelector(e);
const webview = $("webview");
webview.addEventListener("did-stop-loading", ()=>{
webview.executeJavaScript(
`return $("#col_channels_bg").css("backgroundColor")`,
false,
function(color){
console.log(color);
}
);
});
この場合、一件問題なくWebview側で読み込まれていたjQueryを利用して背景色を取得できているようにみえるが、コールバック関数のcolorが何故かundefinedであった
問題の原因
webview.openDevTools();
と入力することでwebview側のデベロッパーコンソールを開くことができるため、こちらで値を確認してみることに。
すると、以下のようなエラーが発生していた。
Uncaught SyntaxError: Illegal return statement
どうやら送った文字列をそのままeval()
かなにかでwebview上でベタに走らせているようで、グローバルでreturnした場合と同じエラーが発生している様子。
解決方法
結論としては、returnせずにそのままJSオブジェクトとして吐かせると、うまくコールバックが動作した。
electron-fix.js
const $ = e=>document.querySelector(e);
const webview = $("webview");
webview.addEventListener("did-stop-loading", ()=>{
webview.executeJavaScript(
`color:{$("#col_channels_bg").css("backgroundColor")}`,
false,
function(color){
console.log(color); // rgb(100, 100, 100);
// 決してcolor.colorではなく、colorでアクセスすることになるので注意
}
);
});
まとめ
- Electronのwebview.executeJavaScript()で実行されるコードはそれ自体にスコープを持っていない
- そのため、returnをするとグローバルでのreturnと同様とみなされエラーが発生する
- これを防ぎつつコールバック側にデータを渡すには、それ自体をJSオブジェクトの形式としてコードを記述すると良い