fix: stop user code after 500ms of execution
Code like `var xs = []; while(true){ xs.push(1) }` can quickly run the browser out of memory causing it to crash. These changes stop user loops from running indefinitely so that common mistakes will no longer cause the browser to crash. Also, the user is informed if a long running loop is detected (js and jsx challenges) during preview or testing. Before this there was no protection for js challenges and no information was given to the user if they had created such a loop. Co-Authored-By: Tom <20648924+moT01@users.noreply.github.com> Co-Authored-By: mrugesh <1884376+raisedadead@users.noreply.github.com> Co-Authored-By: Randell Dawson <5313213+RandellDawson@users.noreply.github.com>
This commit is contained in:
committed by
mrugesh
parent
1a56f4d5f4
commit
f5feff386a
@@ -13,7 +13,7 @@ import {
|
||||
import * as Babel from '@babel/standalone';
|
||||
import presetEnv from '@babel/preset-env';
|
||||
import presetReact from '@babel/preset-react';
|
||||
import protect from 'loop-protect';
|
||||
import protect from '@freecodecamp/loop-protect';
|
||||
|
||||
import * as vinyl from '../utils/polyvinyl.js';
|
||||
import createWorker from '../utils/worker-executor';
|
||||
@@ -23,7 +23,26 @@ import createWorker from '../utils/worker-executor';
|
||||
import { filename as sassCompile } from '../../../../config/sass-compile';
|
||||
|
||||
const protectTimeout = 100;
|
||||
Babel.registerPlugin('loopProtection', protect(protectTimeout));
|
||||
const testProtectTimeout = 1500;
|
||||
const loopsPerTimeoutCheck = 2000;
|
||||
|
||||
function loopProtectCB(line) {
|
||||
console.log(
|
||||
`Potential infinite loop detected on line ${line}. Tests may fail if this is not changed.`
|
||||
);
|
||||
}
|
||||
|
||||
function testLoopProtectCB(line) {
|
||||
console.log(
|
||||
`Potential infinite loop detected on line ${line}. Tests may be failing because of this.`
|
||||
);
|
||||
}
|
||||
|
||||
Babel.registerPlugin('loopProtection', protect(protectTimeout, loopProtectCB));
|
||||
Babel.registerPlugin(
|
||||
'testLoopProtection',
|
||||
protect(testProtectTimeout, testLoopProtectCB, loopsPerTimeoutCheck)
|
||||
);
|
||||
|
||||
const babelOptionsJSX = {
|
||||
plugins: ['loopProtection'],
|
||||
@@ -31,9 +50,15 @@ const babelOptionsJSX = {
|
||||
};
|
||||
|
||||
const babelOptionsJS = {
|
||||
plugins: ['testLoopProtection'],
|
||||
presets: [presetEnv]
|
||||
};
|
||||
|
||||
const babelOptionsJSPreview = {
|
||||
...babelOptionsJS,
|
||||
plugins: ['loopProtection']
|
||||
};
|
||||
|
||||
const babelTransformCode = options => code =>
|
||||
Babel.transform(code, options).code;
|
||||
|
||||
@@ -69,28 +94,31 @@ function tryTransform(wrap = identity) {
|
||||
};
|
||||
}
|
||||
|
||||
export const babelTransformer = cond([
|
||||
[
|
||||
testJS,
|
||||
flow(
|
||||
partial(
|
||||
vinyl.transformHeadTailAndContents,
|
||||
tryTransform(babelTransformCode(babelOptionsJS))
|
||||
const babelTransformer = (preview = false) =>
|
||||
cond([
|
||||
[
|
||||
testJS,
|
||||
flow(
|
||||
partial(
|
||||
vinyl.transformHeadTailAndContents,
|
||||
tryTransform(
|
||||
babelTransformCode(preview ? babelOptionsJSPreview : babelOptionsJS)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
],
|
||||
[
|
||||
testJSX,
|
||||
flow(
|
||||
partial(
|
||||
vinyl.transformHeadTailAndContents,
|
||||
tryTransform(babelTransformCode(babelOptionsJSX))
|
||||
),
|
||||
partial(vinyl.setExt, 'js')
|
||||
)
|
||||
],
|
||||
[stubTrue, identity]
|
||||
]);
|
||||
],
|
||||
[
|
||||
testJSX,
|
||||
flow(
|
||||
partial(
|
||||
vinyl.transformHeadTailAndContents,
|
||||
tryTransform(babelTransformCode(babelOptionsJSX))
|
||||
),
|
||||
partial(vinyl.setExt, 'js')
|
||||
)
|
||||
],
|
||||
[stubTrue, identity]
|
||||
]);
|
||||
|
||||
const sassWorker = createWorker(sassCompile);
|
||||
async function transformSASS(element) {
|
||||
@@ -141,7 +169,14 @@ export const htmlTransformer = cond([
|
||||
|
||||
export const transformers = [
|
||||
replaceNBSP,
|
||||
babelTransformer,
|
||||
babelTransformer(),
|
||||
composeHTML,
|
||||
htmlTransformer
|
||||
];
|
||||
|
||||
export const transformersPreview = [
|
||||
replaceNBSP,
|
||||
babelTransformer(true),
|
||||
composeHTML,
|
||||
htmlTransformer
|
||||
];
|
||||
|
Reference in New Issue
Block a user