Enum implementing exported interface

[JS IR] Not export get instance enum function

[JS IR] Enum corresponding class is not considered in export

[JS IR] All enums are abstract and with private constructor

[JS IR] Any methods is left in d.ts

[JS IR] Make enum with declarations inside corresponding class

[JS IR] Export of interface through fake override

[JS IR] Include enum entry corresponding class members into export model

Merge-request: KT-MR-5031

^KT-49779 fixed
^KT-49773 fixed
This commit is contained in:
Ilya Goncharov
2021-11-24 12:25:50 +00:00
committed by Space
parent 4181429c7e
commit 1481ad21f5
17 changed files with 440 additions and 41 deletions
@@ -405,7 +405,7 @@ fun usefulDeclarations(
// https://youtrack.jetbrains.com/issue/KT-46672
// TODO: Possibly solution with origin is not so good
// There is option with applying this hack to jsGetKClass
if (expression.origin == JsLoweredDeclarationOrigin.CLASS_REFERENCE) {
if (expression.origin == JsStatementOrigins.CLASS_REFERENCE) {
// Maybe we need to filter primary constructor
// Although at this time, we should have only primary constructor
(ref as IrClass)
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.ir.backend.js
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl
import org.jetbrains.kotlin.ir.expressions.IrStatementOriginImpl
object JsLoweredDeclarationOrigin : IrDeclarationOrigin {
object JS_INTRINSICS_STUB : IrDeclarationOriginImpl("JS_INTRINSICS_STUB")
@@ -16,5 +15,5 @@ object JsLoweredDeclarationOrigin : IrDeclarationOrigin {
object BRIDGE_WITHOUT_STABLE_NAME : IrDeclarationOriginImpl("BRIDGE_WITHOUT_STABLE_NAME")
object OBJECT_GET_INSTANCE_FUNCTION : IrDeclarationOriginImpl("OBJECT_GET_INSTANCE_FUNCTION")
object JS_SHADOWED_EXPORT : IrDeclarationOriginImpl("JS_SHADOWED_EXPORT")
object CLASS_REFERENCE : IrStatementOriginImpl("CLASS_REFERENCE")
object ENUM_GET_INSTANCE_FUNCTION : IrDeclarationOriginImpl("ENUM_GET_INSTANCE_FUNCTION")
}
@@ -37,8 +37,11 @@ data class ExportedFunction(
data class ExportedConstructor(
val parameters: List<ExportedParameter>,
val visibility: ExportedVisibility
) : ExportedDeclaration() {
val isProtected: Boolean
) : ExportedDeclaration()
get() = visibility == ExportedVisibility.PROTECTED
}
data class ExportedConstructSignature(
val parameters: List<ExportedParameter>,
@@ -131,3 +134,9 @@ sealed class ExportedType {
fun withImplicitlyExported(implicitlyExportedType: Boolean) =
if (implicitlyExportedType) ImplicitlyExportedType(this) else this
}
enum class ExportedVisibility(val keyword: String) {
DEFAULT(""),
PRIVATE("private "),
PROTECTED("protected ")
}
@@ -10,12 +10,14 @@ import org.jetbrains.kotlin.backend.common.ir.isMethodOfAny
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin
import org.jetbrains.kotlin.ir.backend.js.lower.ES6AddInternalParametersToConstructorPhase.ES6_INIT_BOX_PARAMETER
import org.jetbrains.kotlin.ir.backend.js.lower.ES6AddInternalParametersToConstructorPhase.ES6_RESULT_TYPE_PARAMETER
import org.jetbrains.kotlin.ir.backend.js.utils.getJsNameOrKotlinName
import org.jetbrains.kotlin.ir.backend.js.utils.isExportedInterface
import org.jetbrains.kotlin.ir.backend.js.utils.isJsExport
import org.jetbrains.kotlin.ir.backend.js.utils.sanitizeName
import org.jetbrains.kotlin.ir.declarations.*
@@ -71,8 +73,12 @@ class ExportModelGenerator(
}
}
private fun exportFunction(function: IrSimpleFunction): ExportedDeclaration? =
when (val exportability = functionExportability(function)) {
private fun exportFunction(function: IrSimpleFunction): ExportedDeclaration? {
if (function.origin == JsLoweredDeclarationOrigin.ENUM_GET_INSTANCE_FUNCTION) {
return null
}
return when (val exportability = functionExportability(function)) {
is Exportability.NotNeeded -> null
is Exportability.Prohibited -> ErrorDeclaration(exportability.reason)
is Exportability.Allowed -> {
@@ -90,6 +96,7 @@ class ExportModelGenerator(
)
}
}
}
private fun exportConstructor(constructor: IrConstructor): ExportedDeclaration? {
if (!constructor.isPrimary) return null
@@ -97,7 +104,7 @@ class ExportModelGenerator(
constructor.valueParameters.filterNot { it.origin === ES6_RESULT_TYPE_PARAMETER || it.origin === ES6_INIT_BOX_PARAMETER }
return ExportedConstructor(
parameters = allValueParameters.map { exportParameter(it) },
isProtected = constructor.visibility == DescriptorVisibilities.PROTECTED
visibility = constructor.visibility.toExportedVisibility()
)
}
@@ -115,7 +122,7 @@ class ExportModelGenerator(
// TODO: Report a frontend error
if (accessor.extensionReceiverParameter != null)
return null
if (accessor.isFakeOverride && !accessor.isEnumFakeOverriddenDeclaration(context)) {
if (accessor.isFakeOverride && !accessor.isAllowedFakeOverriddenDeclaration(context)) {
return null
}
}
@@ -254,11 +261,20 @@ class ExportModelGenerator(
enumExportedMember
}
val privateConstructor = ExportedConstructor(
parameters = emptyList(),
visibility = ExportedVisibility.PRIVATE
)
return exportClass(
klass,
members,
listOf(privateConstructor) + members,
nestedClasses
)
).let {
(it as ExportedClass).copy(
isAbstract = true,
)
}
}
private fun exportClassDeclarations(
@@ -382,7 +398,7 @@ class ExportModelGenerator(
val enumEntries = enumEntriesToOrdinal.keys
return when (candidate) {
is IrProperty -> {
if (candidate.isEnumFakeOverriddenDeclaration(context)) {
if (candidate.isAllowedFakeOverriddenDeclaration(context)) {
val type: ExportedType? = when (candidate.getExportedIdentifier()) {
"name" -> enumEntries
.map { it.getExportedIdentifier() }
@@ -507,7 +523,7 @@ class ExportModelGenerator(
return Exportability.Prohibited("Inline reified function")
if (function.isSuspend)
return Exportability.Prohibited("Suspend function")
if (function.isFakeOverride)
if (function.isFakeOverride && !function.isAllowedFakeOverriddenDeclaration(context))
return Exportability.NotNeeded
if (function.origin == JsLoweredDeclarationOrigin.BRIDGE_WITHOUT_STABLE_NAME ||
function.origin == JsLoweredDeclarationOrigin.BRIDGE_WITH_STABLE_NAME ||
@@ -524,9 +540,6 @@ class ExportModelGenerator(
return Exportability.NotNeeded
}
if (function.isFakeOverriddenFromAny())
return Exportability.NotNeeded
val nameString = function.name.asString()
if (nameString.endsWith("-impl"))
return Exportability.NotNeeded
@@ -605,7 +618,7 @@ private fun shouldDeclarationBeExported(declaration: IrDeclarationWithName, cont
if (overriddenNonEmpty) {
return declaration.isOverriddenExported(context) ||
(declaration as? IrSimpleFunction)?.isMethodOfAny() == true // Handle names for special functions
|| declaration.isEnumFakeOverriddenDeclaration(context)
|| declaration.isAllowedFakeOverriddenDeclaration(context)
}
}
@@ -619,12 +632,17 @@ private fun shouldDeclarationBeExported(declaration: IrDeclarationWithName, cont
}
}
fun IrOverridableDeclaration<*>.isEnumFakeOverriddenDeclaration(context: JsIrBackendContext?): Boolean {
fun IrOverridableDeclaration<*>.isAllowedFakeOverriddenDeclaration(context: JsIrBackendContext?): Boolean {
if (this.resolveFakeOverride(allowAbstract = true)?.parentClassOrNull.isExportedInterface()) {
return true
}
return context?.irBuiltIns?.enumClass?.let { enumClass ->
overriddenSymbols
.asSequence()
.map { it.owner }
.filterIsInstance<IrDeclaration>()
.filterIsInstance<IrOverridableDeclaration<*>>()
.filter { it.overriddenSymbols.isEmpty() }
.mapNotNull { it.parentClassOrNull }
.map { it.symbol }
.any { it == enumClass }
@@ -640,6 +658,12 @@ fun IrDeclaration.isExported(context: JsIrBackendContext?): Boolean {
return shouldDeclarationBeExported(candidate, context)
}
private fun DescriptorVisibility.toExportedVisibility() =
when (this) {
DescriptorVisibilities.PROTECTED -> ExportedVisibility.PROTECTED
else -> ExportedVisibility.DEFAULT
}
private val reservedWords = setOf(
"break",
"case",
@@ -93,9 +93,8 @@ fun ExportedDeclaration.toTypeScript(indent: String, prefix: String = ""): Strin
}
is ExportedConstructor -> {
val visibility = if (isProtected) "protected " else ""
val renderedParameters = parameters.joinToString(", ") { it.toTypeScript(indent) }
"${visibility}constructor($renderedParameters);"
"${visibility.keyword}constructor($renderedParameters);"
}
is ExportedConstructSignature -> {
@@ -220,7 +219,7 @@ fun ExportedClass.withProtectedConstructors(): ExportedClass {
if (it !is ExportedConstructor || it.isProtected) {
it
} else {
it.copy(isProtected = true)
it.copy(visibility = ExportedVisibility.PROTECTED)
}
})
}
@@ -142,7 +142,7 @@ class ClassReferenceLowering(val context: JsCommonBackendContext) : BodyLowering
JsIrBuilder.buildCall(
reflectionSymbols.getClassData,
typeArguments = listOf(type),
origin = JsLoweredDeclarationOrigin.CLASS_REFERENCE
origin = JsStatementOrigins.CLASS_REFERENCE
)
private fun buildCall(name: IrSimpleFunctionSymbol, vararg args: IrExpression): IrExpression =
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities.PRIVATE
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.backend.js.JsCommonBackendContext
import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.builders.declarations.buildConstructor
@@ -445,7 +446,7 @@ class EnumEntryCreateGetInstancesFunsLowering(val context: JsCommonBackendContex
context.irFactory.buildFun {
name = Name.identifier(createEntryAccessorName(irClass.name.identifier, enumEntry))
returnType = enumEntry.getType(irClass)
origin = JsIrBuilder.SYNTHESIZED_DECLARATION
origin = JsLoweredDeclarationOrigin.ENUM_GET_INSTANCE_FUNCTION
}.apply {
parent = irClass
}
@@ -6,9 +6,8 @@
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.backend.js.export.isEnumFakeOverriddenDeclaration
import org.jetbrains.kotlin.ir.backend.js.export.isAllowedFakeOverriddenDeclaration
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.*
@@ -102,7 +101,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
classBlock.statements += generateClassMetadata()
if (!irClass.isInterface && !irClass.isEnumEntry) {
if (!irClass.isInterface) {
for (property in properties) {
if (property.getter?.extensionReceiverParameter != null || property.setter?.extensionReceiverParameter != null)
continue
@@ -110,7 +109,10 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
if (!property.visibility.isPublicAPI)
continue
if (property.isFakeOverride && !property.isEnumFakeOverriddenDeclaration(context.staticContext.backendContext))
if (
property.isFakeOverride &&
!property.isAllowedFakeOverriddenDeclaration(context.staticContext.backendContext)
)
continue
fun IrSimpleFunction.propertyAccessorForwarder(
@@ -145,7 +147,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
val noOverriddenExportedSetter = property.setter?.isOverriddenExported(context.staticContext.backendContext) == false
val needsOverride = (overriddenExportedGetter && noOverriddenExportedSetter) ||
property.isEnumFakeOverriddenDeclaration(context.staticContext.backendContext)
property.isAllowedFakeOverriddenDeclaration(context.staticContext.backendContext)
if (irClass.isExported(context.staticContext.backendContext) &&
(overriddenSymbols.isEmpty() || needsOverride) ||
@@ -18,4 +18,5 @@ interface JsStatementOrigins {
object FACTORY_ORIGIN : IrDeclarationOriginImpl("FACTORY_ORIGIN")
object COROUTINE_ROOT_LOOP : IrStatementOriginImpl("COROUTINE_ROOT_LOOP")
object COROUTINE_SWITCH : IrStatementOriginImpl("COROUTINE_SWITCH")
object CLASS_REFERENCE : IrStatementOriginImpl("CLASS_REFERENCE")
}
+11 -9
View File
@@ -29,6 +29,7 @@ enum class Bar {
init {
d = "d2"
}
fun huh() = "huh"
};
val foo = ordinal
@@ -66,19 +67,20 @@ function box() {
if (this["export_enum_class"].Bar.A.bay() !== "A") return "fail15"
if (this["export_enum_class"].Bar.B.bay() !== "B") return "fail16"
if (this["export_enum_class"].Bar.B.constructor.prototype.hasOwnProperty('baz')) return "fail17"
if (this["export_enum_class"].Bar.B.constructor.prototype.hasOwnProperty('d')) return "fail17"
if (this["export_enum_class"].Bar.B.constructor.prototype.hasOwnProperty('huh')) return "fail18"
if (this["export_enum_class"].Foo.valueOf("A") !== this["export_enum_class"].Foo.A) return "fail18"
if (this["export_enum_class"].Foo.valueOf("B") !== this["export_enum_class"].Foo.B) return "fail19"
if (this["export_enum_class"].Foo.valueOf("A") !== this["export_enum_class"].Foo.A) return "fail19"
if (this["export_enum_class"].Foo.valueOf("B") !== this["export_enum_class"].Foo.B) return "fail20"
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.values().indexOf(this["export_enum_class"].Foo.A) === -1) return "fail21"
if (this["export_enum_class"].Foo.values().indexOf(this["export_enum_class"].Foo.B) === -1) return "fail22"
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.name !== "A") return "fail23"
if (this["export_enum_class"].Foo.B.name !== "B") return "fail24"
if (this["export_enum_class"].Foo.A.ordinal !== 0) return "fail24"
if (this["export_enum_class"].Foo.B.ordinal !== 1) return "fail23"
if (this["export_enum_class"].Foo.A.ordinal !== 0) return "fail25"
if (this["export_enum_class"].Foo.B.ordinal !== 1) return "fail26"
return "OK"
}
@@ -100,7 +100,7 @@ declare namespace JS_TESTS {
readonly prop: string;
}
}
class TestEnumClass {
abstract class TestEnumClass {
private constructor();
readonly constructorParameter: string;
static readonly A: foo.TestEnumClass & {
@@ -37,5 +37,62 @@ declare namespace JS_TESTS {
const O2: {
foo(): number;
} & foo.OC;
interface I3 {
readonly foo: string;
bar: string;
readonly baz: string;
bay(): string;
readonly __doNotUseIt: __doNotImplementIt;
}
function getI3(): foo.I3;
function getA(): foo.I3;
function getB(): foo.I3;
function getC(): foo.I3;
abstract class A2 implements foo.I3 {
constructor();
abstract readonly foo: string;
abstract bar: string;
abstract readonly baz: string;
abstract bay(): string;
readonly __doNotUseIt: __doNotImplementIt;
}
class B2 extends foo.A2 {
constructor();
readonly foo: string;
bar: string;
readonly baz: string;
bay(): string;
}
class C2 extends foo.B2 {
constructor();
readonly foo: string;
bar: string;
baz: string;
bay(): string;
}
abstract class EC implements foo.I3 {
private constructor();
static readonly EC1: foo.EC & {
readonly name: "EC1";
readonly ordinal: 0;
};
static readonly EC2: foo.EC & {
readonly name: "EC2";
readonly ordinal: 1;
};
static readonly EC3: foo.EC & {
readonly name: "EC3";
readonly ordinal: 2;
};
readonly foo: string;
bar: string;
bay(): string;
static values(): Array<foo.EC>;
static valueOf(value: string): foo.EC;
readonly name: "EC1" | "EC2" | "EC3";
readonly ordinal: 0 | 1 | 2;
abstract readonly baz: string;
readonly __doNotUseIt: __doNotImplementIt;
}
}
}
@@ -7,22 +7,23 @@
// MODULE: JS_TESTS
// FILE: inheritance.kt
@file:JsExport
package foo
@JsExport
external interface I<T, out S, in U> {
var x: T
val y: S
fun z(u: U)
}
@JsExport
external interface I2 {
var x: String
val y: Boolean
fun z(z: Int)
}
@JsExport
abstract class AC : I2 {
override var x = "AC"
override abstract val y: Boolean
@@ -32,6 +33,7 @@ abstract class AC : I2 {
abstract val acAbstractProp: String
}
@JsExport
open class OC(
override val y: Boolean,
override val acAbstractProp: String
@@ -43,11 +45,121 @@ open class OC(
private fun privateFun(): String = "privateFun"
}
@JsExport
final class FC : OC(true, "FC")
@JsExport
object O1 : OC(true, "O1")
@JsExport
object O2 : OC(true, "O2") {
@JsName("foo") // TODO: Should work without JsName
fun foo(): Int = 10
}
}
@JsExport
interface I3 {
val foo: String
var bar: String
val baz: String
fun bay(): String
}
@JsExport
fun getI3(): I3 = object : I3 {
override val foo: String = "fooI3"
override var bar: String = "barI3"
override var baz: String = "bazI3"
override fun bay(): String = "bayI3"
}
abstract class A : I3
@JsExport
fun getA(): I3 = object : A() {
override val foo: String = "fooA"
override var bar: String = "barA"
override var baz: String = "bazA"
override fun bay(): String = "bayA"
}
open class B : A() {
override val foo: String = "fooB"
override var bar: String = "barB"
override val baz: String = "bazB"
override fun bay(): String = "bayB"
}
@JsExport
fun getB(): I3 = B()
open class C : B() {
override val foo: String = "fooC"
override var bar: String = "barC"
override var baz: String = "bazC"
override fun bay(): String = "bayC"
}
@JsExport
fun getC(): I3 = C()
@JsExport
abstract class A2 : I3
@JsExport
open class B2 : A2() {
override val foo: String = "fooB2"
override var bar: String = "barB2"
override val baz: String = "bazB2"
override fun bay(): String = "bayB2"
}
@JsExport
open class C2 : B2() {
override val foo: String = "fooC2"
override var bar: String = "barC2"
override var baz: String = "bazC2"
override fun bay(): String = "bayC2"
}
@JsExport
enum class EC : I3 {
EC1 {
override var baz = "ec1"
val bah = "bah"
fun huh() = "huh"
},
EC2 {
override var baz = "ec2"
},
EC3 {
override var baz = "ec3"
};
override val foo: String = "foo"
override var bar = "bar"
override fun bay(): String = "bay"
}
@@ -17,6 +17,13 @@ var AC = JS_TESTS.foo.AC;
var FC = JS_TESTS.foo.FC;
var O1 = JS_TESTS.foo.O1;
var O2 = JS_TESTS.foo.O2;
var getI3 = JS_TESTS.foo.getI3;
var getA = JS_TESTS.foo.getA;
var getB = JS_TESTS.foo.getB;
var getC = JS_TESTS.foo.getC;
var B2 = JS_TESTS.foo.B2;
var C2 = JS_TESTS.foo.C2;
var EC = JS_TESTS.foo.EC;
var Impl = /** @class */ (function (_super) {
__extends(Impl, _super);
function Impl() {
@@ -36,6 +43,16 @@ var Impl = /** @class */ (function (_super) {
});
return Impl;
}(AC));
// class A2Impl extends A2 {
// bar: string = "barA2"
// readonly baz: string = "bazA2"
// readonly foo: string = "fooA2"
//
// bay(): string {
// return "bayA2";
// }
//
// }
function box() {
var impl = new Impl();
if (impl.acProp !== "acProp")
@@ -66,5 +83,87 @@ function box() {
return "Fail 9";
if (O2.foo() != 10)
return "Fail 10";
if (getI3().foo != "fooI3")
return "Fail 11";
if (getI3().bar != "barI3")
return "Fail 12";
if (getI3().baz != "bazI3")
return "Fail 13";
if (getI3().bay() != "bayI3")
return "Fail 14";
if (getA().foo != "fooA")
return "Fail 15";
if (getA().bar != "barA")
return "Fail 16";
if (getA().baz != "bazA")
return "Fail 17";
if (getA().bay() != "bayA")
return "Fail 18";
if (getB().foo != "fooB")
return "Fail 19";
if (getB().bar != "barB")
return "Fail 20";
if (getB().baz != "bazB")
return "Fail 21";
if (getB().bay() != "bayB")
return "Fail 22";
if (getC().foo != "fooC")
return "Fail 23";
if (getC().bar != "barC")
return "Fail 24";
if (getC().baz != "bazC")
return "Fail 25";
if (getC().bay() != "bayC")
return "Fail 26";
// const a2Impl = new A2Impl()
// if (a2Impl.foo != "fooA2") return "Fail 27"
// if (a2Impl.bar != "barA2") return "Fail 28"
// if (a2Impl.baz != "bazA2") return "Fail 29"
// if (a2Impl.bay() != "bayA2") return "Fail 30"
var b2 = new B2();
if (b2.foo != "fooB2")
return "Fail 31";
if (b2.bar != "barB2")
return "Fail 32";
if (b2.baz != "bazB2")
return "Fail 33";
if (b2.bay() != "bayB2")
return "Fail 34";
var c2 = new C2();
if (c2.foo != "fooC2")
return "Fail 35";
if (c2.bar != "barC2")
return "Fail 36";
if (c2.baz != "bazC2")
return "Fail 37";
c2.baz = "bazC2-2";
if (c2.baz != "bazC2-2")
return "Fail 38";
if (c2.bay() != "bayC2")
return "Fail 39";
if (EC.EC1.foo != "foo")
return "Fail 40";
if (EC.EC1.bar != "bar")
return "Fail 41";
if (EC.EC1.baz != "ec1")
return "Fail 42";
if (EC.EC1.bay() != "bay")
return "Fail 43";
if (EC.EC2.foo != "foo")
return "Fail 44";
if (EC.EC2.bar != "bar")
return "Fail 45";
if (EC.EC2.baz != "ec2")
return "Fail 46";
if (EC.EC2.bay() != "bay")
return "Fail 47";
if (EC.EC3.foo != "foo")
return "Fail 48";
if (EC.EC3.bar != "bar")
return "Fail 49";
if (EC.EC3.baz != "ec3")
return "Fail 50";
if (EC.EC3.bay() != "bay")
return "Fail 51";
return "OK";
}
@@ -3,6 +3,13 @@ import AC = JS_TESTS.foo.AC;
import FC = JS_TESTS.foo.FC;
import O1 = JS_TESTS.foo.O1;
import O2 = JS_TESTS.foo.O2;
import getI3 = JS_TESTS.foo.getI3;
import getA = JS_TESTS.foo.getA;
import getB = JS_TESTS.foo.getB;
import getC = JS_TESTS.foo.getC;
import B2 = JS_TESTS.foo.B2;
import C2 = JS_TESTS.foo.C2;
import EC = JS_TESTS.foo.EC;
class Impl extends AC {
z(z: number): void {
@@ -12,6 +19,18 @@ class Impl extends AC {
get y(): boolean { return true; }
}
// TODO: Uncomment with fix of export open properties
// class A2Impl extends A2 {
// bar: string = "barA2"
// readonly baz: string = "bazA2"
// readonly foo: string = "fooA2"
//
// bay(): string {
// return "bayA2";
// }
//
// }
function box(): string {
const impl = new Impl();
if (impl.acProp !== "acProp") return "Fail 1";
@@ -36,5 +55,60 @@ function box(): string {
if (O2.acAbstractProp != "O2") return "Fail 9";
if (O2.foo() != 10) return "Fail 10";
if (getI3().foo != "fooI3") return "Fail 11"
if (getI3().bar != "barI3") return "Fail 12"
if (getI3().baz != "bazI3") return "Fail 13"
if (getI3().bay() != "bayI3") return "Fail 14"
if (getA().foo != "fooA") return "Fail 15"
if (getA().bar != "barA") return "Fail 16"
if (getA().baz != "bazA") return "Fail 17"
if (getA().bay() != "bayA") return "Fail 18"
if (getB().foo != "fooB") return "Fail 19"
if (getB().bar != "barB") return "Fail 20"
if (getB().baz != "bazB") return "Fail 21"
if (getB().bay() != "bayB") return "Fail 22"
if (getC().foo != "fooC") return "Fail 23"
if (getC().bar != "barC") return "Fail 24"
if (getC().baz != "bazC") return "Fail 25"
if (getC().bay() != "bayC") return "Fail 26"
// const a2Impl = new A2Impl()
// if (a2Impl.foo != "fooA2") return "Fail 27"
// if (a2Impl.bar != "barA2") return "Fail 28"
// if (a2Impl.baz != "bazA2") return "Fail 29"
// if (a2Impl.bay() != "bayA2") return "Fail 30"
const b2 = new B2()
if (b2.foo != "fooB2") return "Fail 31"
if (b2.bar != "barB2") return "Fail 32"
if (b2.baz != "bazB2") return "Fail 33"
if (b2.bay() != "bayB2") return "Fail 34"
const c2 = new C2()
if (c2.foo != "fooC2") return "Fail 35"
if (c2.bar != "barC2") return "Fail 36"
if (c2.baz != "bazC2") return "Fail 37"
c2.baz = "bazC2-2"
if (c2.baz != "bazC2-2") return "Fail 38"
if (c2.bay() != "bayC2") return "Fail 39"
if (EC.EC1.foo != "foo") return "Fail 40"
if (EC.EC1.bar != "bar") return "Fail 41"
if (EC.EC1.baz != "ec1") return "Fail 42"
if (EC.EC1.bay() != "bay") return "Fail 43"
if (EC.EC2.foo != "foo") return "Fail 44"
if (EC.EC2.bar != "bar") return "Fail 45"
if (EC.EC2.baz != "ec2") return "Fail 46"
if (EC.EC2.bay() != "bay") return "Fail 47"
if (EC.EC3.foo != "foo") return "Fail 48"
if (EC.EC3.bar != "bar") return "Fail 49"
if (EC.EC3.baz != "ec3") return "Fail 50"
if (EC.EC3.bay() != "bay") return "Fail 51"
return "OK";
}
@@ -33,4 +33,19 @@ declare namespace JS_TESTS {
constructor();
}
}
abstract class EnumClass {
private constructor();
static readonly EC1: EnumClass & {
readonly name: "EC1";
readonly ordinal: 0;
};
static readonly EC2: EnumClass & {
readonly name: "EC2";
readonly ordinal: 1;
};
static values(): Array<EnumClass>;
static valueOf(value: string): EnumClass;
readonly name: "EC1" | "EC2";
readonly ordinal: 0 | 1;
}
}
@@ -54,4 +54,9 @@ open class Class {
@JsName("publicFun") // TODO: Should work without JsName
public fun publicFun() = 10
public class publicClass
}
enum class EnumClass {
EC1,
EC2
}