[feat] opt-out loopGuard for async loops (#6963)

pull/7015/head
Tan Li Hau 3 years ago committed by GitHub
parent f2d4a10741
commit 6ecc3e4d6a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -24,7 +24,7 @@ import TemplateScope from './nodes/shared/TemplateScope';
import fuzzymatch from '../utils/fuzzymatch'; import fuzzymatch from '../utils/fuzzymatch';
import get_object from './utils/get_object'; import get_object from './utils/get_object';
import Slot from './nodes/Slot'; import Slot from './nodes/Slot';
import { Node, ImportDeclaration, ExportNamedDeclaration, Identifier, ExpressionStatement, AssignmentExpression, Literal, Property, RestElement, ExportDefaultDeclaration, ExportAllDeclaration } from 'estree'; import { Node, ImportDeclaration, ExportNamedDeclaration, Identifier, ExpressionStatement, AssignmentExpression, Literal, Property, RestElement, ExportDefaultDeclaration, ExportAllDeclaration, FunctionDeclaration, FunctionExpression } from 'estree';
import add_to_set from './utils/add_to_set'; import add_to_set from './utils/add_to_set';
import check_graph_for_cycles from './utils/check_graph_for_cycles'; import check_graph_for_cycles from './utils/check_graph_for_cycles';
import { print, b } from 'code-red'; import { print, b } from 'code-red';
@ -766,12 +766,13 @@ export default class Component {
}; };
let scope_updated = false; let scope_updated = false;
let generator_count = 0; const current_function_stack = [];
let current_function: FunctionDeclaration | FunctionExpression = null;
walk(content, { walk(content, {
enter(node: Node, parent: Node, prop, index) { enter(node: Node, parent: Node, prop, index) {
if ((node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression') && node.generator === true) { if ((node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression')) {
generator_count++; current_function_stack.push(current_function = node);
} }
if (map.has(node)) { if (map.has(node)) {
@ -800,12 +801,13 @@ export default class Component {
}, },
leave(node: Node) { leave(node: Node) {
if ((node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression') && node.generator === true) { if ((node.type === 'FunctionDeclaration' || node.type === 'FunctionExpression')) {
generator_count--; current_function_stack.pop();
current_function = current_function_stack[current_function_stack.length - 1];
} }
// do it on leave, to prevent infinite loop // do it on leave, to prevent infinite loop
if (component.compile_options.dev && component.compile_options.loopGuardTimeout > 0 && generator_count <= 0) { if (component.compile_options.dev && component.compile_options.loopGuardTimeout > 0 && (!current_function || (!current_function.generator && !current_function.async))) {
const to_replace_for_loop_protect = component.loop_protect(node, scope, component.compile_options.loopGuardTimeout); const to_replace_for_loop_protect = component.loop_protect(node, scope, component.compile_options.loopGuardTimeout);
if (to_replace_for_loop_protect) { if (to_replace_for_loop_protect) {
this.replace(to_replace_for_loop_protect); this.replace(to_replace_for_loop_protect);

@ -0,0 +1,9 @@
export default {
compileOptions: {
dev: true,
loopGuardTimeout: 1
},
async test({ component }) {
await component.run_async_function();
}
};

@ -0,0 +1,12 @@
<script>
export async function run_async_function() {
await loop();
}
async function loop() {
let i = 0;
while (i ++ < 5) {
await new Promise(resolve => setTimeout(resolve, 20));
}
}
</script>

@ -2,5 +2,8 @@ export default {
compileOptions: { compileOptions: {
dev: true, dev: true,
loopGuardTimeout: 1 loopGuardTimeout: 1
},
async test({ component }) {
await component.run_generator();
} }
}; };

@ -1,10 +1,12 @@
<script> <script>
const it = gen(); export async function run_generator() {
it.next(); const it = gen();
it.next();
await new Promise(resolve => setTimeout(resolve, 20));
setTimeout(() => {
it.next(); it.next();
}, 20) }
function* gen() { function* gen() {
while (true) { while (true) {

Loading…
Cancel
Save