Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/scripts/frame.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import infiniteLoopDetector from './makeitsafe.js';
console.log(infiniteLoopDetector);
let infDetector = infiniteLoopDetector.infiniteLoopDetector;
console.log(infDetector);

// Defaults in case a game doesn't load.
var code = "console.error('Nothing to run!!')";
let image_lookup = {};
Expand Down Expand Up @@ -82,9 +87,15 @@ let meta = {
}
console.dispatchEvent("evaluate", item);
};

code = infDetector.wrap(code)
try {
eval(code);
} catch (e) {
if (e.type === 'InfiniteLoopError') {
console.err('infinite loop detected')
}

var err = e.constructor(e.message);
let trace = e.stack.split("\n")[1].split(":");
err.lineNumber = trace[trace.length - 2];
Expand Down
49 changes: 49 additions & 0 deletions src/scripts/makeitsafe.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// TODO: Clean up. Not really wriotten for modules and a bit of a hack as is.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a bit of a speil. I think to make this play better with modules, it should be rewritten

// Imports should be better, also may as well make this a proper javascript
// class opposed to whatever this is.

var infiniteLoopDetector = (function() {
var map = {}

// define an InfiniteLoopError class
function InfiniteLoopError(msg, type) {
Error.call(this ,msg)
this.type = 'InfiniteLoopError'
}

function infiniteLoopDetector(id) {
if (id in map) { // Not the first execution, it can be optimized here, the performance is too low
if (Date.now() - map[id] > 1000) {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoded 1 second? Maybe we can make this adjustable? Or do you think 1 second is fine?

delete map[id]
throw new Error('Loop running too long!', 'InfiniteLoopError')
}
} else { // First run, record the time the loop started. All the judgments that are not first run are written in the previous if because the above will be executed more times
map[id] = Date.now()
}
}

infiniteLoopDetector.wrap = function(codeStr) {
if (typeof codeStr !== 'string') {
throw new Error('Can only wrap code represented by string, not any other thing at the time! If you want to wrap a function, convert it to string first.')
}
// Replaces potential infite loop areas with a bit of guard code that makes
// and makes sure that the loop doesn't exceed some value of execution time.
//
// this is not a strong regex, but enough to use at the time
let response = codeStr.replace(/for *\(.*\{|while *\(.*\{|do *\{/g, function(loopHead) {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lol, this regex is such a hack- but works well enough I guess.

var id = parseInt(Math.random() * Number.MAX_SAFE_INTEGER)
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kmsalah
Opposed to random number here, maybe we use the line number and character offset. Need to be careful since we could feasible have multiple loops on one line.

But this would let us create more meaningful errors as well opposed to "Loop running too long"

return `infDetector(${id});${loopHead}infDetector(${id});`
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

infDetector matches the var in frame.js. But obviously this is very brittle as is.

});
// console.log(response);
return response;
}
infiniteLoopDetector.unwrap = function(codeStr) {
return codeStr.replace(/infiniteLoopDetector\([0-9]*?\);/g, '')
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Woops. Bug. This should be infDectector

But also, maybe this function isn't needed? When are we ever going to call unwrap

}

return infiniteLoopDetector
}())

module.exports.infiniteLoopDetector = infiniteLoopDetector;

// todo: copied from https://github.com/xieranmaya/infinite-loop-detector/blob/master/infinite-loop-detector.js