今更こんな事説明するまでもないかもしれませんがガガ…、その理由らしキモノを書き散らかしやがっておきマス。
CodePenでは書いたprogramがそのまま実行されるわけではありません。いちいち書き換えやがってくれます。
編集したJavaScriptはhttps://cdpn.io/cpe/boomboom/pen.js?key=pen.js-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxのような名前の外部js fileへと生まれ変わり果てます。中身をいやらしい目つきで観察してみましょう。
すると…なんと整形されまくっているではありませんか! というのはどうでもよくて、随所にwindow.CP.shouldStopExecutionやwindow.CP.exitedLoopという関数が挿入されています。
用途
infintyな無限の永久的永劫loopによってbrowserが応答不能になるのを防ぐために自動挿入されるお節介機能。
window.CP.shouldStopExecution(id) でloopの監視を開始し、loopが終了した時点で window.CP.exitedLoop(id) を呼び出して終了を通知する。
window.CPの実装
ここ参照。以下のようになっています
"use strict";"object"!=typeof window.CP&&(window.CP={}),window.CP.PenTimer={programNoLongerBeingMonitored:!1,timeOfFirstCallToShouldStopLoop:0,_loopExits:{},_loopTimers:{},START_MONITORING_AFTER:2e3,STOP_ALL_MONITORING_TIMEOUT:5e3,MAX_TIME_IN_LOOP_WO_EXIT:2200,exitedLoop:function(o){this._loopExits[o]=!0},shouldStopLoop:function(o){if(this.programKilledSoStopMonitoring)return!0;if(this.programNoLongerBeingMonitored)return!1;if(this._loopExits[o])return!1;var t=this._getTime();if(0===this.timeOfFirstCallToShouldStopLoop)return this.timeOfFirstCallToShouldStopLoop=t,!1;var i=t-this.timeOfFirstCallToShouldStopLoop;if(i<this.START_MONITORING_AFTER)return!1;if(i>this.STOP_ALL_MONITORING_TIMEOUT)return this.programNoLongerBeingMonitored=!0,!1;try{this._checkOnInfiniteLoop(o,t)}catch(o){return this._sendErrorMessageToEditor(),this.programKilledSoStopMonitoring=!0,!0}return!1},_sendErrorMessageToEditor:function(){try{if(this._shouldPostMessage()){var o={action:"infinite-loop",line:this._findAroundLineNumber()};parent.postMessage(JSON.stringify(o),"*")}else this._throwAnErrorToStopPen()}catch(o){this._throwAnErrorToStopPen()}},_shouldPostMessage:function(){return document.location.href.match(/boomerang/)},_throwAnErrorToStopPen:function(){throw"We found an infinite loop in your Pen. We've stopped the Pen from running. Please correct it or contact support@codepen.io."},_findAroundLineNumber:function(){var o=new Error,t=0;if(o.stack){var i=o.stack.match(/boomerang\S+:(\d+):\d+/);i&&(t=i[1])}return t},_checkOnInfiniteLoop:function(o,t){if(!this._loopTimers[o])return this._loopTimers[o]=t,!1;var i=t-this._loopTimers[o];if(i>this.MAX_TIME_IN_LOOP_WO_EXIT)throw"Infinite Loop found on loop: "+o},_getTime:function(){return+new Date}},window.CP.shouldStopExecution=function(o){var t=window.CP.PenTimer.shouldStopLoop(o);return t===!0&&console.warn("[CodePen]: An infinite loop (or a loop taking too long) was detected, so we stopped its execution. Sorry!"),t},window.CP.exitedLoop=function(o){window.CP.PenTimer.exitedLoop(o)};
改竄例
for(let n=0,A,B=[];n++<9;){
B.push(Math.random()*222|0);
A=B.map((a,b)=>b);
A.sort((a,b)=>{
let c=a<b?n-b:n-a,d;
for(;c--&&!(d=B[a++]-B[b++]););return d||b-a
});
document.write(A,"<br>")
}
for (let n = 0, A, B = []; n++ < 9;) {if (window.CP.shouldStopExecution(0)) break;
B.push(Math.random() * 222 | 0);
A = B.map((a, b) => b);
A.sort((a, b) => {
let c = a < b ? n - b : n - a,d;
for (; c-- && !(d = B[a++] - B[b++]);) {if (window.CP.shouldStopExecution(1)) break;;}window.CP.exitedLoop(1);return d || b - a;
});
document.write(A, "<br>");
}window.CP.exitedLoop(0);
ご覧のようにloopの冒頭でwindow.CP.shouldStopExecutionが召喚され、loop終了地点でwindow.CP.exitedLoopが召喚されています。ついでに変てこ整形機能も働いています。
こいつらを召喚したくなければ文字列化してeval()で実行すると良いです。もしくはFunction()を利用
eval(`for(let n=0,A,B=[];n++<9;){
B.push(Math.random()*222|0);
A=B.map((a,b)=>b);
A.sort((a,b)=>{
let c=a<b?n-b:n-a,d;
for(;c--&&!(d=B[a++]-B[b++]););return d||b-a
});
document.write(A,"<br>")
}`)
原型ではなくbase64から復号して実行するという手もあります
eval(atob`Zm9yKGxldCBuPTAsQSxCPVtdO24rKzw5Oyl7CglCLnB1c2goTWF0aC5yYW5kb20oKSoyMjJ8MCk7CglBPUIubWFwKChhLGIpPT5iKTsKCUEuc29ydCgoYSxiKT0+ewoJCWxldCBjPWE8Yj9uLWI6bi1hLGQ7CgkJZm9yKDtjLS0mJiEoZD1CW2ErK10tQltiKytdKTspO3JldHVybiBkfHxiLWEKCX0pOwoJZG9jdW1lbnQud3JpdGUoQSwiPGJyPiIpCn0`)