GASのV8ランタイムをOFFにしてもArray.find等を利用したい
タイトルの通りです。
GASはV8エンジンに対応してだいぶ便利になりましたが、一方でいくつか不具合のような挙動をすることが知られています。
今回は最初のリンクにあるように以下の条件に一致していました。
- V8ランタイムが有効である。
- ライブラリにdeveloperモードのものがある。
- スクリプトのオーナー以外のユーザーによる実行である。
作成したライブラリは、利用者が意識せずに変更を加えられるように常に最新の状況を見るDeveloperモードに設定する必要がありました。
(逆に言うと、いったん承認しちゃうと権限の変更がない限り、どんな変更してもライブラリの利用者は気が付けないので上記のような制限がかかっているのかもしれませんね。)
clasp + TypeScriptを利用して開発をしていたので、ES3相当のトランスパイルがすでにされていました。
- 参考リンク
そこで、V8ランライムを無効にして処理を実行したところ、Array.findの関数が存在しないためエラーになってしまいました。
claspのissueにもある通り、一部サポートされていない関数があります。issueにあるspreadsheetで記載されている一覧がわかりやすいです。
Array.findを書き換えるのはさすがに面倒なので、既存のpolyfillのライブラリを利用することにしました。
エラーになっているコードに対して、polyfillを追加してもいいのですが、今後も同様の問題が発生しそうなので、汎用的に使えるようにライブラリにしました。
GASのライブラリを作る
意外とGASのライブラリで公開されているものが少ないので、自分の手で作成することにしました。
コードは以下に置いてあります。
polyfillとしてはcore-jsがよさそうなので利用することにしました。
core-jsを呼び出しているだけなので、一部を抜粋して紹介します。
なお、claspについては以下のリンクなどを参考にしてください
-
初期化して、必要なライブラリを入れます
npm init -y
mkdir dist
clasp create --type standalone --rootDir dist
npm install --save core-js
npm install -D webpack webpack-cli
- ソース。importだけです。
import "core-js/stable/array";
import "core-js/stable/object";
import "core-js/stable/string";
- webpackの設定をします。
const path = require('path');
module.exports = {
mode: "development",
entry: './src/index.js',
target: ['web', 'es5'],
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist'),
},
};
- package.jsonでwebpackを追加します。
"scripts": {
+ "build": "webpack",
"test": "echo \"Error: no test specified\" && exit 1"
},
- appscript.jsonでV8エンジンを無効にします。
{
"timeZone": "Asia/Tokyo",
"dependencies": {
},
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "DEPRECATED_ES5"
}
- GASにpushします。
npm run build
clasp push
- clasp createしたときのURL(.clasp.jsonのscriptId)にアクセスすると、pushしたものが反映されてることが確認できます。
はまったポイント
- index.tsで
import "core-js/stable";
をすれば基本的にすべてのpolyfillを使えるようになりますが、その状態でライブラリを使用すると実行時にExceeded maximum stack depth
のエラーが出ます。- おそらくpolyfillの処理が長すぎるために出ているっぽいので、importは一部にしてあげると意図した通りに動作するようになりました。
- webpack.config.jsのtargetにwebを入れないとアロー関数式になるため、エラーになります。
- webpack.config.jsのmodeをproductionにしてclasp pushすると
axiosError: Syntax error: Invalid property ID. line: 1 file: main
のエラーが出て、pushできません。- developmentだと成功するのでとりあえずdevelopmentにしています。
Discussion