rra/ilgonmic/kt-51973
[JS IR] Add non overridden property and method insode exported class [JS IR] Add method into exported interface in test [JS IR] Add interface properties cases to all file export test [JS IR] Fix usage of isExported inside IrJsUtils Co-authored-by: Anton Bannykh <Anton.Bannykh@jetbrains.com> Merge-request: KT-MR-6087 Merged-by: Ilya Goncharov <Ilya.Goncharov@jetbrains.com> ^KT-51973 fixed
This commit is contained in:
+1
-1
@@ -668,7 +668,7 @@ private fun shouldDeclarationBeExported(declaration: IrDeclarationWithName, cont
|
||||
}
|
||||
|
||||
fun IrOverridableDeclaration<*>.isAllowedFakeOverriddenDeclaration(context: JsIrBackendContext): Boolean {
|
||||
if (this.resolveFakeOverride(allowAbstract = true)?.parentClassOrNull.isExportedInterface()) {
|
||||
if (this.resolveFakeOverride(allowAbstract = true)?.parentClassOrNull.isExportedInterface(context)) {
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -134,6 +134,8 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
|
||||
|
||||
val overriddenSymbols = property.getter?.overriddenSymbols.orEmpty()
|
||||
|
||||
val backendContext = context.staticContext.backendContext
|
||||
|
||||
// Don't generate `defineProperty` if the property overrides a property from an exported class,
|
||||
// because we've already generated `defineProperty` for the base class property.
|
||||
// In other words, we only want to generate `defineProperty` once for each property.
|
||||
@@ -142,7 +144,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
|
||||
// P.S. If the overridden property is owned by an interface - we should generate defineProperty
|
||||
// for overridden property in the first class which override those properties
|
||||
val hasOverriddenExportedInterfaceProperties = overriddenSymbols.any { it.owner.isDefinedInsideExportedInterface() }
|
||||
&& !overriddenSymbols.any { it.owner.parentClassOrNull.isExportedClass() }
|
||||
&& !overriddenSymbols.any { it.owner.parentClassOrNull.isExportedClass(backendContext) }
|
||||
|
||||
val getterOverridesExternal = property.getter?.overridesExternal() == true
|
||||
val overriddenExportedGetter = !property.getter?.overriddenSymbols.isNullOrEmpty() &&
|
||||
@@ -213,7 +215,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
|
||||
}
|
||||
|
||||
private fun IrSimpleFunction.isDefinedInsideExportedInterface(): Boolean {
|
||||
return (!isFakeOverride && parentClassOrNull.isExportedInterface()) ||
|
||||
return (!isFakeOverride && parentClassOrNull.isExportedInterface(context.staticContext.backendContext)) ||
|
||||
overriddenSymbols.any { it.owner.isDefinedInsideExportedInterface() }
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -124,7 +124,7 @@ fun translateCall(
|
||||
val property = function.correspondingPropertySymbol?.owner
|
||||
if (
|
||||
property != null &&
|
||||
(property.isEffectivelyExternal() || property.isExportedMember())
|
||||
(property.isEffectivelyExternal() || property.isExportedMember(context.staticContext.backendContext))
|
||||
) {
|
||||
val propertyName = context.getNameForProperty(property)
|
||||
val nameRef = when (jsDispatchReceiver) {
|
||||
|
||||
@@ -7,6 +7,8 @@ package org.jetbrains.kotlin.ir.backend.js.utils
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.isClass
|
||||
import org.jetbrains.kotlin.descriptors.isInterface
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.export.isExported
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithVisibility
|
||||
@@ -14,18 +16,15 @@ import org.jetbrains.kotlin.ir.expressions.IrReturn
|
||||
import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol
|
||||
import org.jetbrains.kotlin.ir.util.parentClassOrNull
|
||||
|
||||
fun IrDeclaration.isExportedMember() =
|
||||
fun IrDeclaration.isExportedMember(context: JsIrBackendContext) =
|
||||
(this is IrDeclarationWithVisibility && visibility.isPublicAPI) &&
|
||||
parentClassOrNull.let { it is IrClass && it.isJsExport() }
|
||||
parentClassOrNull?.isExported(context) == true
|
||||
|
||||
fun IrDeclaration?.isExportedClass() =
|
||||
this is IrClass && kind.isClass && isJsExport()
|
||||
fun IrDeclaration?.isExportedClass(context: JsIrBackendContext) =
|
||||
this is IrClass && kind.isClass && isExported(context)
|
||||
|
||||
fun IrDeclaration?.isExportedInterface() =
|
||||
this is IrClass && kind.isInterface && isJsExport()
|
||||
|
||||
fun IrDeclaration.isExportedInterfaceMember() =
|
||||
parentClassOrNull.isExportedInterface()
|
||||
fun IrDeclaration?.isExportedInterface(context: JsIrBackendContext) =
|
||||
this is IrClass && kind.isInterface && isExported(context)
|
||||
|
||||
fun IrReturn.isTheLastReturnStatementIn(target: IrReturnableBlockSymbol): Boolean {
|
||||
return target.owner.statements.lastOrNull() === this
|
||||
|
||||
+138
-2
@@ -9,15 +9,151 @@
|
||||
|
||||
abstract class A {
|
||||
abstract fun foo(k: String): String
|
||||
|
||||
abstract val bar: String
|
||||
|
||||
abstract val baz: String
|
||||
|
||||
abstract var bay: String
|
||||
|
||||
abstract var bat: String
|
||||
}
|
||||
|
||||
class B : A() {
|
||||
open class B : A() {
|
||||
override fun foo(k: String): String {
|
||||
return "O" + k
|
||||
}
|
||||
|
||||
override val bar: String = "bar"
|
||||
|
||||
override val baz: String
|
||||
get() = "baz"
|
||||
|
||||
override var bay: String = "bay"
|
||||
|
||||
private var _bat: String = "bat"
|
||||
|
||||
override var bat: String
|
||||
get() = _bat
|
||||
set(value) {
|
||||
_bat = value
|
||||
}
|
||||
}
|
||||
|
||||
interface I {
|
||||
val gap: String
|
||||
|
||||
val hap: String
|
||||
|
||||
var baz: String
|
||||
|
||||
var bay: String
|
||||
|
||||
fun foo(): String
|
||||
}
|
||||
|
||||
open class C : I {
|
||||
override val gap: String = "gap"
|
||||
|
||||
override val hap: String
|
||||
get() = "hap"
|
||||
|
||||
override var bay: String = "bay"
|
||||
|
||||
private var _baz = "baz"
|
||||
|
||||
override var baz: String
|
||||
get() = _baz
|
||||
set(value) {
|
||||
_baz = value
|
||||
}
|
||||
|
||||
val koo: String = "koo"
|
||||
|
||||
override fun foo(): String {
|
||||
return "foo"
|
||||
}
|
||||
|
||||
fun foi() = "foi"
|
||||
}
|
||||
|
||||
fun topFoo(a: A): String {
|
||||
if (a.bar != "bar3") return "fail"
|
||||
if (a.baz != "baz3") return "fail"
|
||||
return "OK"
|
||||
}
|
||||
|
||||
fun topBar(c: C): String {
|
||||
if (c.bay != "bay3") return "fail"
|
||||
if (c.baz != "baz3") return "fail"
|
||||
return "OK"
|
||||
}
|
||||
|
||||
// FILE: test.js
|
||||
|
||||
function box() {
|
||||
return new this["export_all_file"].B().foo("K");
|
||||
var exportObject = this["export_all_file"]
|
||||
|
||||
function H() {
|
||||
}
|
||||
|
||||
H.prototype = Object.create(exportObject.B.prototype);
|
||||
H.prototype.constructor = H;
|
||||
Object.defineProperty(H.prototype, "bar", {
|
||||
get: function() {
|
||||
return "bar3"
|
||||
}
|
||||
})
|
||||
|
||||
Object.defineProperty(H.prototype, "baz", {
|
||||
get: function() {
|
||||
return "baz3"
|
||||
}
|
||||
})
|
||||
|
||||
function J() {
|
||||
}
|
||||
|
||||
J.prototype = Object.create(exportObject.C.prototype);
|
||||
J.prototype.constructor = J;
|
||||
Object.defineProperty(J.prototype, "bay", {
|
||||
get: function() {
|
||||
return "bay3"
|
||||
}
|
||||
})
|
||||
|
||||
Object.defineProperty(J.prototype, "baz", {
|
||||
get: function() {
|
||||
return "baz3"
|
||||
}
|
||||
})
|
||||
|
||||
var b = new exportObject.B()
|
||||
if (b.foo("K") != "OK") return "fail 1";
|
||||
if (b.bar != "bar") return "fail 2"
|
||||
if (b.baz != "baz") return "fail 3"
|
||||
if (b.bay != "bay") return "fail 4"
|
||||
b.bay = "bay2"
|
||||
if (b.bay != "bay2") return "fail 5"
|
||||
if (b.bat != "bat") return "fail6"
|
||||
b.bat = "bat2"
|
||||
if (b.bat != "bat2") return "fail7"
|
||||
|
||||
var c = new exportObject.C()
|
||||
if (c.gap != "gap") return "fail 8"
|
||||
if (c.hap != "hap") return "fail 9"
|
||||
if (c.bay != "bay") return "fail 10"
|
||||
c.bay = c.bay + "2"
|
||||
if (c.bay != "bay2") return "fail 11"
|
||||
if (c.baz != "baz") return "fail 12"
|
||||
c.baz = c.baz + "2"
|
||||
if (c.baz != "baz2") return "fail 13"
|
||||
if (c.foo() != "foo") return "fail 14"
|
||||
if (c.koo != "koo") return "fail 15"
|
||||
if (c.foi() != "foi") return "fail 16"
|
||||
|
||||
if (exportObject.topFoo(new H()) != "OK") return "fail 17"
|
||||
if (exportObject.topBar(new J()) != "OK") return "fail 18"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Reference in New Issue
Block a user