JS: Inlined local declarations should be positioned after imports
This commit is contained in:
@@ -33,8 +33,6 @@ sealed class InliningScope {
|
|||||||
|
|
||||||
protected open fun preprocess(statement: JsStatement) {}
|
protected open fun preprocess(statement: JsStatement) {}
|
||||||
|
|
||||||
abstract fun update()
|
|
||||||
|
|
||||||
private val publicFunctionCache = mutableMapOf<String, JsFunction>()
|
private val publicFunctionCache = mutableMapOf<String, JsFunction>()
|
||||||
|
|
||||||
private val localFunctionCache = mutableMapOf<JsFunction, JsFunction>()
|
private val localFunctionCache = mutableMapOf<JsFunction, JsFunction>()
|
||||||
@@ -167,21 +165,6 @@ class ImportInfoFragmentInliningScope private constructor(
|
|||||||
|
|
||||||
private val additionalDeclarations = mutableListOf<JsStatement>()
|
private val additionalDeclarations = mutableListOf<JsStatement>()
|
||||||
|
|
||||||
override fun update() {
|
|
||||||
// TODO fix the order?
|
|
||||||
fragment.declarationBlock.statements.addAll(0, additionalDeclarations)
|
|
||||||
|
|
||||||
// post-processing
|
|
||||||
|
|
||||||
// If run separately `private inline suspend fun`'s local declarations get inlined twice.
|
|
||||||
InlineSuspendFunctionSplitter(this).accept(allCode)
|
|
||||||
|
|
||||||
simplifyWrappedFunctions(allCode)
|
|
||||||
removeUnusedFunctionDefinitions(allCode, collectNamedFunctions(allCode))
|
|
||||||
removeUnusedImports(fragment, allCode)
|
|
||||||
renameLabels(allCode)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hasImport(name: JsName, tag: String): JsName? {
|
override fun hasImport(name: JsName, tag: String): JsName? {
|
||||||
return name.localAlias?.let { (name, tag) ->
|
return name.localAlias?.let { (name, tag) ->
|
||||||
if (tag != null) {
|
if (tag != null) {
|
||||||
@@ -251,7 +234,21 @@ class ImportInfoFragmentInliningScope private constructor(
|
|||||||
fun process(fragment: JsProgramFragment, fn: (ImportInfoFragmentInliningScope) -> Unit) {
|
fun process(fragment: JsProgramFragment, fn: (ImportInfoFragmentInliningScope) -> Unit) {
|
||||||
val scope = ImportInfoFragmentInliningScope(fragment)
|
val scope = ImportInfoFragmentInliningScope(fragment)
|
||||||
fn(scope)
|
fn(scope)
|
||||||
scope.update()
|
|
||||||
|
scope.apply {
|
||||||
|
// TODO fix the order?
|
||||||
|
fragment.declarationBlock.statements.addAll(0, additionalDeclarations)
|
||||||
|
|
||||||
|
// post-processing
|
||||||
|
|
||||||
|
// If run separately `private inline suspend fun`'s local declarations get inlined twice.
|
||||||
|
InlineSuspendFunctionSplitter(this).accept(allCode)
|
||||||
|
|
||||||
|
simplifyWrappedFunctions(allCode)
|
||||||
|
removeUnusedFunctionDefinitions(allCode, collectNamedFunctions(allCode))
|
||||||
|
removeUnusedImports(fragment, allCode)
|
||||||
|
renameLabels(allCode)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -260,13 +257,24 @@ class ImportIntoWrapperInliningScope private constructor(
|
|||||||
private val wrapperBody: JsBlock,
|
private val wrapperBody: JsBlock,
|
||||||
override val fragment: JsProgramFragment
|
override val fragment: JsProgramFragment
|
||||||
) : InliningScope() {
|
) : InliningScope() {
|
||||||
private val existingImports = mutableMapOf<String, JsName>().also { map ->
|
private val importList = mutableListOf<JsVars>()
|
||||||
|
|
||||||
|
private val otherLocalStatements = mutableListOf<JsStatement>()
|
||||||
|
|
||||||
|
private val existingImports = mutableMapOf<String, JsName>()
|
||||||
|
|
||||||
|
init {
|
||||||
for (s in wrapperBody.statements) {
|
for (s in wrapperBody.statements) {
|
||||||
if (s !is JsVars) continue
|
if (s is JsVars) {
|
||||||
|
val tag = getImportTag(s)
|
||||||
|
if (tag != null) {
|
||||||
|
importList.add(s)
|
||||||
|
existingImports[tag] = s.vars[0].name
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val tag = getImportTag(s) ?: continue
|
otherLocalStatements.add(s)
|
||||||
|
|
||||||
map[tag] = s.vars[0].name
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,18 +288,19 @@ class ImportIntoWrapperInliningScope private constructor(
|
|||||||
|
|
||||||
override fun addImport(tag: String, vars: JsVars) {
|
override fun addImport(tag: String, vars: JsVars) {
|
||||||
existingImports[tag] = vars.vars[0].name
|
existingImports[tag] = vars.vars[0].name
|
||||||
additionalStatements.add(vars)
|
importList.add(vars)
|
||||||
}
|
|
||||||
|
|
||||||
override fun update() {
|
|
||||||
wrapperBody.statements.addAll(0, additionalStatements)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun process(wrapperBody: JsBlock, fragment: JsProgramFragment, fn: (ImportIntoWrapperInliningScope) -> Unit) {
|
fun process(wrapperBody: JsBlock, fragment: JsProgramFragment, fn: (ImportIntoWrapperInliningScope) -> Unit) {
|
||||||
val scope = ImportIntoWrapperInliningScope(wrapperBody, fragment)
|
val scope = ImportIntoWrapperInliningScope(wrapperBody, fragment)
|
||||||
fn(scope)
|
fn(scope)
|
||||||
scope.update()
|
wrapperBody.statements.apply {
|
||||||
|
clear()
|
||||||
|
addAll(scope.importList)
|
||||||
|
addAll(scope.additionalStatements)
|
||||||
|
addAll(scope.otherLocalStatements)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+5
@@ -4005,6 +4005,11 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
|||||||
runTest("js/js.translator/testData/box/inline/inlineSimpleAssignment.kt");
|
runTest("js/js.translator/testData/box/inline/inlineSimpleAssignment.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inlinedObjectLiteralIsCheck.kt")
|
||||||
|
public void testInlinedObjectLiteralIsCheck() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/inline/inlinedObjectLiteralIsCheck.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("innerOuterThis.kt")
|
@TestMetadata("innerOuterThis.kt")
|
||||||
public void testInnerOuterThis() throws Exception {
|
public void testInnerOuterThis() throws Exception {
|
||||||
runTest("js/js.translator/testData/box/inline/innerOuterThis.kt");
|
runTest("js/js.translator/testData/box/inline/innerOuterThis.kt");
|
||||||
|
|||||||
+5
@@ -4005,6 +4005,11 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
|||||||
runTest("js/js.translator/testData/box/inline/inlineSimpleAssignment.kt");
|
runTest("js/js.translator/testData/box/inline/inlineSimpleAssignment.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inlinedObjectLiteralIsCheck.kt")
|
||||||
|
public void testInlinedObjectLiteralIsCheck() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/inline/inlinedObjectLiteralIsCheck.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("innerOuterThis.kt")
|
@TestMetadata("innerOuterThis.kt")
|
||||||
public void testInnerOuterThis() throws Exception {
|
public void testInnerOuterThis() throws Exception {
|
||||||
runTest("js/js.translator/testData/box/inline/innerOuterThis.kt");
|
runTest("js/js.translator/testData/box/inline/innerOuterThis.kt");
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
// EXPECTED_REACHABLE_NODES: 1282
|
||||||
|
// IGNORE_BACKEND: JS_IR
|
||||||
|
|
||||||
|
interface I {
|
||||||
|
fun ok(): String
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun ok(): I {
|
||||||
|
return object : I {
|
||||||
|
override fun ok() = "OK"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsName("convolutedOk")
|
||||||
|
inline fun convolutedOk(): I {
|
||||||
|
val fail = object : I {
|
||||||
|
override fun ok() = "fail"
|
||||||
|
}.ok()
|
||||||
|
|
||||||
|
println(fail)
|
||||||
|
|
||||||
|
return ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val ok = js("_").convolutedOk()
|
||||||
|
if (ok !is I) return "fail"
|
||||||
|
|
||||||
|
return ok.ok()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user