Prevent JS AST nodes of several types to be shared
This commit is contained in:
@@ -25,7 +25,7 @@ import org.jetbrains.kotlin.js.inline.util.collectBreakContinueTargets
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||
import org.jetbrains.kotlin.utils.DFS
|
||||
|
||||
class CoroutineBodyTransformer(private val program: JsProgram, private val context: CoroutineTransformationContext) : RecursiveJsVisitor() {
|
||||
class CoroutineBodyTransformer(private val context: CoroutineTransformationContext) : RecursiveJsVisitor() {
|
||||
private val entryBlock = context.entryBlock
|
||||
private val globalCatchBlock = context.globalCatchBlock
|
||||
private var currentBlock = entryBlock
|
||||
@@ -55,7 +55,7 @@ class CoroutineBodyTransformer(private val program: JsProgram, private val conte
|
||||
currentBlock.statements += JsReturn()
|
||||
val graph = entryBlock.buildGraph(globalCatchBlock)
|
||||
val orderedBlocks = DFS.topologicalOrder(listOf(entryBlock)) { graph[it].orEmpty() }
|
||||
orderedBlocks.replaceCoroutineFlowStatements(context, program)
|
||||
orderedBlocks.replaceCoroutineFlowStatements(context)
|
||||
return orderedBlocks
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ class CoroutineBodyTransformer(private val program: JsProgram, private val conte
|
||||
currentStatements += stateAndJump(bodyEntryBlock, x)
|
||||
|
||||
currentBlock = bodyEntryBlock
|
||||
if (x.condition != JsLiteral.TRUE) {
|
||||
if (!JsLiteral.isTrueBoolean(x.condition)) {
|
||||
currentStatements += JsIf(JsAstUtils.notOptimized(x.condition), JsBlock(stateAndJump(successor, x))).apply { source = x.source }
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ class CoroutineBodyTransformer(private val program: JsProgram, private val conte
|
||||
x.body.accept(this)
|
||||
}
|
||||
|
||||
if (x.condition != JsLiteral.TRUE) {
|
||||
if (!JsLiteral.isTrueBoolean(x.condition)) {
|
||||
val jsIf = JsIf(JsAstUtils.notOptimized(x.condition), JsBlock(stateAndJump(successor, x))).apply { source = x.source }
|
||||
currentStatements.add(jsIf)
|
||||
}
|
||||
@@ -168,7 +168,7 @@ class CoroutineBodyTransformer(private val program: JsProgram, private val conte
|
||||
currentStatements += stateAndJump(bodyEntryBlock, x)
|
||||
|
||||
currentBlock = bodyEntryBlock
|
||||
if (x.condition != null && x.condition != JsLiteral.TRUE) {
|
||||
if (x.condition != null && !JsLiteral.isTrueBoolean(x.condition)) {
|
||||
currentStatements += JsIf(JsAstUtils.notOptimized(x.condition), JsBlock(stateAndJump(successor, x))).apply { source = x.source }
|
||||
}
|
||||
|
||||
|
||||
+16
-16
@@ -25,7 +25,7 @@ import org.jetbrains.kotlin.js.inline.util.getInnerFunction
|
||||
import org.jetbrains.kotlin.js.translate.context.Namer
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||
|
||||
class CoroutineFunctionTransformer(private val program: JsProgram, private val function: JsFunction, name: String?) {
|
||||
class CoroutineFunctionTransformer(private val function: JsFunction, name: String?) {
|
||||
private val innerFunction = function.getInnerFunction()
|
||||
private val functionWithBody = innerFunction ?: function
|
||||
private val body = functionWithBody.body
|
||||
@@ -35,7 +35,7 @@ class CoroutineFunctionTransformer(private val program: JsProgram, private val f
|
||||
|
||||
fun transform(): List<JsStatement> {
|
||||
val context = CoroutineTransformationContext(function.scope, function)
|
||||
val bodyTransformer = CoroutineBodyTransformer(program, context)
|
||||
val bodyTransformer = CoroutineBodyTransformer(context)
|
||||
bodyTransformer.preProcess(body)
|
||||
body.statements.forEach { it.accept(bodyTransformer) }
|
||||
val coroutineBlocks = bodyTransformer.postProcess()
|
||||
@@ -83,11 +83,11 @@ class CoroutineFunctionTransformer(private val program: JsProgram, private val f
|
||||
|
||||
constructor.body.statements.run {
|
||||
val baseClass = context.metadata.baseClassRef.deepCopy()
|
||||
this += JsInvocation(Namer.getFunctionCallRef(baseClass), JsLiteral.THIS, interceptorRef).source(psiElement).makeStmt()
|
||||
this += JsInvocation(Namer.getFunctionCallRef(baseClass), JsThisRef(), interceptorRef).source(psiElement).makeStmt()
|
||||
if (controllerName != null) {
|
||||
assignToField(context.controllerFieldName, controllerName.makeRef(), psiElement)
|
||||
}
|
||||
assignToField(context.metadata.exceptionStateName, program.getNumberLiteral(globalCatchBlockIndex), psiElement)
|
||||
assignToField(context.metadata.exceptionStateName, JsIntLiteral(globalCatchBlockIndex), psiElement)
|
||||
if (context.metadata.hasReceiver) {
|
||||
assignToField(context.receiverFieldName, context.receiverFieldName.makeRef(), psiElement)
|
||||
}
|
||||
@@ -117,7 +117,7 @@ class CoroutineFunctionTransformer(private val program: JsProgram, private val f
|
||||
propertyInitializers +=
|
||||
JsPropertyInitializer(JsNameRef(Namer.METADATA_CLASS_KIND),
|
||||
JsNameRef(Namer.CLASS_KIND_CLASS, JsNameRef(Namer.CLASS_KIND_ENUM, Namer.KOTLIN_NAME)))
|
||||
propertyInitializers += JsPropertyInitializer(JsNameRef(Namer.METADATA_SIMPLE_NAME), JsLiteral.NULL)
|
||||
propertyInitializers += JsPropertyInitializer(JsNameRef(Namer.METADATA_SIMPLE_NAME), JsNullLiteral())
|
||||
propertyInitializers += JsPropertyInitializer(JsNameRef(Namer.METADATA_SUPERTYPES), JsArrayLiteral(listOf(baseClassRefRef)))
|
||||
}
|
||||
|
||||
@@ -150,13 +150,13 @@ class CoroutineFunctionTransformer(private val program: JsProgram, private val f
|
||||
val psiElement = context.metadata.psiElement
|
||||
val instantiation = JsNew(className.makeRef()).apply { source = psiElement }
|
||||
if (context.metadata.hasReceiver) {
|
||||
instantiation.arguments += JsLiteral.THIS
|
||||
instantiation.arguments += JsThisRef()
|
||||
}
|
||||
val parameters = function.parameters + innerFunction?.parameters.orEmpty()
|
||||
instantiation.arguments += parameters.dropLast(1).map { it.name.makeRef() }
|
||||
|
||||
if (function.coroutineMetadata!!.hasController) {
|
||||
instantiation.arguments += JsLiteral.THIS
|
||||
instantiation.arguments += JsThisRef()
|
||||
}
|
||||
|
||||
instantiation.arguments += parameters.last().name.makeRef()
|
||||
@@ -167,7 +167,7 @@ class CoroutineFunctionTransformer(private val program: JsProgram, private val f
|
||||
val instanceName = JsScope.declareTemporaryName("instance")
|
||||
functionWithBody.body.statements += JsAstUtils.newVar(instanceName, instantiation)
|
||||
|
||||
val invokeResume = JsReturn(JsInvocation(JsNameRef(context.metadata.doResumeName, instanceName.makeRef()), JsLiteral.NULL)
|
||||
val invokeResume = JsReturn(JsInvocation(JsNameRef(context.metadata.doResumeName, instanceName.makeRef()), JsNullLiteral())
|
||||
.source(psiElement))
|
||||
|
||||
functionWithBody.body.statements += JsIf(
|
||||
@@ -181,28 +181,28 @@ class CoroutineFunctionTransformer(private val program: JsProgram, private val f
|
||||
blocks: List<CoroutineBlock>
|
||||
): List<JsStatement> {
|
||||
val indexOfGlobalCatch = blocks.indexOf(context.globalCatchBlock)
|
||||
val stateRef = JsNameRef(context.metadata.stateName, JsLiteral.THIS)
|
||||
val stateRef = JsNameRef(context.metadata.stateName, JsThisRef())
|
||||
|
||||
val isFromGlobalCatch = JsAstUtils.equality(stateRef, program.getNumberLiteral(indexOfGlobalCatch))
|
||||
val isFromGlobalCatch = JsAstUtils.equality(stateRef, JsIntLiteral(indexOfGlobalCatch))
|
||||
val catch = JsCatch(functionWithBody.scope, "e")
|
||||
val continueWithException = JsBlock(
|
||||
JsAstUtils.assignment(stateRef.deepCopy(), JsNameRef(context.metadata.exceptionStateName, JsLiteral.THIS)).makeStmt(),
|
||||
JsAstUtils.assignment(JsNameRef(context.metadata.exceptionName, JsLiteral.THIS),
|
||||
JsAstUtils.assignment(stateRef.deepCopy(), JsNameRef(context.metadata.exceptionStateName, JsThisRef())).makeStmt(),
|
||||
JsAstUtils.assignment(JsNameRef(context.metadata.exceptionName, JsThisRef()),
|
||||
catch.parameter.name.makeRef()).makeStmt()
|
||||
)
|
||||
catch.body = JsBlock(JsIf(isFromGlobalCatch, JsThrow(catch.parameter.name.makeRef()), continueWithException))
|
||||
|
||||
val throwResultRef = JsNameRef(context.metadata.exceptionName, JsLiteral.THIS)
|
||||
val throwResultRef = JsNameRef(context.metadata.exceptionName, JsThisRef())
|
||||
context.globalCatchBlock.statements += JsThrow(throwResultRef)
|
||||
|
||||
val cases = blocks.withIndex().map { (index, block) ->
|
||||
JsCase().apply {
|
||||
caseExpression = program.getNumberLiteral(index)
|
||||
caseExpression = JsIntLiteral(index)
|
||||
statements += block.statements
|
||||
}
|
||||
}
|
||||
val switchStatement = JsSwitch(stateRef.deepCopy(), cases)
|
||||
val loop = JsDoWhile(JsLiteral.TRUE, JsTry(JsBlock(switchStatement), catch, null))
|
||||
val loop = JsDoWhile(JsBooleanLiteral(true), JsTry(JsBlock(switchStatement), catch, null))
|
||||
|
||||
return listOf(loop)
|
||||
}
|
||||
@@ -217,7 +217,7 @@ class CoroutineFunctionTransformer(private val program: JsProgram, private val f
|
||||
}
|
||||
|
||||
private fun MutableList<JsStatement>.assignToField(fieldName: JsName, value: JsExpression, psiElement: PsiElement?) {
|
||||
this += JsAstUtils.assignment(JsNameRef(fieldName, JsLiteral.THIS), value).source(psiElement).makeStmt()
|
||||
this += JsAstUtils.assignment(JsNameRef(fieldName, JsThisRef()), value).source(psiElement).makeStmt()
|
||||
}
|
||||
|
||||
private fun MutableList<JsStatement>.assignToPrototype(fieldName: JsName, value: JsExpression) {
|
||||
|
||||
@@ -113,7 +113,7 @@ fun JsNode.collectNodesToSplit(breakContinueTargets: Map<JsContinue, JsStatement
|
||||
return nodes
|
||||
}
|
||||
|
||||
fun List<CoroutineBlock>.replaceCoroutineFlowStatements(context: CoroutineTransformationContext, program: JsProgram) {
|
||||
fun List<CoroutineBlock>.replaceCoroutineFlowStatements(context: CoroutineTransformationContext) {
|
||||
val blockIndexes = withIndex().associate { (index, block) -> Pair(block, index) }
|
||||
|
||||
val blockReplacementVisitor = object : JsVisitorWithContextImpl() {
|
||||
@@ -121,7 +121,7 @@ fun List<CoroutineBlock>.replaceCoroutineFlowStatements(context: CoroutineTransf
|
||||
val target = x.targetBlock
|
||||
if (target != null) {
|
||||
val lhs = JsNameRef(context.metadata.stateName, JsAstUtils.stateMachineReceiver())
|
||||
val rhs = program.getNumberLiteral(blockIndexes[target]!!)
|
||||
val rhs = JsIntLiteral(blockIndexes[target]!!)
|
||||
ctx.replaceMe(JsExpressionStatement(JsAstUtils.assignment(lhs, rhs).source(x.source)).apply {
|
||||
targetBlock = true
|
||||
})
|
||||
@@ -130,7 +130,7 @@ fun List<CoroutineBlock>.replaceCoroutineFlowStatements(context: CoroutineTransf
|
||||
val exceptionTarget = x.targetExceptionBlock
|
||||
if (exceptionTarget != null) {
|
||||
val lhs = JsNameRef(context.metadata.exceptionStateName, JsAstUtils.stateMachineReceiver())
|
||||
val rhs = program.getNumberLiteral(blockIndexes[exceptionTarget]!!)
|
||||
val rhs = JsIntLiteral(blockIndexes[exceptionTarget]!!)
|
||||
ctx.replaceMe(JsExpressionStatement(JsAstUtils.assignment(lhs, rhs).source(x.source)).apply {
|
||||
targetExceptionBlock = true
|
||||
})
|
||||
@@ -140,7 +140,7 @@ fun List<CoroutineBlock>.replaceCoroutineFlowStatements(context: CoroutineTransf
|
||||
if (finallyPath != null) {
|
||||
if (finallyPath.isNotEmpty()) {
|
||||
val lhs = JsNameRef(context.metadata.finallyPathName, JsAstUtils.stateMachineReceiver())
|
||||
val rhs = JsArrayLiteral(finallyPath.map { program.getNumberLiteral(blockIndexes[it]!!) })
|
||||
val rhs = JsArrayLiteral(finallyPath.map { JsIntLiteral(blockIndexes[it]!!) })
|
||||
ctx.replaceMe(JsExpressionStatement(JsAstUtils.assignment(lhs, rhs).source(x.source)).apply {
|
||||
this.finallyPath = true
|
||||
})
|
||||
@@ -208,8 +208,8 @@ private fun CoroutineBlock.collectFinallyPaths(): List<List<CoroutineBlock>> {
|
||||
|
||||
fun JsBlock.replaceSpecialReferences(context: CoroutineTransformationContext) {
|
||||
val visitor = object : JsVisitorWithContextImpl() {
|
||||
override fun endVisit(x: JsLiteral.JsThisRef, ctx: JsContext<in JsNode>) {
|
||||
ctx.replaceMe(JsNameRef(context.receiverFieldName, JsLiteral.THIS))
|
||||
override fun endVisit(x: JsThisRef, ctx: JsContext<in JsNode>) {
|
||||
ctx.replaceMe(JsNameRef(context.receiverFieldName, JsThisRef()))
|
||||
}
|
||||
|
||||
override fun visit(x: JsFunction, ctx: JsContext<*>) = false
|
||||
@@ -217,7 +217,7 @@ fun JsBlock.replaceSpecialReferences(context: CoroutineTransformationContext) {
|
||||
override fun endVisit(x: JsNameRef, ctx: JsContext<in JsNode>) {
|
||||
when {
|
||||
x.coroutineReceiver -> {
|
||||
ctx.replaceMe(JsLiteral.THIS)
|
||||
ctx.replaceMe(JsThisRef())
|
||||
}
|
||||
|
||||
x.coroutineController -> {
|
||||
@@ -254,7 +254,7 @@ fun JsBlock.replaceLocalVariables(context: CoroutineTransformationContext, local
|
||||
val nameMap = freeVars.associate { it to JsScope.declareTemporaryName(it.ident) }
|
||||
for (freeVar in freeVars) {
|
||||
wrapperFunction.parameters += JsParameter(nameMap[freeVar]!!)
|
||||
wrapperInvocation.arguments += JsNameRef(context.getFieldName(freeVar), JsLiteral.THIS)
|
||||
wrapperInvocation.arguments += JsNameRef(context.getFieldName(freeVar), JsThisRef())
|
||||
}
|
||||
x.body = replaceNames(x.body, nameMap.mapValues { it.value.makeRef() })
|
||||
ctx.replaceMe(wrapperInvocation)
|
||||
@@ -264,7 +264,7 @@ fun JsBlock.replaceLocalVariables(context: CoroutineTransformationContext, local
|
||||
override fun endVisit(x: JsNameRef, ctx: JsContext<in JsNode>) {
|
||||
if (x.qualifier == null && x.name in localVariables) {
|
||||
val fieldName = context.getFieldName(x.name!!)
|
||||
ctx.replaceMe(JsNameRef(fieldName, JsLiteral.THIS).source(x.source))
|
||||
ctx.replaceMe(JsNameRef(fieldName, JsThisRef()).source(x.source))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,7 +273,7 @@ fun JsBlock.replaceLocalVariables(context: CoroutineTransformationContext, local
|
||||
val fieldName = context.getFieldName(it.name)
|
||||
val initExpression = it.initExpression
|
||||
if (initExpression != null) {
|
||||
JsAstUtils.assignment(JsNameRef(fieldName, JsLiteral.THIS), it.initExpression)
|
||||
JsAstUtils.assignment(JsNameRef(fieldName, JsThisRef()), it.initExpression)
|
||||
}
|
||||
else {
|
||||
null
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.js.backend.ast.metadata.coroutineMetadata
|
||||
import org.jetbrains.kotlin.js.translate.expression.InlineMetadata
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||
|
||||
class CoroutineTransformer(private val program: JsProgram) : JsVisitorWithContextImpl() {
|
||||
class CoroutineTransformer() : JsVisitorWithContextImpl() {
|
||||
private val additionalStatementsByNode = mutableMapOf<JsNode, List<JsStatement>>()
|
||||
|
||||
override fun endVisit(x: JsExpressionStatement, ctx: JsContext<in JsStatement>) {
|
||||
@@ -44,13 +44,13 @@ class CoroutineTransformer(private val program: JsProgram) : JsVisitorWithContex
|
||||
val function = rhs as? JsFunction ?: InlineMetadata.decompose(rhs)?.function
|
||||
if (function?.coroutineMetadata != null) {
|
||||
val name = ((lhs as? JsNameRef)?.name ?: function.name)?.ident
|
||||
additionalStatementsByNode[x] = CoroutineFunctionTransformer(program, function, name).transform()
|
||||
additionalStatementsByNode[x] = CoroutineFunctionTransformer(function, name).transform()
|
||||
return false
|
||||
}
|
||||
}
|
||||
else if (expression is JsFunction) {
|
||||
if (expression.coroutineMetadata != null) {
|
||||
additionalStatementsByNode[x] = CoroutineFunctionTransformer(program, expression, expression.name?.ident).transform()
|
||||
additionalStatementsByNode[x] = CoroutineFunctionTransformer(expression, expression.name?.ident).transform()
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -63,7 +63,7 @@ class CoroutineTransformer(private val program: JsProgram) : JsVisitorWithContex
|
||||
val function = initExpression as? JsFunction ?: InlineMetadata.decompose(initExpression)?.function
|
||||
if (function?.coroutineMetadata != null) {
|
||||
val name = x.name.ident
|
||||
additionalStatementsByNode[x] = CoroutineFunctionTransformer(program, function, name).transform()
|
||||
additionalStatementsByNode[x] = CoroutineFunctionTransformer(function, name).transform()
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -139,7 +139,7 @@ internal class ExpressionDecomposer private constructor(
|
||||
}
|
||||
|
||||
body = additionalStatements.toStatement()
|
||||
test = JsLiteral.TRUE
|
||||
test = JsBooleanLiteral(true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -404,8 +404,8 @@ internal open class JsExpressionVisitor() : JsVisitorWithContextImpl() {
|
||||
override fun visit(x: JsCase, ctx: JsContext<JsNode>): Boolean = false
|
||||
override fun visit(x: JsDefault, ctx: JsContext<JsNode>): Boolean = false
|
||||
override fun visit(x: JsEmpty, ctx: JsContext<JsNode>): Boolean = false
|
||||
override fun visit(x: JsLiteral.JsBooleanLiteral, ctx: JsContext<JsNode>): Boolean = false
|
||||
override fun visit(x: JsLiteral.JsThisRef, ctx: JsContext<JsNode>): Boolean = false
|
||||
override fun visit(x: JsBooleanLiteral, ctx: JsContext<JsNode>): Boolean = false
|
||||
override fun visit(x: JsThisRef, ctx: JsContext<JsNode>): Boolean = false
|
||||
override fun visit(x: JsNullLiteral, ctx: JsContext<JsNode>): Boolean = false
|
||||
override fun visit(x: JsNumberLiteral, ctx: JsContext<JsNode>): Boolean = false
|
||||
override fun visit(x: JsRegExp, ctx: JsContext<JsNode>): Boolean = false
|
||||
|
||||
@@ -97,7 +97,7 @@ private constructor(
|
||||
if (!hasThisReference(block)) return
|
||||
|
||||
var thisReplacement = getThisReplacement(call)
|
||||
if (thisReplacement == null || thisReplacement is JsLiteral.JsThisRef) return
|
||||
if (thisReplacement == null || thisReplacement is JsThisRef) return
|
||||
|
||||
val thisName = JsScope.declareTemporaryName(getThisAlias())
|
||||
namingContext.newVar(thisName, thisReplacement)
|
||||
@@ -195,7 +195,7 @@ private constructor(
|
||||
}
|
||||
|
||||
private fun hasThisReference(body: JsBlock): Boolean {
|
||||
val thisRefs = collectInstances(JsLiteral.JsThisRef::class.java, body)
|
||||
val thisRefs = collectInstances(JsThisRef::class.java, body)
|
||||
return !thisRefs.isEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -78,7 +78,7 @@ internal class DeadCodeElimination(private val root: JsStatement) {
|
||||
|
||||
visitLoop(x.body) {
|
||||
val condition = x.condition
|
||||
condition !is JsLiteral.JsBooleanLiteral || !condition.value
|
||||
condition !is JsBooleanLiteral || !condition.value
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ object LabeledBlockToDoWhileTransformation {
|
||||
object : JsVisitorWithContextImpl() {
|
||||
override fun endVisit(x: JsLabel, ctx: JsContext<JsNode>) {
|
||||
if (x.statement is JsBlock) {
|
||||
x.statement = JsDoWhile(JsLiteral.FALSE, x.statement)
|
||||
x.statement = JsDoWhile(JsBooleanLiteral(false), x.statement)
|
||||
}
|
||||
|
||||
super.endVisit(x, ctx)
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.js.backend.ast.metadata.sideEffects
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.synthetic
|
||||
import org.jetbrains.kotlin.js.inline.util.collectFreeVariables
|
||||
import org.jetbrains.kotlin.js.inline.util.collectLocalVariables
|
||||
import org.jetbrains.kotlin.js.translate.context.Namer
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||
import org.jetbrains.kotlin.js.translate.utils.splitToRanges
|
||||
|
||||
@@ -165,7 +166,7 @@ internal class TemporaryVariableElimination(private val function: JsFunction) {
|
||||
useVariable(name)
|
||||
if (name !in currentScope) {
|
||||
// Variable is inconsistent, i.e. it's defined after it's used.
|
||||
assignVariable(name, JsLiteral.UNDEFINED)
|
||||
assignVariable(name, Namer.getUndefinedExpression())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -66,8 +66,8 @@ class WhileConditionFolding(val body: JsBlock) {
|
||||
if (condition != null) {
|
||||
statement.body = remove(statement.body)
|
||||
val existingCondition = statement.condition
|
||||
statement.condition = when (existingCondition) {
|
||||
JsLiteral.TRUE -> condition
|
||||
statement.condition = when {
|
||||
JsLiteral.isTrueBoolean(existingCondition) -> condition
|
||||
else -> combine(existingCondition, condition)
|
||||
}
|
||||
changed = true
|
||||
@@ -105,7 +105,7 @@ class WhileConditionFolding(val body: JsBlock) {
|
||||
// therefore for single `break` we should return `false`.
|
||||
is JsBreak -> {
|
||||
val target = statement.label?.name
|
||||
if (label == target) JsLiteral.FALSE else null
|
||||
if (label == target) JsBooleanLiteral(false) else null
|
||||
}
|
||||
|
||||
// Code like this
|
||||
@@ -138,11 +138,11 @@ class WhileConditionFolding(val body: JsBlock) {
|
||||
val then = statement.thenStatement
|
||||
if (statement.elseStatement == null) {
|
||||
val nextCondition = extractCondition(then, label)
|
||||
val result: JsExpression? = when (nextCondition) {
|
||||
val result: JsExpression? = when {
|
||||
// Just a little optimization. When inner statement is a single `break`, `nextCondition` would be false.
|
||||
// However, `A || false` can be rewritten as simply `A`
|
||||
JsLiteral.FALSE -> JsAstUtils.notOptimized(statement.ifExpression)
|
||||
null -> null
|
||||
nextCondition == null -> null
|
||||
JsLiteral.isFalseBoolean(nextCondition) -> JsAstUtils.notOptimized(statement.ifExpression)
|
||||
else -> JsAstUtils.or(JsAstUtils.notOptimized(statement.ifExpression), nextCondition)
|
||||
}
|
||||
result
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.js.inline.util.rewriters
|
||||
import org.jetbrains.kotlin.js.backend.ast.*
|
||||
|
||||
class ThisReplacingVisitor(private val thisReplacement: JsExpression) : JsVisitorWithContextImpl() {
|
||||
override fun endVisit(x: JsLiteral.JsThisRef, ctx: JsContext<JsNode>) {
|
||||
override fun endVisit(x: JsThisRef, ctx: JsContext<JsNode>) {
|
||||
ctx.replaceMe(thisReplacement)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user