diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/InliningScope.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/InliningScope.kt index 9a1df489bd1..cf3b04ae7bc 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/InliningScope.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/InliningScope.kt @@ -33,8 +33,6 @@ sealed class InliningScope { protected open fun preprocess(statement: JsStatement) {} - abstract fun update() - private val publicFunctionCache = mutableMapOf() private val localFunctionCache = mutableMapOf() @@ -167,21 +165,6 @@ class ImportInfoFragmentInliningScope private constructor( private val additionalDeclarations = mutableListOf() - 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? { return name.localAlias?.let { (name, tag) -> if (tag != null) { @@ -251,7 +234,21 @@ class ImportInfoFragmentInliningScope private constructor( fun process(fragment: JsProgramFragment, fn: (ImportInfoFragmentInliningScope) -> Unit) { val scope = ImportInfoFragmentInliningScope(fragment) 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, override val fragment: JsProgramFragment ) : InliningScope() { - private val existingImports = mutableMapOf().also { map -> + private val importList = mutableListOf() + + private val otherLocalStatements = mutableListOf() + + private val existingImports = mutableMapOf() + + init { 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 - - map[tag] = s.vars[0].name + otherLocalStatements.add(s) } } @@ -280,18 +288,19 @@ class ImportIntoWrapperInliningScope private constructor( override fun addImport(tag: String, vars: JsVars) { existingImports[tag] = vars.vars[0].name - additionalStatements.add(vars) - } - - override fun update() { - wrapperBody.statements.addAll(0, additionalStatements) + importList.add(vars) } companion object { fun process(wrapperBody: JsBlock, fragment: JsProgramFragment, fn: (ImportIntoWrapperInliningScope) -> Unit) { val scope = ImportIntoWrapperInliningScope(wrapperBody, fragment) fn(scope) - scope.update() + wrapperBody.statements.apply { + clear() + addAll(scope.importList) + addAll(scope.additionalStatements) + addAll(scope.otherLocalStatements) + } } } } \ No newline at end of file diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java index e6a83f6d6e1..60726fe9765 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java @@ -4005,6 +4005,11 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest { 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") public void testInnerOuterThis() throws Exception { runTest("js/js.translator/testData/box/inline/innerOuterThis.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrBoxJsTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrBoxJsTestGenerated.java index 0a051ba4126..8cd948b16fb 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrBoxJsTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrBoxJsTestGenerated.java @@ -4005,6 +4005,11 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest { 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") public void testInnerOuterThis() throws Exception { runTest("js/js.translator/testData/box/inline/innerOuterThis.kt"); diff --git a/js/js.translator/testData/box/inline/inlinedObjectLiteralIsCheck.kt b/js/js.translator/testData/box/inline/inlinedObjectLiteralIsCheck.kt new file mode 100644 index 00000000000..50760674321 --- /dev/null +++ b/js/js.translator/testData/box/inline/inlinedObjectLiteralIsCheck.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() +} \ No newline at end of file