[JS IR] Export name and ordinal for enum classes

^KT-37916 fixed
^KT-44494 fixed
This commit is contained in:
Ilya Goncharov
2021-10-28 20:05:49 +03:00
committed by Space
parent a31a6c5117
commit 4fa2fa6c26
6 changed files with 42 additions and 10 deletions
@@ -108,7 +108,7 @@ class ExportModelGenerator(
// TODO: Report a frontend error
if (accessor.extensionReceiverParameter != null)
return null
if (accessor.isFakeOverride) {
if (accessor.isFakeOverride && !accessor.isEnumFakeOverriddenDeclaration(context)) {
return null
}
}
@@ -446,14 +446,15 @@ private fun shouldDeclarationBeExported(declaration: IrDeclarationWithName, cont
if (context?.additionalExportedDeclarations?.contains(declaration) == true)
return true
if (declaration is IrSimpleFunction) {
if (declaration is IrOverridableDeclaration<*>) {
val overriddenNonEmpty = declaration
.overriddenSymbols
.isNotEmpty()
if (overriddenNonEmpty) {
return declaration.isOverriddenExported(context) ||
declaration.isMethodOfAny() // Handle names for special functions
(declaration as? IrSimpleFunction)?.isMethodOfAny() == true // Handle names for special functions
|| declaration.isEnumFakeOverriddenDeclaration(context)
}
}
@@ -467,9 +468,21 @@ private fun shouldDeclarationBeExported(declaration: IrDeclarationWithName, cont
}
}
fun IrSimpleFunction.isOverriddenExported(context: JsIrBackendContext?): Boolean =
fun IrOverridableDeclaration<*>.isEnumFakeOverriddenDeclaration(context: JsIrBackendContext?): Boolean {
return context?.irBuiltIns?.enumClass?.let { enumClass ->
overriddenSymbols
.asSequence()
.map { it.owner }
.filterIsInstance<IrDeclaration>()
.mapNotNull { it.parentClassOrNull }
.map { it.symbol }
.any { it == enumClass }
} == true
}
fun IrOverridableDeclaration<*>.isOverriddenExported(context: JsIrBackendContext?): Boolean =
overriddenSymbols
.any { shouldDeclarationBeExported(it.owner, context) }
.any { shouldDeclarationBeExported(it.owner as IrDeclarationWithName, context) }
fun IrDeclaration.isExported(context: JsIrBackendContext?): Boolean {
val candidate = getExportCandidate(this) ?: return false
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.backend.js.export.isEnumFakeOverriddenDeclaration
import org.jetbrains.kotlin.ir.backend.js.export.isExported
import org.jetbrains.kotlin.ir.backend.js.export.isOverriddenExported
import org.jetbrains.kotlin.ir.backend.js.utils.*
@@ -108,7 +109,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
if (!property.visibility.isPublicAPI)
continue
if (property.isFakeOverride)
if (property.isFakeOverride && !property.isEnumFakeOverriddenDeclaration(context.staticContext.backendContext))
continue
fun IrSimpleFunction.propertyAccessorForwarder(
@@ -140,15 +141,16 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
// so we need regenerate `defineProperty` with setter.
val noOverriddenGetter = property.getter?.overriddenSymbols?.isEmpty() == true
val overriddenExportedGetter = property.getter?.overriddenSymbols?.isNotEmpty() == true &&
property.getter?.isOverriddenExported(context.staticContext.backendContext) == true
val overriddenExportedGetter = (property.getter?.overriddenSymbols?.isNotEmpty() == true &&
property.getter?.isOverriddenExported(context.staticContext.backendContext) == true)
val noOverriddenExportedSetter = property.setter?.isOverriddenExported(context.staticContext.backendContext) == false
val needOverrideBySetter = overriddenExportedGetter && noOverriddenExportedSetter
val needsOverride = (overriddenExportedGetter && noOverriddenExportedSetter) ||
property.isEnumFakeOverriddenDeclaration(context.staticContext.backendContext)
if (irClass.isExported(context.staticContext.backendContext) &&
(noOverriddenGetter || needOverrideBySetter) ||
(noOverriddenGetter || needsOverride) ||
property.getter?.overridesExternal() == true ||
property.getJsName() != null
) {
@@ -74,5 +74,11 @@ function box() {
if (this["export_enum_class"].Foo.values().indexOf(this["export_enum_class"].Foo.A) === -1) return "fail20"
if (this["export_enum_class"].Foo.values().indexOf(this["export_enum_class"].Foo.B) === -1) return "fail21"
if (this["export_enum_class"].Foo.A.name !== "A") return "fail22"
if (this["export_enum_class"].Foo.B.name !== "B") return "fail23"
if (this["export_enum_class"].Foo.A.ordinal !== 0) return "fail24"
if (this["export_enum_class"].Foo.B.ordinal !== 1) return "fail23"
return "OK"
}
@@ -108,6 +108,8 @@ declare namespace JS_TESTS {
bay(): string;
static values(): Array<foo.TestEnumClass>;
static valueOf(value: string): foo.TestEnumClass;
readonly name: string;
readonly ordinal: number;
}
namespace TestEnumClass {
class Nested {
@@ -107,6 +107,10 @@ function box() {
assert(TestEnumClass.valueOf("B") === TestEnumClass.B);
assert(TestEnumClass.values().indexOf(TestEnumClass.A) != -1);
assert(TestEnumClass.values().indexOf(TestEnumClass.B) != -1);
assert(TestEnumClass.A.name === "A");
assert(TestEnumClass.B.name === "B");
assert(TestEnumClass.A.ordinal === 0);
assert(TestEnumClass.B.ordinal === 1);
assert(new TestEnumClass.Nested().prop == "hello2");
return "OK";
}
@@ -126,6 +126,11 @@ function box(): string {
assert(TestEnumClass.values().indexOf(TestEnumClass.A) != -1)
assert(TestEnumClass.values().indexOf(TestEnumClass.B) != -1)
assert(TestEnumClass.A.name === "A")
assert(TestEnumClass.B.name === "B")
assert(TestEnumClass.A.ordinal === 0)
assert(TestEnumClass.B.ordinal === 1)
assert(new TestEnumClass.Nested().prop == "hello2")
return "OK";