diff --git a/docs/polyfills.md b/docs/polyfills.md index 5083acf..1e28f70 100644 --- a/docs/polyfills.md +++ b/docs/polyfills.md @@ -48,3 +48,15 @@ ExtendScript(ES3)では以下の理由で再現不可能: shim では正しく動作しない機能が存在する。 これらは ESLint ルールによってエラーとして表示される。 詳細は各 shim ファイルのコメントを参照。 + +## 同一 ExtendScript セッションでの再評価 + +Rollup の CommonJS 変換が生成する `hasRequiredEs5Shim` / +`hasRequiredEs6Shim` は、1つのバンドル内での require 再実行を防ぐローカル +ガードである。`$.evalFile()` で同じバンドルを再評価するとローカル変数は +初期化されるため、このガードだけでは shim の再適用を防げない。 + +そのため両 shim の `factory` 本体は、実行結果をバージョン付きの `$.global` +モジュール固有キャッシュへ保存する。バンドル内の既存ガードはそのまま利用し、 +別のバンドルを再評価しても `factory` 本体を再実行しない。`factory` が例外を +投げた場合は不完全な結果をキャッシュしない。 diff --git a/src/lib/polyfills/es5-shim.js b/src/lib/polyfills/es5-shim.js index e08ee65..4c8e134 100644 --- a/src/lib/polyfills/es5-shim.js +++ b/src/lib/polyfills/es5-shim.js @@ -28,6 +28,19 @@ root.returnExports = factory(); // eslint-disable-line no-param-reassign } })(this, function () { + // $.global survives $.evalFile() re-evaluation in ExtendScript. + var esTsGlobal = + typeof $ !== "undefined" && $.global ? $.global : null; + var esTsCacheKey = "__ES_TS_TEMPLATE_ES5_SHIM__"; + var esTsCacheVersion = "v1"; + var esTsCache = esTsGlobal && esTsGlobal[esTsCacheKey]; + if ( + esTsCache && + esTsCache.version === esTsCacheVersion + ) { + return esTsCache.exports; + } + /** * Brings an environment as close to ECMAScript 5 compliance * as is possible with the facilities of erstwhile engines. @@ -2807,4 +2820,11 @@ // can't use defineProperties here because of toString enumeration issue in IE <= 8 RegExp.prototype.toString = regexToString; } + + if (esTsGlobal) { + esTsGlobal[esTsCacheKey] = { + version: esTsCacheVersion, + exports: undefined, + }; + } }); diff --git a/src/lib/polyfills/es6-shim.js b/src/lib/polyfills/es6-shim.js index ed23373..be6c171 100644 --- a/src/lib/polyfills/es6-shim.js +++ b/src/lib/polyfills/es6-shim.js @@ -27,6 +27,19 @@ })(this, function () { ("use strict"); + // $.global survives $.evalFile() re-evaluation in ExtendScript. + var esTsGlobal = + typeof $ !== "undefined" && $.global ? $.global : null; + var esTsCacheKey = "__ES_TS_TEMPLATE_ES6_SHIM__"; + var esTsCacheVersion = "v1"; + var esTsCache = esTsGlobal && esTsGlobal[esTsCacheKey]; + if ( + esTsCache && + esTsCache.version === esTsCacheVersion + ) { + return esTsCache.exports; + } + var _apply = Function.call.bind(Function.apply); var _call = Function.call.bind(Function.call); var isArray = Array.isArray; @@ -186,10 +199,14 @@ }; var getGlobal = function () { - /* global self, window */ + /* global $, self, window, global */ // the only reliable means to get the global object is // `Function('return this')()` // However, this causes CSP violations in Chrome apps. + // ExtendScript exposes the engine global through $.global. + if (typeof $ !== "undefined" && $.global) { + return $.global; + } if (typeof self !== "undefined") { return self; } @@ -3013,5 +3030,11 @@ }); } + if (esTsGlobal) { + esTsGlobal[esTsCacheKey] = { + version: esTsCacheVersion, + exports: globals, + }; + } return globals; });