Merge pull request #5001 from FreeCodeCamp/feature/disable-javascript
Add ability to disable user code on page load
This commit is contained in:
@ -42,6 +42,8 @@ window.common = (function(global) {
|
|||||||
return decoded
|
return decoded
|
||||||
.split('?')
|
.split('?')
|
||||||
.splice(1)
|
.splice(1)
|
||||||
|
.pop()
|
||||||
|
.split('&')
|
||||||
.reduce(function(found, param) {
|
.reduce(function(found, param) {
|
||||||
var key = param.split('=')[0];
|
var key = param.split('=')[0];
|
||||||
if (key === 'solution') {
|
if (key === 'solution') {
|
||||||
@ -55,6 +57,23 @@ window.common = (function(global) {
|
|||||||
codeUri.isInQuery(location.search) ||
|
codeUri.isInQuery(location.search) ||
|
||||||
codeUri.isInQuery(location.hash);
|
codeUri.isInQuery(location.hash);
|
||||||
},
|
},
|
||||||
|
getKeyInQuery(query, keyToFind = '') {
|
||||||
|
return query
|
||||||
|
.split('&')
|
||||||
|
.reduce(function(oldValue, param) {
|
||||||
|
var key = param.split('=')[0];
|
||||||
|
var value = param.split('=')[1];
|
||||||
|
if (key === keyToFind) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return oldValue;
|
||||||
|
}, null);
|
||||||
|
},
|
||||||
|
getSolutionFromQuery(query = '') {
|
||||||
|
return decodeFcc(
|
||||||
|
codeUri.decode(codeUri.getKeyInQuery(query, 'solution'))
|
||||||
|
);
|
||||||
|
},
|
||||||
parse: function() {
|
parse: function() {
|
||||||
if (!codeUri.enabled) {
|
if (!codeUri.enabled) {
|
||||||
return null;
|
return null;
|
||||||
@ -62,6 +81,7 @@ window.common = (function(global) {
|
|||||||
var query;
|
var query;
|
||||||
if (location.search && codeUri.isInQuery(location.search)) {
|
if (location.search && codeUri.isInQuery(location.search)) {
|
||||||
query = location.search.replace(/^\?/, '');
|
query = location.search.replace(/^\?/, '');
|
||||||
|
|
||||||
if (history && typeof history.replaceState === 'function') {
|
if (history && typeof history.replaceState === 'function') {
|
||||||
history.replaceState(
|
history.replaceState(
|
||||||
history.state,
|
history.state,
|
||||||
@ -73,30 +93,29 @@ window.common = (function(global) {
|
|||||||
} else {
|
} else {
|
||||||
query = location.hash.replace(/^\#\?/, '');
|
query = location.hash.replace(/^\#\?/, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!query) {
|
if (!query) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return query
|
return this.getSolutionFromQuery(query);
|
||||||
.split('&')
|
|
||||||
.reduce(function(solution, param) {
|
|
||||||
var key = param.split('=')[0];
|
|
||||||
var value = param.split('=')[1];
|
|
||||||
if (key === 'solution') {
|
|
||||||
return decodeFcc(codeUri.decode(value || ''));
|
|
||||||
}
|
|
||||||
return solution;
|
|
||||||
}, null);
|
|
||||||
},
|
},
|
||||||
querify: function(solution) {
|
querify: function(solution) {
|
||||||
if (!codeUri.enabled) {
|
if (!codeUri.enabled) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (history && typeof history.replaceState === 'function') {
|
if (history && typeof history.replaceState === 'function') {
|
||||||
|
// grab the url up to the query
|
||||||
|
// destroy any hash symbols still clinging to life
|
||||||
|
const url = (location.href.split('?')[0]).replace(/(#*)$/, '');
|
||||||
history.replaceState(
|
history.replaceState(
|
||||||
history.state,
|
history.state,
|
||||||
null,
|
null,
|
||||||
'?solution=' + codeUri.encode(encodeFcc(solution))
|
url +
|
||||||
|
'#?' +
|
||||||
|
(codeUri.shouldRun() ? '' : 'run=disabled&') +
|
||||||
|
'solution=' +
|
||||||
|
codeUri.encode(encodeFcc(solution))
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
location.hash = '?solution=' +
|
location.hash = '?solution=' +
|
||||||
@ -105,7 +124,13 @@ window.common = (function(global) {
|
|||||||
|
|
||||||
return solution;
|
return solution;
|
||||||
},
|
},
|
||||||
enabled: true
|
enabled: true,
|
||||||
|
shouldRun() {
|
||||||
|
return !this.getKeyInQuery(
|
||||||
|
(location.search || location.hash).replace(/^(\?|#\?)/, ''),
|
||||||
|
'run'
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
common.init.push(function() {
|
common.init.push(function() {
|
||||||
@ -113,6 +138,7 @@ window.common = (function(global) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
common.codeUri = codeUri;
|
common.codeUri = codeUri;
|
||||||
|
common.shouldRun = () => codeUri.shouldRun();
|
||||||
|
|
||||||
return common;
|
return common;
|
||||||
}(window));
|
}(window));
|
||||||
|
@ -34,6 +34,11 @@ window.common = (function(global) {
|
|||||||
body { padding: 0px 3px 0px 3px; }
|
body { padding: 0px 3px 0px 3px; }
|
||||||
</style>
|
</style>
|
||||||
`;
|
`;
|
||||||
|
const codeDisabledError = `
|
||||||
|
<script>
|
||||||
|
window.__err = new Error('code has been disabled');
|
||||||
|
</script>
|
||||||
|
`;
|
||||||
|
|
||||||
const iFrameScript$ =
|
const iFrameScript$ =
|
||||||
common.getScriptContent$('/js/iFrameScripts.js').shareReplay();
|
common.getScriptContent$('/js/iFrameScripts.js').shareReplay();
|
||||||
@ -74,7 +79,7 @@ window.common = (function(global) {
|
|||||||
preview.write(
|
preview.write(
|
||||||
libraryIncludes +
|
libraryIncludes +
|
||||||
jQuery +
|
jQuery +
|
||||||
code +
|
(common.shouldRun() ? code : codeDisabledError) +
|
||||||
'<!-- -->' +
|
'<!-- -->' +
|
||||||
iframeScript
|
iframeScript
|
||||||
);
|
);
|
||||||
|
@ -11,6 +11,9 @@ window.$(document).ready(function() {
|
|||||||
var common = parent.common;
|
var common = parent.common;
|
||||||
|
|
||||||
common.getJsOutput = function evalJs(code = '') {
|
common.getJsOutput = function evalJs(code = '') {
|
||||||
|
if (window.__err || !common.shouldRun()) {
|
||||||
|
return window.__err || 'code disabled';
|
||||||
|
}
|
||||||
let output;
|
let output;
|
||||||
try {
|
try {
|
||||||
/* eslint-disable no-eval */
|
/* eslint-disable no-eval */
|
||||||
|
@ -20,6 +20,7 @@ if (typeof DEBUG === 'undefined') { DEBUG = true; }
|
|||||||
var reSingle = /\b(for|while|do)\b/;
|
var reSingle = /\b(for|while|do)\b/;
|
||||||
var labelRe = /\b([a-z_]{1}\w+:)/i;
|
var labelRe = /\b([a-z_]{1}\w+:)/i;
|
||||||
var comments = /(?:\/\*(?:[\s\S]*?)\*\/)|(?:([\s;])+\/\/(?:.*)$)/gm;
|
var comments = /(?:\/\*(?:[\s\S]*?)\*\/)|(?:([\s;])+\/\/(?:.*)$)/gm;
|
||||||
|
var loopTimeout = 500;
|
||||||
|
|
||||||
var loopProtect = rewriteLoops;
|
var loopProtect = rewriteLoops;
|
||||||
|
|
||||||
@ -404,8 +405,7 @@ if (typeof DEBUG === 'undefined') { DEBUG = true; }
|
|||||||
}
|
}
|
||||||
|
|
||||||
line.hit++;
|
line.hit++;
|
||||||
if ((now - line.time) > 100) {//} && line.hit !== line.last+1) {
|
if ((now - line.time) > loopTimeout) {//} && line.hit !== line.last+1) {
|
||||||
// We've spent over 100ms on this loop... smells infinite.
|
|
||||||
loopProtect.hit(state.line);
|
loopProtect.hit(state.line);
|
||||||
// Returning true prevents the loop running again
|
// Returning true prevents the loop running again
|
||||||
return true;
|
return true;
|
||||||
|
Reference in New Issue
Block a user