2015-11-18 05:25:16 +00:00
|
|
|
// what are the executeChallenge functions?
|
|
|
|
// Should be responsible for starting after a submit action
|
|
|
|
// Should not be responsible for displaying results
|
|
|
|
// Should return results
|
|
|
|
// should grab editor value
|
|
|
|
// depends on main editor
|
|
|
|
window.common = (function(global) {
|
|
|
|
const {
|
|
|
|
ga,
|
|
|
|
Rx: { Observable },
|
|
|
|
common = { init: [] }
|
|
|
|
} = global;
|
|
|
|
|
|
|
|
let attempts = 0;
|
|
|
|
const detectFunctionCall = /function\s*?\(|function\s+\w+\s*?\(/gi;
|
|
|
|
const detectUnsafeJQ = /\$\s*?\(\s*?\$\s*?\)/gi;
|
|
|
|
const detectUnsafeConsoleCall = /if\s\(null\)\sconsole\.log\(1\);/gi;
|
|
|
|
|
|
|
|
common.executeChallenge$ = function executeChallenge$() {
|
|
|
|
const code = common.editor.getValue();
|
|
|
|
const head = common.arrayToNewLineString(common.head);
|
|
|
|
const tail = common.arrayToNewLineString(common.tail);
|
|
|
|
|
|
|
|
attempts++;
|
|
|
|
|
|
|
|
ga('send', 'event', 'Challenge', 'ran-code', common.challengeName);
|
|
|
|
|
|
|
|
let openingComments = code.match(/\/\*/gi);
|
|
|
|
|
|
|
|
// checks if the number of opening comments(/*) matches the number of
|
|
|
|
// closing comments(*/)
|
2015-11-20 05:51:38 +00:00
|
|
|
return Observable.just({ code })
|
|
|
|
.flatMap(({ code }) => {
|
2015-11-18 05:25:16 +00:00
|
|
|
if (
|
|
|
|
code.match(/\$\s*?\(\s*?\$\s*?\)/gi) &&
|
|
|
|
openingComments &&
|
|
|
|
openingComments.length > code.match(/\*\//gi).length
|
|
|
|
) {
|
|
|
|
|
2015-11-20 05:51:38 +00:00
|
|
|
return Observable.throw({
|
2015-11-18 05:25:16 +00:00
|
|
|
err: 'SyntaxError: Unfinished multi-line comment',
|
2015-11-20 05:51:38 +00:00
|
|
|
code
|
2015-11-18 05:25:16 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
if (code.match(detectUnsafeJQ)) {
|
2015-11-20 05:51:38 +00:00
|
|
|
return Observable.throw({
|
2015-11-18 05:25:16 +00:00
|
|
|
err: 'Unsafe $($)',
|
2015-11-20 05:51:38 +00:00
|
|
|
code
|
2015-11-18 05:25:16 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
if (
|
|
|
|
code.match(/function/g) &&
|
|
|
|
!code.match(detectFunctionCall)
|
|
|
|
) {
|
2015-11-20 05:51:38 +00:00
|
|
|
return Observable.throw({
|
2015-11-18 05:25:16 +00:00
|
|
|
err: 'SyntaxError: Unsafe or unfinished function declaration',
|
2015-11-20 05:51:38 +00:00
|
|
|
code
|
2015-11-18 05:25:16 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
if (common.challengeType === '0') {
|
|
|
|
let openingComments = code.match(/\<\!\-\-/gi);
|
|
|
|
let closingComments = code.match(/\-\-\>/gi) || [];
|
|
|
|
if (
|
|
|
|
openingComments &&
|
|
|
|
openingComments.length > closingComments.length
|
|
|
|
) {
|
2015-11-20 05:51:38 +00:00
|
|
|
return Observable.throw({
|
2015-11-18 05:25:16 +00:00
|
|
|
err: 'SyntaxError: Unfinished HTML comment',
|
2015-11-20 05:51:38 +00:00
|
|
|
code
|
2015-11-18 05:25:16 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (code.match(detectUnsafeConsoleCall)) {
|
2015-11-20 05:51:38 +00:00
|
|
|
return Observable.throw({
|
2015-11-18 05:25:16 +00:00
|
|
|
err: 'Invalid if (null) console.log(1); detected',
|
2015-11-20 05:51:38 +00:00
|
|
|
code
|
2015-11-18 05:25:16 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// add head and tail and detect loops
|
2015-11-20 05:51:38 +00:00
|
|
|
return Observable.just({ code: head + code + tail, original: code });
|
|
|
|
})
|
|
|
|
.map(data => {
|
|
|
|
if (common.challengeType === common.challengeTypes.HTML) {
|
|
|
|
return common.getScriptCode(data);
|
|
|
|
}
|
2015-11-18 05:25:16 +00:00
|
|
|
|
2015-11-20 05:51:38 +00:00
|
|
|
return common.addTestsToString(Object.assign(
|
|
|
|
data,
|
|
|
|
{
|
|
|
|
code: common.removeComments(code),
|
|
|
|
tests: common.tests.slice()
|
|
|
|
}
|
|
|
|
));
|
|
|
|
})
|
|
|
|
.flatMap(common.detectLoops$)
|
|
|
|
.flatMap(({ err, code, data, userTests, original }) => {
|
|
|
|
if (err) {
|
|
|
|
return Observable.throw({ err });
|
|
|
|
}
|
2015-11-18 05:25:16 +00:00
|
|
|
|
2015-11-20 05:51:38 +00:00
|
|
|
return common.runTests$({
|
|
|
|
data,
|
|
|
|
code,
|
|
|
|
userTests,
|
|
|
|
original,
|
|
|
|
output: data.output.replace(/\\\"/gi, '')
|
2015-11-18 05:25:16 +00:00
|
|
|
});
|
2015-11-20 05:51:38 +00:00
|
|
|
})
|
|
|
|
.catch(e => {
|
|
|
|
return e && e.err ?
|
|
|
|
Observable.throw(e) :
|
|
|
|
Observable.throw({ err: e });
|
2015-11-18 05:25:16 +00:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
return common;
|
|
|
|
}(window));
|