mirror of
https://github.com/chinchang/web-maker.git
synced 2025-10-21 00:16:10 +02:00
110 lines
3.3 KiB
JavaScript
110 lines
3.3 KiB
JavaScript
(function () {
|
|
window.DEBUG = document.cookie.indexOf('wmdebug') > -1;
|
|
|
|
window.$ = document.querySelector.bind(document);
|
|
window.$all = document.querySelectorAll.bind(document);
|
|
var alphaNum = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
|
|
|
// https://github.com/substack/semver-compare/blob/master/index.js
|
|
function semverCompare(a, b) {
|
|
var pa = a.split('.');
|
|
var pb = b.split('.');
|
|
for (var i = 0; i < 3; i++) {
|
|
var na = Number(pa[i]);
|
|
var nb = Number(pb[i]);
|
|
if (na > nb) { return 1; }
|
|
if (nb > na) { return -1; }
|
|
if (!isNaN(na) && isNaN(nb)) { return 1; }
|
|
if (isNaN(na) && !isNaN(nb)) { return -1; }
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
function generateRandomId(len) {
|
|
len = len || 10;
|
|
var id = '';
|
|
for (var i = len; i--;) {
|
|
id += alphaNum[~~(Math.random() * alphaNum.length)];
|
|
}
|
|
return id;
|
|
}
|
|
|
|
function onButtonClick(btn, listener) {
|
|
btn.addEventListener('click', function buttonClickListener(e) {
|
|
listener(e);
|
|
return false;
|
|
});
|
|
}
|
|
|
|
function log() {
|
|
if (window.DEBUG) {
|
|
console.log.apply(console, [].splice.call(arguments, 0));
|
|
}
|
|
}
|
|
|
|
// Generate 2 ASTs for the code to be inserted in loops for infinite run protection.
|
|
// The `myVar` variable names would be changed later for every insertion.
|
|
function getLoopProtectorBlocks() {
|
|
var ast1 = esprima.parse('var myvar = Date.now();');
|
|
var ast2 = esprima.parse('while(a){if (Date.now() - a787897 > 1000) { window.top.previewException(new Error("Infinite loop")); break;}}');
|
|
return {
|
|
before: ast1.body[0],
|
|
inside: ast2.body[0].body.body[0]
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add timed limit on the loops found in the passed AST body
|
|
* @param {ASTBody} Body of an AST generated by esprima or any ES compliant AST
|
|
*/
|
|
function addInfiniteLoopProtection(astBody) {
|
|
if (!astBody) return;
|
|
if (!Array.isArray(astBody)) {
|
|
addInfiniteLoopProtection(astBody.body);
|
|
return;
|
|
}
|
|
var el, randomVariableName, insertionBLocks;
|
|
|
|
for (var i = astBody.length; i--;) {
|
|
el = astBody[i];
|
|
if (el && el.type === 'ForStatement' || el.type === 'WhileStatement' || el.type === 'DoWhileStatement') {
|
|
randomVariableName = '_' + generateRandomId(3);
|
|
insertionBLocks = getLoopProtectorBlocks();
|
|
insertionBLocks.before.declarations[0].id.name = insertionBLocks.inside.test.left.right.name = randomVariableName;
|
|
// Insert time variable assignment
|
|
astBody.splice(i, 0, insertionBLocks.before);
|
|
// If the loop's body is a single statement, then convert it into a block statement
|
|
// so that we can insert our conditional break inside it.
|
|
if (!Array.isArray(el.body)) {
|
|
el.body = {
|
|
body: [ el.body ],
|
|
type: 'BlockStatement'
|
|
};
|
|
}
|
|
// Insert IfStatement
|
|
el.body.body.unshift(insertionBLocks.inside);
|
|
}
|
|
if (el.body) {
|
|
addInfiniteLoopProtection(el.body);
|
|
}
|
|
}
|
|
}
|
|
|
|
function getHumanDate(timestamp) {
|
|
var d = new Date(timestamp);
|
|
var retVal = d.getDate() + ' '
|
|
+ [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'][d.getMonth()] + ' '
|
|
+ d.getFullYear();
|
|
return retVal;
|
|
}
|
|
|
|
window.utils = {
|
|
semverCompare: semverCompare,
|
|
generateRandomId: generateRandomId,
|
|
onButtonClick: onButtonClick,
|
|
addInfiniteLoopProtection: addInfiniteLoopProtection,
|
|
getHumanDate: getHumanDate,
|
|
log: log
|
|
};
|
|
})();
|