mirror of
https://github.com/zebrajr/react.git
synced 2025-12-06 12:20:20 +01:00
If a Scheduler profile runs without stopping, the event log will grow unbounded. Eventually it will run out of memory and the VM will throw an error. To prevent this from happening, let's automatically stop the profiler once the log exceeds a certain limit. We'll also print a warning with advice to call `stopLoggingProfilingEvents` explicitly.
75 lines
2.4 KiB
JavaScript
75 lines
2.4 KiB
JavaScript
/**
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
* Copyright (c) 2017, Amjad Masad
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
// Based on https://repl.it/site/blog/infinite-loops.
|
|
|
|
// This should be reasonable for all loops in the source.
|
|
// Note that if the numbers are too large, the tests will take too long to fail
|
|
// for this to be useful (each individual test case might hit an infinite loop).
|
|
const MAX_SOURCE_ITERATIONS = 1500;
|
|
// Code in tests themselves is permitted to run longer.
|
|
// For example, in the fuzz tester.
|
|
const MAX_TEST_ITERATIONS = 5000;
|
|
|
|
module.exports = ({types: t, template}) => {
|
|
// We set a global so that we can later fail the test
|
|
// even if the error ends up being caught by the code.
|
|
const buildGuard = template(`
|
|
if (%%iterator%%++ > %%maxIterations%%) {
|
|
global.infiniteLoopError = new RangeError(
|
|
'Potential infinite loop: exceeded ' +
|
|
%%maxIterations%% +
|
|
' iterations.'
|
|
);
|
|
throw global.infiniteLoopError;
|
|
}
|
|
`);
|
|
|
|
return {
|
|
visitor: {
|
|
'WhileStatement|ForStatement|DoWhileStatement': (path, file) => {
|
|
const filename = file.file.opts.filename;
|
|
const maxIterations = t.logicalExpression(
|
|
'||',
|
|
t.memberExpression(
|
|
t.identifier('global'),
|
|
t.identifier('__MAX_ITERATIONS__')
|
|
),
|
|
t.numericLiteral(
|
|
filename.indexOf('__tests__') === -1
|
|
? MAX_SOURCE_ITERATIONS
|
|
: MAX_TEST_ITERATIONS
|
|
)
|
|
);
|
|
|
|
// An iterator that is incremented with each iteration
|
|
const iterator = path.scope.parent.generateUidIdentifier('loopIt');
|
|
const iteratorInit = t.numericLiteral(0);
|
|
path.scope.parent.push({
|
|
id: iterator,
|
|
init: iteratorInit,
|
|
});
|
|
// If statement and throw error if it matches our criteria
|
|
const guard = buildGuard({
|
|
iterator,
|
|
maxIterations,
|
|
});
|
|
// No block statement e.g. `while (1) 1;`
|
|
if (!path.get('body').isBlockStatement()) {
|
|
const statement = path.get('body').node;
|
|
path.get('body').replaceWith(t.blockStatement([guard, statement]));
|
|
} else {
|
|
path.get('body').unshiftContainer('body', guard);
|
|
}
|
|
},
|
|
},
|
|
};
|
|
};
|