[JS IR] Export nested objects

Companion objects are exported as ParentClass.Companion.
Companion object's members are not exposed to its parent class —
one must reference the companion object explicitly if they want to
access its members.

#KT-43783 Fixed
This commit is contained in:
Sergej Jaskiewicz
2021-08-26 16:30:23 +03:00
committed by TeamCityServer
parent 862f8cdad8
commit be999564b1
7 changed files with 83 additions and 3 deletions
@@ -86,9 +86,15 @@ class ExportModelToJsStatements(
)
).makeStmt()
// These are only used when exporting secondary constructors annotated with @JsName
val staticFunctions = declaration.members.filter { it is ExportedFunction && it.isStatic }
val staticsExport = (staticFunctions + declaration.nestedClasses)
// Nested objects are exported as static properties
val staticProperties = declaration.members.mapNotNull {
(it as? ExportedProperty)?.takeIf { it.isStatic }
}
val staticsExport = (staticFunctions + staticProperties + declaration.nestedClasses)
.flatMap { generateDeclarationExport(it, newNameSpace) }
listOf(klassExport) + staticsExport
@@ -1627,6 +1627,11 @@ public class IrBoxJsES6TestGenerated extends AbstractIrBoxJsES6Test {
runTest("js/js.translator/testData/box/export/exportNestedClass.kt");
}
@TestMetadata("exportNestedObject.kt")
public void testExportNestedObject() throws Exception {
runTest("js/js.translator/testData/box/export/exportNestedObject.kt");
}
@TestMetadata("nonIndetifierModuleName.kt")
public void testNonIndetifierModuleName() throws Exception {
runTest("js/js.translator/testData/box/export/nonIndetifierModuleName.kt");
@@ -1627,6 +1627,11 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
runTest("js/js.translator/testData/box/export/exportNestedClass.kt");
}
@TestMetadata("exportNestedObject.kt")
public void testExportNestedObject() throws Exception {
runTest("js/js.translator/testData/box/export/exportNestedObject.kt");
}
@TestMetadata("nonIndetifierModuleName.kt")
public void testNonIndetifierModuleName() throws Exception {
runTest("js/js.translator/testData/box/export/nonIndetifierModuleName.kt");
@@ -1632,6 +1632,11 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
runTest("js/js.translator/testData/box/export/exportNestedClass.kt");
}
@TestMetadata("exportNestedObject.kt")
public void testExportNestedObject() throws Exception {
runTest("js/js.translator/testData/box/export/exportNestedObject.kt");
}
@TestMetadata("nonIndetifierModuleName.kt")
public void testNonIndetifierModuleName() throws Exception {
runTest("js/js.translator/testData/box/export/nonIndetifierModuleName.kt");
@@ -0,0 +1,58 @@
// EXPECTED_REACHABLE_NODES: 1265
// RUN_PLAIN_BOX_FUNCTION
// INFER_MAIN_MODULE
// SKIP_MINIFICATION
// SKIP_DCE_DRIVEN
// SKIP_NODE_JS
// See KT-43783
// MODULE: nestedObjectExport
// FILE: lib.kt
@JsExport
class Abc {
companion object AbcCompanion {
fun xyz(): String = "Companion object method OK"
val prop: String
get() = "Companion object property OK"
}
}
@JsExport
class Foo {
companion object {
fun xyz(): String = "Companion object method OK"
val prop: String
get() = "Companion object property OK"
}
}
@JsExport
sealed class MyEnum(val name: String) {
object A: MyEnum("A")
object B: MyEnum("B")
object C: MyEnum("C")
}
// FILE: test.js
function box() {
const abcCompanion = nestedObjectExport.Abc.AbcCompanion;
if (abcCompanion.xyz() != 'Companion object method OK') return 'companion object function failure';
if (abcCompanion.prop != 'Companion object property OK') return 'companion object property failure';
const justCompanion = nestedObjectExport.Foo.Companion;
if (justCompanion.xyz() != 'Companion object method OK') return 'companion object function failure';
if (justCompanion.prop != 'Companion object property OK') return 'companion object property failure';
if (nestedObjectExport.MyEnum.A.name != 'A') return 'MyEnum.A failure';
if (nestedObjectExport.MyEnum.B.name != 'B') return 'MyEnum.B failure';
if (nestedObjectExport.MyEnum.C.name != 'C') return 'MyEnum.C failure';
return 'OK';
}
@@ -96,8 +96,6 @@ object O {
fun takesO(o: O): Int =
O.x + O.foo()
// Test that JsExport with companion object compiles without error.
// Usage is not supported yet.
class KT_37829 {
companion object {
val x = 10
@@ -22,6 +22,7 @@ import _valCustomWithField = JS_TESTS.foo._valCustomWithField;
import A4 = JS_TESTS.foo.A4;
import O = JS_TESTS.foo.O;
import takesO = JS_TESTS.foo.takesO;
import KT_37829 = JS_TESTS.foo.KT_37829;
function assert(condition: boolean) {
if (!condition) {
@@ -92,5 +93,7 @@ function box(): string {
assert(O.foo() === 20);
assert(takesO(O) === 30);
assert(KT_37829.Companion.x == 10);
return "OK";
}