[JS IR BE] Do not create $default stub for external function and any its fake override
This commit is contained in:
+5
-2
@@ -396,12 +396,15 @@ class DefaultParameterCleaner constructor(val context: CommonBackendContext) : F
|
|||||||
// TODO this implementation is exponential
|
// TODO this implementation is exponential
|
||||||
private fun IrFunction.needsDefaultArgumentsLowering(skipInlineMethods: Boolean, skipExternalMethods: Boolean): Boolean {
|
private fun IrFunction.needsDefaultArgumentsLowering(skipInlineMethods: Boolean, skipExternalMethods: Boolean): Boolean {
|
||||||
if (isInline && skipInlineMethods) return false
|
if (isInline && skipInlineMethods) return false
|
||||||
if (skipExternalMethods && isEffectivelyExternal()) return false
|
if (skipExternalMethods && isExternalOrInheritedFromExternal()) return false
|
||||||
if (valueParameters.any { it.defaultValue != null }) return true
|
if (valueParameters.any { it.defaultValue != null }) return true
|
||||||
|
|
||||||
if (this !is IrSimpleFunction) return false
|
if (this !is IrSimpleFunction) return false
|
||||||
|
|
||||||
return overriddenSymbols.any { it.owner.needsDefaultArgumentsLowering(skipInlineMethods, skipExternalMethods) }
|
fun IrSimpleFunction.inheritsDefaultValues(): Boolean =
|
||||||
|
valueParameters.any { it.defaultValue != null } || overriddenSymbols.any { it.owner.inheritsDefaultValues() }
|
||||||
|
|
||||||
|
return inheritsDefaultValues()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrFunction.generateDefaultsFunctionImpl(
|
private fun IrFunction.generateDefaultsFunctionImpl(
|
||||||
|
|||||||
+1
-1
@@ -27,7 +27,7 @@ import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
|||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
class JsDefaultArgumentStubGenerator(override val context: JsIrBackendContext) : DefaultArgumentStubGenerator(context, true, false) {
|
class JsDefaultArgumentStubGenerator(override val context: JsIrBackendContext) : DefaultArgumentStubGenerator(context, true, true) {
|
||||||
|
|
||||||
override fun needSpecialDispatch(irFunction: IrSimpleFunction) = irFunction.isOverridableOrOverrides
|
override fun needSpecialDispatch(irFunction: IrSimpleFunction) = irFunction.isOverridableOrOverrides
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -15,7 +15,7 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
|
|||||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
|
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrWhen
|
import org.jetbrains.kotlin.ir.expressions.IrWhen
|
||||||
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
|
import org.jetbrains.kotlin.ir.util.isExternalOrInheritedFromExternal
|
||||||
import org.jetbrains.kotlin.js.backend.ast.*
|
import org.jetbrains.kotlin.js.backend.ast.*
|
||||||
|
|
||||||
fun jsVar(name: JsName, initializer: IrExpression?, context: JsGenerationContext): JsVars {
|
fun jsVar(name: JsName, initializer: IrExpression?, context: JsGenerationContext): JsVars {
|
||||||
@@ -72,7 +72,7 @@ fun translateCallArguments(expression: IrMemberAccessExpression, context: JsGene
|
|||||||
val argument = expression.getValueArgument(index)
|
val argument = expression.getValueArgument(index)
|
||||||
val result = argument?.accept(transformer, context)
|
val result = argument?.accept(transformer, context)
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
require(expression is IrFunctionAccessExpression && expression.symbol.owner.isEffectivelyExternal())
|
assert(expression is IrFunctionAccessExpression && expression.symbol.owner.isExternalOrInheritedFromExternal())
|
||||||
JsPrefixOperation(JsUnaryOperator.VOID, JsIntLiteral(1))
|
JsPrefixOperation(JsUnaryOperator.VOID, JsIntLiteral(1))
|
||||||
} else
|
} else
|
||||||
result
|
result
|
||||||
|
|||||||
@@ -360,6 +360,13 @@ fun IrDeclaration.isEffectivelyExternal(): Boolean {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun IrFunction.isExternalOrInheritedFromExternal(): Boolean {
|
||||||
|
fun isExternalOrInheritedFromExternalImpl(f: IrSimpleFunction): Boolean =
|
||||||
|
f.isEffectivelyExternal() || f.overriddenSymbols.any { isExternalOrInheritedFromExternalImpl(it.owner) }
|
||||||
|
|
||||||
|
return isEffectivelyExternal() || (this is IrSimpleFunction && isExternalOrInheritedFromExternalImpl(this))
|
||||||
|
}
|
||||||
|
|
||||||
inline fun <reified T : IrDeclaration> IrDeclarationContainer.findDeclaration(predicate: (T) -> Boolean): T? =
|
inline fun <reified T : IrDeclaration> IrDeclarationContainer.findDeclaration(predicate: (T) -> Boolean): T? =
|
||||||
declarations.find { it is T && predicate(it) } as? T
|
declarations.find { it is T && predicate(it) } as? T
|
||||||
|
|
||||||
|
|||||||
+5
@@ -4918,6 +4918,11 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
|||||||
runTest("js/js.translator/testData/box/jsModule/externalClass.kt");
|
runTest("js/js.translator/testData/box/jsModule/externalClass.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("externalClassWithDefaults.kt")
|
||||||
|
public void testExternalClassWithDefaults() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/jsModule/externalClassWithDefaults.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("externalFunction.kt")
|
@TestMetadata("externalFunction.kt")
|
||||||
public void testExternalFunction() throws Exception {
|
public void testExternalFunction() throws Exception {
|
||||||
runTest("js/js.translator/testData/box/jsModule/externalFunction.kt");
|
runTest("js/js.translator/testData/box/jsModule/externalFunction.kt");
|
||||||
|
|||||||
+5
@@ -4933,6 +4933,11 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
|||||||
runTest("js/js.translator/testData/box/jsModule/externalClass.kt");
|
runTest("js/js.translator/testData/box/jsModule/externalClass.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("externalClassWithDefaults.kt")
|
||||||
|
public void testExternalClassWithDefaults() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/jsModule/externalClassWithDefaults.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("externalFunction.kt")
|
@TestMetadata("externalFunction.kt")
|
||||||
public void testExternalFunction() throws Exception {
|
public void testExternalFunction() throws Exception {
|
||||||
runTest("js/js.translator/testData/box/jsModule/externalFunction.kt");
|
runTest("js/js.translator/testData/box/jsModule/externalFunction.kt");
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
define("lib", [], function() {
|
||||||
|
function A(ss) {
|
||||||
|
this.s = ss || "A"
|
||||||
|
}
|
||||||
|
A.prototype.foo = function (y) {
|
||||||
|
return y || "K";
|
||||||
|
};
|
||||||
|
A.prototype.bar = function (y) {
|
||||||
|
return y || "O";
|
||||||
|
};
|
||||||
|
|
||||||
|
return A;
|
||||||
|
});
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
// EXPECTED_REACHABLE_NODES: 1284
|
||||||
|
// MODULE_KIND: AMD
|
||||||
|
package foo
|
||||||
|
|
||||||
|
@JsModule("lib")
|
||||||
|
external open class A(ss: String = definedExternally) {
|
||||||
|
val s: String
|
||||||
|
fun foo(y: String = definedExternally): String = definedExternally
|
||||||
|
fun bar(y: String = definedExternally): String = definedExternally
|
||||||
|
}
|
||||||
|
|
||||||
|
class C: A {
|
||||||
|
constructor(ss: String) : super(ss) {}
|
||||||
|
constructor() : super() {}
|
||||||
|
|
||||||
|
fun qux(s: String = "O") = s
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val a = A()
|
||||||
|
val c = C()
|
||||||
|
|
||||||
|
val r1 = a.foo("O") + c.foo()
|
||||||
|
if (r1 != "OK") return "Fail1: $r1"
|
||||||
|
|
||||||
|
val r2 = a.bar() + c.bar("K")
|
||||||
|
if (r2 != "OK") return "Fail2: $r2"
|
||||||
|
|
||||||
|
val r3 = c.qux() + c.qux("K")
|
||||||
|
if (r3 != "OK") return "Fail3: $r3"
|
||||||
|
|
||||||
|
if (a.s != "A") return "Fail4: ${a.s}"
|
||||||
|
if (c.s != "A") return "Fail5: ${c.s}"
|
||||||
|
|
||||||
|
val a2 = A("A2")
|
||||||
|
val c2 = C("C2")
|
||||||
|
|
||||||
|
val r6 = a2.s + c2.s
|
||||||
|
if (r6 != "A2C2") return "Fail6: $r6"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user