JS: fix module aliasing for inline imports (KT-26466 fixed)
Consider an import from an inline function invocation. If it is being called from another inline function, it should be defined in a special way (e.g. `$$importsForInline$$.foo`) so that the compiler knows where to load transitive dependencies from. What's more, the declaration itself should be inside the inline function wrapper. Otherwise it should be defined in a regular way (e.g. `$module$bar.foo` among other top-level imports). By default the imports are loaded in the first form, and transformed into the second one when needed. To check whether this transformation the following predicate is used: `inlineFunctionDepth == 0`. At the moment the mentioned variable is increased upon visiting an inline function declaration (`defineInlineFunction`), and upon visiting an unknown (not visited before) inline function invocation. It seems that instead the variable should be increased when processing an existing inline function wrapper. At that point a new place to put import definitions (`statementContextForInline`) is set. Due to way JS code is generated (lambda's come before their call sites) this issue seems to have been masked. Primary class constructors are a special case - they come before any other declaration within. Hence a lambda invocation inside a constructor leads to incorrect import definition.
This commit is contained in:
@@ -229,6 +229,7 @@ public class JsInliner extends JsVisitorWithContextImpl {
|
|||||||
private void visit(@NotNull FunctionWithWrapper functionWithWrapper) {
|
private void visit(@NotNull FunctionWithWrapper functionWithWrapper) {
|
||||||
JsContext<JsStatement> oldContextForInline = statementContextForInline;
|
JsContext<JsStatement> oldContextForInline = statementContextForInline;
|
||||||
Map<String, JsName> oldExistingImports = existingImports;
|
Map<String, JsName> oldExistingImports = existingImports;
|
||||||
|
int oldInlineFunctionDepth = inlineFunctionDepth;
|
||||||
|
|
||||||
ListContext<JsStatement> innerContext = new ListContext<>();
|
ListContext<JsStatement> innerContext = new ListContext<>();
|
||||||
|
|
||||||
@@ -238,6 +239,7 @@ public class JsInliner extends JsVisitorWithContextImpl {
|
|||||||
existingImports = new HashMap<>();
|
existingImports = new HashMap<>();
|
||||||
statementContexts.push(innerContext);
|
statementContexts.push(innerContext);
|
||||||
statementContextForInline = innerContext;
|
statementContextForInline = innerContext;
|
||||||
|
inlineFunctionDepth++;
|
||||||
|
|
||||||
for (JsStatement statement : wrapperBody.getStatements()) {
|
for (JsStatement statement : wrapperBody.getStatements()) {
|
||||||
processImportStatement(statement);
|
processImportStatement(statement);
|
||||||
@@ -268,14 +270,11 @@ public class JsInliner extends JsVisitorWithContextImpl {
|
|||||||
|
|
||||||
statementContextForInline = oldContextForInline;
|
statementContextForInline = oldContextForInline;
|
||||||
existingImports = oldExistingImports;
|
existingImports = oldExistingImports;
|
||||||
|
inlineFunctionDepth = oldInlineFunctionDepth;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean visit(@NotNull JsInvocation call, @NotNull JsContext context) {
|
public boolean visit(@NotNull JsInvocation call, @NotNull JsContext context) {
|
||||||
if (InlineMetadata.decompose(call) != null) {
|
|
||||||
inlineFunctionDepth++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasToBeInlined(call)) return true;
|
if (!hasToBeInlined(call)) return true;
|
||||||
|
|
||||||
JsFunction containingFunction = getCurrentNamedFunction();
|
JsFunction containingFunction = getCurrentNamedFunction();
|
||||||
@@ -294,9 +293,7 @@ public class JsInliner extends JsVisitorWithContextImpl {
|
|||||||
JsExpression argument = call.getArguments().get(i);
|
JsExpression argument = call.getArguments().get(i);
|
||||||
call.getArguments().set(i, accept(argument));
|
call.getArguments().set(i, accept(argument));
|
||||||
}
|
}
|
||||||
inlineFunctionDepth++;
|
|
||||||
visit(definition);
|
visit(definition);
|
||||||
inlineFunctionDepth--;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,10 +302,6 @@ public class JsInliner extends JsVisitorWithContextImpl {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void endVisit(@NotNull JsInvocation x, @NotNull JsContext ctx) {
|
public void endVisit(@NotNull JsInvocation x, @NotNull JsContext ctx) {
|
||||||
if (InlineMetadata.decompose(x) != null) {
|
|
||||||
inlineFunctionDepth--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasToBeInlined(x)) {
|
if (hasToBeInlined(x)) {
|
||||||
inline(x, ctx);
|
inline(x, ctx);
|
||||||
}
|
}
|
||||||
|
|||||||
+10
@@ -3875,6 +3875,11 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
|||||||
runTest("js/js.translator/testData/box/inline/inlineChain.kt");
|
runTest("js/js.translator/testData/box/inline/inlineChain.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inlineChainCrossModule.kt")
|
||||||
|
public void testInlineChainCrossModule() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/inline/inlineChainCrossModule.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("inlineChainWithFewStatements.kt")
|
@TestMetadata("inlineChainWithFewStatements.kt")
|
||||||
public void testInlineChainWithFewStatements() throws Exception {
|
public void testInlineChainWithFewStatements() throws Exception {
|
||||||
runTest("js/js.translator/testData/box/inline/inlineChainWithFewStatements.kt");
|
runTest("js/js.translator/testData/box/inline/inlineChainWithFewStatements.kt");
|
||||||
@@ -3985,6 +3990,11 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
|||||||
runTest("js/js.translator/testData/box/inline/kt26117.kt");
|
runTest("js/js.translator/testData/box/inline/kt26117.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt26466.kt")
|
||||||
|
public void testKt26466() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/inline/kt26466.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("lambdaInLambda.kt")
|
@TestMetadata("lambdaInLambda.kt")
|
||||||
public void testLambdaInLambda() throws Exception {
|
public void testLambdaInLambda() throws Exception {
|
||||||
runTest("js/js.translator/testData/box/inline/lambdaInLambda.kt");
|
runTest("js/js.translator/testData/box/inline/lambdaInLambda.kt");
|
||||||
|
|||||||
+10
@@ -3875,6 +3875,11 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
|||||||
runTest("js/js.translator/testData/box/inline/inlineChain.kt");
|
runTest("js/js.translator/testData/box/inline/inlineChain.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inlineChainCrossModule.kt")
|
||||||
|
public void testInlineChainCrossModule() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/inline/inlineChainCrossModule.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("inlineChainWithFewStatements.kt")
|
@TestMetadata("inlineChainWithFewStatements.kt")
|
||||||
public void testInlineChainWithFewStatements() throws Exception {
|
public void testInlineChainWithFewStatements() throws Exception {
|
||||||
runTest("js/js.translator/testData/box/inline/inlineChainWithFewStatements.kt");
|
runTest("js/js.translator/testData/box/inline/inlineChainWithFewStatements.kt");
|
||||||
@@ -3985,6 +3990,11 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
|||||||
runTest("js/js.translator/testData/box/inline/kt26117.kt");
|
runTest("js/js.translator/testData/box/inline/kt26117.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt26466.kt")
|
||||||
|
public void testKt26466() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/inline/kt26466.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("lambdaInLambda.kt")
|
@TestMetadata("lambdaInLambda.kt")
|
||||||
public void testLambdaInLambda() throws Exception {
|
public void testLambdaInLambda() throws Exception {
|
||||||
runTest("js/js.translator/testData/box/inline/lambdaInLambda.kt");
|
runTest("js/js.translator/testData/box/inline/lambdaInLambda.kt");
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
// EXPECTED_REACHABLE_NODES: 1192
|
||||||
|
// IGNORE_BACKEND: JS_IR
|
||||||
|
|
||||||
|
// MODULE: lib
|
||||||
|
// FILE: lib.kt
|
||||||
|
|
||||||
|
|
||||||
|
inline fun baz() = pp()
|
||||||
|
|
||||||
|
fun pp(): String = "OK"
|
||||||
|
|
||||||
|
// MODULE: mid(lib)
|
||||||
|
// FILE: mid.kt
|
||||||
|
|
||||||
|
fun bar() {
|
||||||
|
foo()
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun foo()= baz()
|
||||||
|
|
||||||
|
// MODULE: main(mid)
|
||||||
|
// FILE: main.kt
|
||||||
|
|
||||||
|
fun box() = foo()
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
// EXPECTED_REACHABLE_NODES: 1269
|
||||||
|
// IGNORE_BACKEND: JS_IR
|
||||||
|
|
||||||
|
// MODULE: lib
|
||||||
|
// FILE: lib.kt
|
||||||
|
|
||||||
|
class A(k: String) {
|
||||||
|
val ok = "O" + k
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun o(k: String) = A(k).ok
|
||||||
|
|
||||||
|
// MODULE: main(lib)
|
||||||
|
// FILE: main.kt
|
||||||
|
|
||||||
|
class B {
|
||||||
|
val ok = run { o("K") }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box() = B().ok
|
||||||
Reference in New Issue
Block a user