Wandbox のエディタ設定を言語ごとに保存して自動で切り替えする UserScript
表題の通り。
Wandbox さん非常に便利なんですが、言語を切り替えてもエディタ設定は切り替わらないんですよね。
例えば F# はタブ文字をインデントに使えませんが、Go はタブ文字でのインデントを推奨しています。
これら言語を切り替えるときに設定も都度触るのが非常に億劫だと常々思っていました。
というわけで、そのちょっとした不満を解消するために書きました。
設計は「まぁ Proxy
使えば未定義のプロパティも初期化できるやろ」くらいのかなり適当なノリでやってしまったので、メンテが非常につらい感じになっています。
変数の命名も適当です。適当に書いてたら名前が被りそうだったので、普段はオブジェクトをバインドした定数に UPPER_SNAKE_CASE は使わないんですが、他に考えるのも面倒だったので苦し紛れに使っています。
Promise を再帰させるとどうなるか
ただの興味本位です。
以下のコードを各環境で動かしていきます。
const p = n => new Promise(resolve => { console.log(n); resolve(p(n + 1)); }); p(1);
なるべく公平を期すため、ブラウザの場合は about:blank
にて実行します。
環境
PC1:
種別 | 詳細 |
---|---|
OS | Windows 10 |
CPU | AMD Rizen 5 1600 |
MEM | DDR4 PC4-24000 16GB x2 (空き 20000MB程度) |
PC2:
種別 | 詳細 |
---|---|
OS | macOS 10.14.6 (Mojave) |
CPU | Intel Core i5 5250U |
MEM | LPDDR3 PC3-12800 4GB (空き1000MB程度) |
結果
環境 | 再帰回数 | 備考 |
---|---|---|
Edge 44 | 1000 | 20回置きにウェイトが入る。終了時は特に出力なし |
Safari | 3674 | コンソールにはエラーが表示されず、 ブラウザページにポップアップで Maximum call stack size exceeded. と表示され終了 |
Firefox 69 (PC1) | 582 | too much recursion の例外で終了 |
Firefox 69 (PC2) | 2946 | too much recursion の例外で終了 |
Chrome 77 (PC1) | 1934 | RangeError: Maximum call stack size exceeded の例外で終了 |
Chrome 77 (PC2) | 1929 | RangeError: Maximum call stack size exceeded の例外で終了 |
node 10.16.3 (PC1) | 1818 | エラーを吐かずにクラッシュして終了 |
node 10.16.3 (PC2) | 1847 | RangeError: Maximum call stack size exceeded の例外で終了 |
node 12.11.1 (PC1) | 1806 | エラーを吐かずにクラッシュして終了 |
node 12.11.1 (PC2) | 1835 | RangeError: Maximum call stack size exceeded の例外で終了 |
この規則性のない結果から、おそらく Promise における再帰については厳密な仕様はなく実装依存であることが推定されますが、仕様書のどの辺りを見ればよいのか分からず…。
同じバージョンでも環境によって結果が異なるので、メモリ等の状態によっても変わるのかなと思いますが、ブラウザのソースコード読む気力もなく、「とりあえず Promise の再帰はなるべく避けよう」という辺りで落ち着けておきます。
JScript(not JavaScript)のArrayに対するメソッド群を追加する超単純なポリフィル
今さらこんなコードを書くこと自体恥ずべきことだと思うのだけど、勤務先の業務システムがJSPで実装されており、クライアントサイドはレガシーなIEが想定されています(嘆かわしいですが、よくある光景ですね…)
そしてこれまたよくある光景なのですが、秘伝のソースであるため、
<%-- yyyy/mm/dd add someone IE11対応 --%> <META HTTP-EQUIV=X-UA-Compatible CONTENT=IE=5> <%-- /IE11対応 --%>
みたいなのが書いてあるわけです。
お前それどこがIE11対応やねん、といったツッコミはさておき。
そんな環境ですと、おもむろにF12
を押してデバッグをしようにも配列やArrayLikeを扱う上で非常につらみを感じるわけです。
「じゃあlodash使えばいいじゃん!」と
(function(s){ s.src="https://cdn.jsdelivr.net/lodash/4.17.4/lodash.min.js"; document.body.appendChild(s); })(document.createElement("script"))
なんてコードを実行してみても、lodashの実行中にコケたりするんです。
そのときに知ったんですが、lodashってIE9+なんですね…。
便利なライブラリが使えないとなると、ある程度自分で書かざるをえないのでブックマークレットを作成して活用しています。
というのが前置き。
当たり前ですがコードの持ち出しは禁止なので、実際のコードとはちょっと違うと思います。
javascript:(function(d,i,l,x,a){d("indexOf",function(v){for(i=0,l=this.length;i<l;++i)if(this[i]===v)return i;return -1});d("includes",function(v){return!!~this.indexOf(v)});d("map",function(f,t){x=this,a=[];for(i=0,l=x.length;i<l;++i)a.push(f.call(t,x[i],i,x));return a});d("filter",function(f,t){x=this,a=[];for(i=0,l=x.length;i<l;++i)f.call(t,x[i],i,x)&&a.push(x[i]);return a});d("forEach",function(f,t){x=this;for(i=0,l=x.length;i<l;++i)f.call(t,x[i],i,x)});d("reduce",function(f,v){x=this,v=v!==void 0?v:x.shift();for(i=0,l=x.length;i<l;++i)v=f(v,x[i],i,x);return v});d("every",function(f,t){return!!this.reduce(function(p,c){return p&&f.call(t,c)},1)});d("some",function(f,t){return!!this.reduce(function(p,c){return p||f.call(t,c)},0)})})(function(n,f){if(![][n])Array.prototype[n]=f})
追記 (2018/06/11 01:59)
改めてGistに起こしました。
ES5 or above polyfills for ES3 (It's not compatible with ECMA-262 strictly) · GitHub
len
という変数を定義してまでいちいちthis.length
を代入している理由は、賢明な諸兄はもちろんご存知かと思いますが、forループで毎回Array#length
にアクセスしてパフォーマンスが落ちるからです。
なので最初に長さを持ってしまいます。
その結果、高階関数に渡す関数がオブジェクト自身の要素数に副作用を起こすものである場合、意図しない動作になります。
まぁ自分しか使わないのでどうでもいいんですが。