JS: don't treat return, break and continue as split points when possible
This commit is contained in:
@@ -107,7 +107,18 @@ public class JsFor extends SourceInfoAwareJsNode implements JsStatement {
|
|||||||
if (initExpression != null) {
|
if (initExpression != null) {
|
||||||
initExpression = v.accept(initExpression);
|
initExpression = v.accept(initExpression);
|
||||||
} else if (initVars != null) {
|
} else if (initVars != null) {
|
||||||
initVars = v.acceptStatement(initVars);
|
JsStatement newInitVars = v.<JsStatement>acceptStatement(initVars);
|
||||||
|
if (newInitVars instanceof JsVars) {
|
||||||
|
initVars = (JsVars) newInitVars;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
initVars = null;
|
||||||
|
if (newInitVars instanceof JsExpressionStatement) {
|
||||||
|
initExpression = ((JsExpressionStatement) newInitVars).getExpression();
|
||||||
|
} else if (newInitVars != null) {
|
||||||
|
ctx.addPrevious(newInitVars);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (condition != null) {
|
if (condition != null) {
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ class CoroutineBodyTransformer(
|
|||||||
|
|
||||||
fun preProcess(node: JsNode) {
|
fun preProcess(node: JsNode) {
|
||||||
breakContinueTargetStatements += node.collectBreakContinueTargets()
|
breakContinueTargetStatements += node.collectBreakContinueTargets()
|
||||||
nodesToSplit = node.collectNodesToSplit()
|
nodesToSplit = node.collectNodesToSplit(breakContinueTargetStatements)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun postProcess(): List<CoroutineBlock> {
|
fun postProcess(): List<CoroutineBlock> {
|
||||||
|
|||||||
@@ -21,11 +21,13 @@ import com.google.dart.compiler.backend.js.ast.metadata.*
|
|||||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||||
import org.jetbrains.kotlin.utils.singletonOrEmptyList
|
import org.jetbrains.kotlin.utils.singletonOrEmptyList
|
||||||
|
|
||||||
fun JsNode.collectNodesToSplit(): Set<JsNode> {
|
fun JsNode.collectNodesToSplit(breakContinueTargets: Map<JsContinue, JsStatement>): Set<JsNode> {
|
||||||
|
val root = this
|
||||||
val nodes = mutableSetOf<JsNode>()
|
val nodes = mutableSetOf<JsNode>()
|
||||||
|
|
||||||
val visitor = object : RecursiveJsVisitor() {
|
val visitor = object : RecursiveJsVisitor() {
|
||||||
var childrenInSet = false
|
var childrenInSet = false
|
||||||
|
var finallyLevel = 0
|
||||||
|
|
||||||
override fun visitInvocation(invocation: JsInvocation) {
|
override fun visitInvocation(invocation: JsInvocation) {
|
||||||
super.visitInvocation(invocation)
|
super.visitInvocation(invocation)
|
||||||
@@ -37,23 +39,41 @@ fun JsNode.collectNodesToSplit(): Set<JsNode> {
|
|||||||
|
|
||||||
override fun visitReturn(x: JsReturn) {
|
override fun visitReturn(x: JsReturn) {
|
||||||
super.visitReturn(x)
|
super.visitReturn(x)
|
||||||
nodes += x
|
|
||||||
childrenInSet = true
|
if (root in nodes || finallyLevel > 0) {
|
||||||
|
nodes += x
|
||||||
|
childrenInSet = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitBreak(x: JsBreak) {
|
override fun visitBreak(x: JsBreak) {
|
||||||
super.visitBreak(x)
|
super.visitBreak(x)
|
||||||
|
|
||||||
// It's a simplification
|
val breakTarget = breakContinueTargets[x]!!
|
||||||
// TODO: don't split break and continue statements when possible
|
if (breakTarget in nodes) {
|
||||||
nodes += x
|
nodes += x
|
||||||
childrenInSet = true
|
childrenInSet = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitContinue(x: JsContinue) {
|
override fun visitContinue(x: JsContinue) {
|
||||||
super.visitContinue(x)
|
super.visitContinue(x)
|
||||||
nodes += x
|
|
||||||
childrenInSet = true
|
val continueTarget = breakContinueTargets[x]!!
|
||||||
|
if (continueTarget in nodes) {
|
||||||
|
nodes += x
|
||||||
|
childrenInSet = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitTry(x: JsTry) {
|
||||||
|
if (x.finallyBlock != null) {
|
||||||
|
finallyLevel++
|
||||||
|
}
|
||||||
|
super.visitTry(x)
|
||||||
|
if (x.finallyBlock != null) {
|
||||||
|
finallyLevel--
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitElement(node: JsNode) {
|
override fun visitElement(node: JsNode) {
|
||||||
@@ -71,8 +91,12 @@ fun JsNode.collectNodesToSplit(): Set<JsNode> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
visitor.accept(this)
|
while (true) {
|
||||||
visitor.accept(this)
|
val countBefore = nodes.size
|
||||||
|
visitor.accept(this)
|
||||||
|
val countAfter = nodes.size
|
||||||
|
if (countAfter == countBefore) break
|
||||||
|
}
|
||||||
|
|
||||||
return nodes
|
return nodes
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user