helperise loop protection

pull/3890/head
Richard Harris 6 years ago
parent 0dca28895c
commit 47cac13b7d

@ -717,12 +717,12 @@ export default class Component {
let scope = instance_scope; let scope = instance_scope;
const toRemove = []; const to_remove = [];
const remove = (parent, prop, index) => { const remove = (parent, prop, index) => {
toRemove.unshift([parent, prop, index]); to_remove.unshift([parent, prop, index]);
}; };
const toInsert = new Map(); const to_insert = new Map();
walk(content, { walk(content, {
enter(node, parent, prop, index) { enter(node, parent, prop, index) {
@ -760,10 +760,10 @@ export default class Component {
}; };
} else { } else {
// can't insert directly, will screw up the index in the for-loop of estree-walker // can't insert directly, will screw up the index in the for-loop of estree-walker
if (!toInsert.has(parent)) { if (!to_insert.has(parent)) {
toInsert.set(parent, []); to_insert.set(parent, []);
} }
toInsert.get(parent).push(to_insert_for_loop_protect); to_insert.get(parent).push(to_insert_for_loop_protect);
} }
} }
} }
@ -773,17 +773,17 @@ export default class Component {
if (map.has(node)) { if (map.has(node)) {
scope = scope.parent; scope = scope.parent;
} }
if (toInsert.has(node)) { if (to_insert.has(node)) {
const nodes_to_insert = toInsert.get(node); const nodes_to_insert = to_insert.get(node);
for (const { index, prop, node: node_to_insert } of nodes_to_insert.reverse()) { for (const { index, prop, node: node_to_insert } of nodes_to_insert.reverse()) {
node[prop].splice(index, 0, node_to_insert); node[prop].splice(index, 0, node_to_insert);
} }
toInsert.delete(node); to_insert.delete(node);
} }
}, },
}); });
for (const [parent, prop, index] of toRemove) { for (const [parent, prop, index] of to_remove) {
if (parent) { if (parent) {
if (index !== null) { if (index !== null) {
parent[prop].splice(index, 1); parent[prop].splice(index, 1);
@ -867,18 +867,15 @@ export default class Component {
if (node.type === 'WhileStatement' || if (node.type === 'WhileStatement' ||
node.type === 'ForStatement' || node.type === 'ForStatement' ||
node.type === 'DoWhileStatement') { node.type === 'DoWhileStatement') {
const id = this.get_unique_name('LP'); const guard = this.get_unique_name('guard');
this.add_var({ this.add_var({
name: id.name, name: guard.name,
internal: true, internal: true,
}); });
const before = b`const ${id} = Date.now();`; const before = b`const ${guard} = @loop_guard()`;
const inside = b` const inside = b`${guard}();`;
if (Date.now() - ${id} > 100) {
throw new Error('Infinite loop detected');
}
`;
// wrap expression statement with BlockStatement // wrap expression statement with BlockStatement
if (node.body.type !== 'BlockStatement') { if (node.body.type !== 'BlockStatement') {
node.body = { node.body = {

@ -95,3 +95,12 @@ export class SvelteComponentDev extends SvelteComponent {
}; };
} }
} }
export function loop_guard() {
const start = Date.now();
return () => {
if (Date.now() - start > 100) {
throw new Error(`Infinite loop detected`);
}
};
}

@ -3,6 +3,7 @@ import {
SvelteComponentDev, SvelteComponentDev,
dispatch_dev, dispatch_dev,
init, init,
loop_guard,
noop, noop,
safe_not_equal safe_not_equal
} from "svelte/internal"; } from "svelte/internal";
@ -34,44 +35,32 @@ function create_fragment(ctx) {
} }
function instance($$self) { function instance($$self) {
const LP = Date.now(); const guard = loop_guard();
while (true) { while (true) {
foo(); foo();
guard();
if (Date.now() - LP > 100) {
throw new Error("Infinite loop detected");
}
} }
const LP_1 = Date.now(); const guard_1 = loop_guard();
for (; ; ) { for (; ; ) {
foo(); foo();
guard_1();
if (Date.now() - LP_1 > 100) {
throw new Error("Infinite loop detected");
}
} }
const LP_2 = Date.now(); const guard_2 = loop_guard();
while (true) { while (true) {
foo(); foo();
guard_2();
if (Date.now() - LP_2 > 100) {
throw new Error("Infinite loop detected");
}
} }
const LP_4 = Date.now(); const guard_4 = loop_guard();
do { do {
foo(); foo();
guard_4();
if (Date.now() - LP_4 > 100) {
throw new Error("Infinite loop detected");
}
} while (true); } while (true);
$$self.$capture_state = () => { $$self.$capture_state = () => {
@ -79,30 +68,24 @@ function instance($$self) {
}; };
$$self.$inject_state = $$props => { $$self.$inject_state = $$props => {
}; };
$: { $: {
const LP_3 = Date.now(); const guard_3 = loop_guard();
while (true) { while (true) {
foo(); foo();
guard_3();
if (Date.now() - LP_3 > 100) {
throw new Error("Infinite loop detected");
}
} }
} }
$: { $: {
const LP_5 = Date.now(); const guard_5 = loop_guard();
do { do {
foo(); foo();
guard_5();
if (Date.now() - LP_5 > 100) {
throw new Error("Infinite loop detected");
}
} while (true); } while (true);
} }
Loading…
Cancel
Save