mirror of
https://github.com/jsbin/jsbin.git
synced 2026-01-18 15:18:04 +00:00
Rewrote more of loop protection to carefully walk new lines
This ensures we catch multi-line loop conditions, and fixes #725.
This commit is contained in:
parent
36de005a4e
commit
208ea017fa
@ -29,10 +29,11 @@ var loopProtect = (function () {
|
||||
return ';' + method + '({ line: ' + lineNum + ', reset: true });\n' + line;
|
||||
};
|
||||
|
||||
lines.forEach(function (line, i) {
|
||||
lines.forEach(function (line, lineNum) {
|
||||
var next = line,
|
||||
index = 0,
|
||||
lineNum = i - offset + 1, // +1 since we're humans and don't read lines numbers from zero
|
||||
originalLineNum = lineNum,
|
||||
printLineNumber = lineNum - offset + 1, // +1 since we're humans and don't read lines numbers from zero
|
||||
character = '',
|
||||
cont = true,
|
||||
oneliner = false,
|
||||
@ -40,7 +41,7 @@ var loopProtect = (function () {
|
||||
match = (line.match(re) || [null,''])[1],
|
||||
openBrackets = 0;
|
||||
|
||||
if (ignore[i]) return;
|
||||
if (ignore[lineNum]) return;
|
||||
|
||||
|
||||
if (match && line.indexOf('jsbin') === -1) {
|
||||
@ -73,6 +74,7 @@ var loopProtect = (function () {
|
||||
|
||||
while (index < line.length) {
|
||||
character = line.substr(index, 1);
|
||||
// console.log(character, index);
|
||||
|
||||
if (character === '(') {
|
||||
openBrackets++;
|
||||
@ -81,67 +83,51 @@ var loopProtect = (function () {
|
||||
if (character === ')') {
|
||||
openBrackets--;
|
||||
|
||||
if (openBrackets === 0) {
|
||||
if (openBrackets === 0 && terminator === false) {
|
||||
terminator = index;
|
||||
}
|
||||
}
|
||||
|
||||
if (terminator !== false && character === ';') {
|
||||
// this is the end of a oneliner
|
||||
oneliner = true;
|
||||
if (openBrackets === 0 && (character === ';' || character === '{')) {
|
||||
|
||||
// insert the loop protection extra new lines ensure we clear any comments on the original line
|
||||
line = line.substring(0, terminator + 1) + '{\nif (' + method + '({ line: ' + lineNum + ' })) break;\n' + line.substring(terminator + 1) + '\n}\n';
|
||||
recompiled.push(insertReset(lineNum, line));
|
||||
return;
|
||||
}
|
||||
// if we're a non-curlies loop, then convert to curlies to get our code inserted
|
||||
if (character === ';') {
|
||||
if (lineNum !== originalLineNum) {
|
||||
// affect the compiled line
|
||||
recompiled[originalLineNum] = recompiled[originalLineNum].substring(0, terminator + 1) + '{\nif (' + method + '({ line: ' + printLineNumber + ' })) break;\n';
|
||||
line += '\n}\n';
|
||||
} else {
|
||||
// simpler
|
||||
line = line.substring(0, terminator + 1) + '{\nif (' + method + '({ line: ' + printLineNumber + ' })) break;\n' + line.substring(terminator + 1) + '\n}\n';
|
||||
}
|
||||
|
||||
if (openBrackets === 0 && character === '{') {
|
||||
// we've found the start of the loop, so insert the loop protection
|
||||
line = line.substring(0, index + 1) + ';\nif (' + method + '({ line: ' + lineNum + ' })) break;';
|
||||
recompiled.push(insertReset(lineNum, line));
|
||||
} else if (character === '{') {
|
||||
line = line.substring(0, index + 1) + ';\nif (' + method + '({ line: ' + printLineNumber + ' })) break;';
|
||||
}
|
||||
|
||||
// work out where to put the reset
|
||||
if (lineNum === originalLineNum) {
|
||||
line = insertReset(printLineNumber, line);
|
||||
} else {
|
||||
// insert the reset above the originalLineNum
|
||||
recompiled[originalLineNum] = insertReset(printLineNumber, recompiled[originalLineNum]);
|
||||
}
|
||||
|
||||
recompiled.push(line);
|
||||
return;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
// if we didn't find the start of the loop program,
|
||||
// then move on to the next line to work out whether
|
||||
// this is a one liner or if there's a new line to
|
||||
// get to the the curly.
|
||||
next = lines[i+1];
|
||||
|
||||
// reset the index to the start of the line and work forwards
|
||||
index = 0;
|
||||
do {
|
||||
character = next.substr(index, 1);
|
||||
|
||||
if (character === '{' || character === ';') {
|
||||
|
||||
// we found a curly, so we need to insert: `if (...)\n { dostuff();\n}`
|
||||
if (character === '{') {
|
||||
// we've found the start of the loop, so insert the loop protection
|
||||
next = next.substring(0, index + 1) + ';\nif (' + method + '({ line: ' + lineNum + ' })) break;';
|
||||
}
|
||||
|
||||
// this is the end of a mutliline one-liner: `if (...)\n dostuff();`
|
||||
if (character === ';') {
|
||||
// insert the loop protection extra new lines ensure we clear any comments on the original line
|
||||
next = '{\nif (' + method + '({ line: ' + lineNum + ' })) break;\n' + next + '\n}\n';
|
||||
}
|
||||
|
||||
recompiled.push(insertReset(lineNum, line));
|
||||
recompiled.push(next);
|
||||
ignore[i + 1] = true;
|
||||
return;
|
||||
if (index === line.length && lineNum < (lines.length-1)) {
|
||||
// move to the next line
|
||||
recompiled.push(line);
|
||||
lineNum++;
|
||||
line = lines[lineNum];
|
||||
ignore[lineNum] = true;
|
||||
index = 0;
|
||||
}
|
||||
|
||||
} while (++index < next.length);
|
||||
|
||||
|
||||
// just in case...but really we shouldn't get here.
|
||||
recompiled.push(line);
|
||||
}
|
||||
} else {
|
||||
// else we're a regular line, and we shouldn't be touched
|
||||
recompiled.push(line);
|
||||
|
||||
@ -14,7 +14,7 @@ var code = {
|
||||
onelinefor: 'var i = 0, j = 0;\nfor (; i < 10; i++) j = i * 10;\nreturn i;',
|
||||
simplewhile: 'var i = 0; while (i < 100) {\ni += 10;\n}\nreturn i;',
|
||||
onelinewhile: 'var i = 0; while (i < 100) i += 10;\nreturn i;',
|
||||
onelinewhile2: 'while (1) console.log("Ha.");',
|
||||
onelinewhile2: 'function noop(){}; while (1) noop("Ha.");',
|
||||
whiletrue: 'var i = 0;\nwhile(true) {\ni++;\n}\nreturn true;',
|
||||
irl1: 'var nums = [0,1];\n var total = 8;\n for(var i = 0; i <= total; i++){\n var newest = nums[i--]\n nums.push(newest);\n }\n return i;',
|
||||
irl2: 'var a = 0;\n for(var j=1;j<=2;j++){\n for(var i=1;i<=60000;i++) {\n a += 1;\n }\n }\n return a;',
|
||||
@ -25,6 +25,7 @@ var code = {
|
||||
onelinenewliner: "var b=0;\n function f(){b+=1;}\n for(var j=1;j<120000; j++)\n f();\nreturn j;",
|
||||
irl3: "Todos.Todo = DS.Model.extend({\n title: DS.attr('string'),\n isCompleted: DS.attr('boolean')\n });",
|
||||
brackets: 'var NUM=103, i, sqrt;\nfor(i=2; i<=Math.sqrt(NUM); i+=1){\n if(NUM % i === 0){\n console.log(NUM + " can be divided by " + i + ".");\n break;\n }\n}\nreturn i;',
|
||||
lotolines: 'var LIMIT = 10;\nvar num, lastNum, tmp;\nfor(num = 1, lastNum = 0;\n num < LIMIT;\n lastNum = num, num = tmp){\n\n tmp = num + lastNum;\n}\nreturn lastNum;',
|
||||
};
|
||||
|
||||
|
||||
@ -71,7 +72,7 @@ describe('loop', function () {
|
||||
var c = code.onelinewhile2;
|
||||
var compiled = loopProtect.rewriteLoops(c);
|
||||
assert(compiled !== c);
|
||||
console.log('---------' + c + '---------' + compiled);
|
||||
// console.log('\n---------\n' + c + '\n---------\n' + compiled);
|
||||
var result = run(compiled);
|
||||
assert(result === undefined);
|
||||
});
|
||||
@ -133,6 +134,10 @@ describe('loop', function () {
|
||||
it('should find one liners on multiple lines', function () {
|
||||
var c = code.onelinenewliner;
|
||||
var compiled = loopProtect.rewriteLoops(c);
|
||||
// console.log('\n----------');
|
||||
// console.log(c);
|
||||
// console.log('\n----------');
|
||||
// console.log(compiled);
|
||||
assert(compiled !== c);
|
||||
assert(spy(compiled) === 120000);
|
||||
});
|
||||
@ -143,4 +148,11 @@ describe('loop', function () {
|
||||
assert(compiled !== c);
|
||||
assert(spy(compiled) === 11);
|
||||
});
|
||||
|
||||
it('should not corrupt multi-line (on more than one line) loops', function () {
|
||||
var c = code.lotolines;
|
||||
var compiled = loopProtect.rewriteLoops(c);
|
||||
assert(compiled !== c);
|
||||
assert(spy(compiled) === 8);
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user