prevent infinite loop

pull/3887/head
Tan Li Hau 5 years ago
parent 31a81d3553
commit ace35336b7

@ -27,7 +27,7 @@ import Slot from './nodes/Slot';
import { Node, ImportDeclaration, Identifier, Program, ExpressionStatement, AssignmentExpression, Literal } from 'estree';
import add_to_set from './utils/add_to_set';
import check_graph_for_cycles from './utils/check_graph_for_cycles';
import { print, x } from 'code-red';
import { print, x, b } from 'code-red';
interface ComponentOptions {
namespace?: string;
@ -722,6 +722,8 @@ export default class Component {
toRemove.unshift([parent, prop, index]);
};
const toInsert = new Map();
walk(content, {
enter(node, parent, prop, index) {
if (map.has(node)) {
@ -747,12 +749,37 @@ export default class Component {
}
component.warn_on_undefined_store_value_references(node, parent, scope);
if (component.compile_options.dev) {
const to_insert_for_loop_protect = component.loop_protect(node, prop, index);
if (to_insert_for_loop_protect) {
if (!Array.isArray(parent[prop])) {
parent[prop] = {
type: 'BlockStatement',
body: [to_insert_for_loop_protect.node, node],
};
} else {
// can't insert directly, will screw up the index in the for-loop of estree-walker
if (!toInsert.has(parent)) {
toInsert.set(parent, []);
}
toInsert.get(parent).push(to_insert_for_loop_protect);
}
}
}
},
leave(node) {
if (map.has(node)) {
scope = scope.parent;
}
if (toInsert.has(node)) {
const nodes_to_insert = toInsert.get(node);
for (const { index, prop, node: node_to_insert } of nodes_to_insert.reverse()) {
node[prop].splice(index, 0, node_to_insert);
}
toInsert.delete(node);
}
},
});
@ -836,6 +863,35 @@ export default class Component {
}
}
loop_protect(node, prop, index) {
if (node.type === 'WhileStatement' ||
node.type === 'ForStatement' ||
node.type === 'DoWhileStatement') {
const id = this.get_unique_name('LP');
this.add_var({
name: id.name,
internal: true,
});
const before = b`const ${id} = Date.now();`;
const inside = b`
if (Date.now() - ${id} > 100) {
throw new Error('Infinite loop detected');
}
`;
// wrap expression statement with BlockStatement
if (node.body.type !== 'BlockStatement') {
node.body = {
type: 'BlockStatement',
body: [node.body],
};
}
node.body.body.push(inside[0]);
return { index, prop, node: before[0] };
}
return null;
}
invalidate(name, value?) {
const variable = this.var_lookup.get(name);

@ -0,0 +1,5 @@
export default {
options: {
dev: true
}
};

@ -0,0 +1,126 @@
/* generated by Svelte vX.Y.Z */
import {
SvelteComponentDev,
dispatch_dev,
init,
noop,
safe_not_equal
} from "svelte/internal";
const file = undefined;
function create_fragment(ctx) {
const block = {
c: noop,
l: function claim(nodes) {
throw new Error("options.hydrate only works if the component was compiled with the `hydratable: true` option");
},
m: noop,
p: noop,
i: noop,
o: noop,
d: noop
};
dispatch_dev("SvelteRegisterBlock", {
block,
id: create_fragment.name,
type: "component",
source: "",
ctx
});
return block;
}
function instance($$self) {
const LP = Date.now();
while (true) {
foo();
if (Date.now() - LP > 100) {
throw new Error("Infinite loop detected");
}
}
const LP_1 = Date.now();
for (; ; ) {
foo();
if (Date.now() - LP_1 > 100) {
throw new Error("Infinite loop detected");
}
}
const LP_2 = Date.now();
while (true) {
foo();
if (Date.now() - LP_2 > 100) {
throw new Error("Infinite loop detected");
}
}
const LP_4 = Date.now();
do {
foo();
if (Date.now() - LP_4 > 100) {
throw new Error("Infinite loop detected");
}
} while (true);
$$self.$capture_state = () => {
return {};
};
$$self.$inject_state = $$props => {
};
$: {
const LP_3 = Date.now();
while (true) {
foo();
if (Date.now() - LP_3 > 100) {
throw new Error("Infinite loop detected");
}
}
}
$: {
const LP_5 = Date.now();
do {
foo();
if (Date.now() - LP_5 > 100) {
throw new Error("Infinite loop detected");
}
} while (true);
}
return {};
}
class Component extends SvelteComponentDev {
constructor(options) {
super(options);
init(this, options, instance, create_fragment, safe_not_equal, {});
dispatch_dev("SvelteRegisterComponent", {
component: this,
tagName: "Component",
options,
id: create_fragment.name
});
}
}
export default Component;

@ -0,0 +1,12 @@
<script>
while(true) {
foo();
}
for(;;) {
foo();
}
while(true) foo();
$: while(true) foo();
do foo(); while(true);
$: do foo(); while(true);
</script>

@ -0,0 +1,6 @@
export default {
error: 'Infinite loop detected',
compileOptions: {
dev: true,
}
};

@ -0,0 +1,5 @@
<script>
while(true) {
// do nothing
}
</script>
Loading…
Cancel
Save