[K/JS] Move ES modules logic to a new transformer with IC

This commit is contained in:
Artem Kobzar
2022-10-13 07:32:44 +00:00
committed by Space Team
parent 54deba63a1
commit de880ce9aa
88 changed files with 2476 additions and 1134 deletions
@@ -0,0 +1,31 @@
// DONT_TARGET_EXACT_BACKEND: JS
// ES_MODULES
// MODULE: bridge_saving_after_export
// FILE: lib.kt
@JsExport
open class A<T> {
open fun foo(value: T): T = value
}
@JsExport
class B: A<String>() {
override fun foo(value: String): String = value
}
// FILE: entry.mjs
// ENTRY_ES_MODULE
import { A, B } from "./bridgeSavingAfterExport-bridge_saving_after_export_v5.mjs";
export function box() {
var a = new A()
var aFoo = a.foo("ok")
if (aFoo != "ok") return "fail 1"
var b = new B()
var bFoo = b.foo("ok")
if (bFoo != "ok") return "fail 2"
return "OK"
}
@@ -0,0 +1,30 @@
// DONT_TARGET_EXACT_BACKEND: JS
// ES_MODULES
// MODULE: bridge_saving_after_export
// FILE: lib.kt
@file:JsExport
open class A<T> {
open fun foo(value: T): T = value
}
class B: A<String>() {
override fun foo(value: String): String = value
}
// FILE: entry.mjs
// ENTRY_ES_MODULE
import { A, B } from "./bridgeSavingAfterExportInExportedFile-bridge_saving_after_export_v5.mjs";
export function box() {
var a = new A()
var aFoo = a.foo("ok")
if (aFoo != "ok") return "fail 1"
var b = new B()
var bFoo = b.foo("ok")
if (bFoo != "ok") return "fail 2"
return "OK"
}
@@ -0,0 +1,22 @@
// IGNORE_FIR
// KT-49225
// DONT_TARGET_EXACT_BACKEND: JS
// ES_MODULES
// SPLIT_PER_MODULE
// MODULE: lib
// FILE: lib.kt
value class Koo(val koo: String = "OK")
@JsExport
class Bar(val koo: Koo = Koo())
// MODULE: main(lib)
// FILE: entry.mjs
// ENTRY_ES_MODULE
import { Bar } from "./defaultInlineClassConstructorParam-kotlin_lib_v5.mjs";
export function box() {
return new Bar().koo;
}
@@ -0,0 +1,24 @@
// IGNORE_FIR
// KT-49225
// ES_MODULES
// DONT_TARGET_EXACT_BACKEND: JS
// SPLIT_PER_MODULE
// MODULE: lib
// FILE: koo.kt
value class Koo(val koo: String = "OK")
// FILE: bar.kt
@file:JsExport
class Bar(val koo: Koo = Koo())
// MODULE: main(lib)
// FILE: entry.mjs
// ENTRY_ES_MODULE
import { Bar } from "./defaultInlineClassConstructorParamInExportedFile-kotlin_lib_v5.mjs";
export function box() {
return new Bar().koo;
}
@@ -1,6 +1,5 @@
// DONT_TARGET_EXACT_BACKEND: JS
// EXPECTED_REACHABLE_NODES: 1252
// INFER_MAIN_MODULE
// ES_MODULES
// MODULE: export_all_file
@@ -19,5 +18,9 @@ class B : A() {
// FILE: entry.mjs
// ENTRY_ES_MODULE
import { B } from "./export_all_file/index.js";
console.assert(new B().foo("K") == "OK");
import { B } from "./exportAllFile-export_all_file_v5.mjs";
export function box() {
return new B().foo("K")
}
@@ -0,0 +1,103 @@
// DONT_TARGET_EXACT_BACKEND: JS
// ES_MODULES
// MODULE: export_enum_class
// FILE: lib.kt
@JsExport
enum class Foo(val constructorParameter: String) {
A("aConstructorParameter"),
B("bConstructorParameter");
val foo = ordinal
fun bar(value: String) = value
fun bay() = name
companion object {
val baz = "baz"
}
}
@JsExport
enum class Bar {
A,
B {
var d = "d"
init {
d = "d2"
}
fun huh() = "huh"
};
val foo = ordinal
fun bar(value: String) = value
fun bay() = name
}
@JsExport
class OuterClass {
enum class NestedEnum {
A,
B;
}
}
// FILE: main.mjs
// ENTRY_ES_MODULE
import { Foo, Bar, OuterClass } from "./exportEnumClass-export_enum_class_v5.mjs"
export function box() {
if (Foo.A !== Foo.A) return "fail1"
if (Foo.B !== Foo.B) return "fail2"
if (Foo.Companion.baz !== "baz") return "fail3"
if (Foo.A.foo !== 0) return "fail4"
if (Foo.B.foo !== 1) return "fail5"
if (Foo.A.bar("A") !== "A") return "fail6"
if (Foo.B.bar("B") !== "B") return "fail7"
if (Foo.A.bay() !== "A") return "fail8"
if (Foo.B.bay() !== "B") return "fail9"
if (Foo.A.constructorParameter !== "aConstructorParameter") return "fail10"
if (Foo.B.constructorParameter !== "bConstructorParameter") return "fail11"
if (Bar.A.foo !== 0) return "fail12"
if (Bar.B.foo !== 1) return "fail13"
if (Bar.A.bar("A") !== "A") return "fail14"
if (Bar.B.bar("B") !== "B") return "fail15"
if (Bar.A.bay() !== "A") return "fail15"
if (Bar.B.bay() !== "B") return "fail16"
if (Bar.B.constructor.prototype.hasOwnProperty('d')) return "fail17"
if (Bar.B.constructor.prototype.hasOwnProperty('huh')) return "fail18"
if (Foo.valueOf("A") !== Foo.A) return "fail19"
if (Foo.valueOf("B") !== Foo.B) return "fail20"
if (Foo.values().indexOf(Foo.A) === -1) return "fail21"
if (Foo.values().indexOf(Foo.B) === -1) return "fail22"
if (Foo.A.name !== "A") return "fail23"
if (Foo.B.name !== "B") return "fail24"
if (Foo.A.ordinal !== 0) return "fail25"
if (Foo.B.ordinal !== 1) return "fail26"
if (OuterClass.NestedEnum.A.name !== "A") return "fail27"
if (OuterClass.NestedEnum.B.name !== "B") return "fail28"
if (OuterClass.NestedEnum.A.ordinal !== 0) return "fail29"
if (OuterClass.NestedEnum.B.ordinal !== 1) return "fail30"
return "OK"
}
@@ -0,0 +1,100 @@
// DONT_TARGET_EXACT_BACKEND: JS
// ES_MODULES
// MODULE: export_enum_class
// FILE: lib.kt
@file:JsExport
enum class Foo(val constructorParameter: String) {
A("aConstructorParameter"),
B("bConstructorParameter");
val foo = ordinal
fun bar(value: String) = value
fun bay() = name
companion object {
val baz = "baz"
}
}
enum class Bar {
A,
B {
var d = "d"
init {
d = "d2"
}
fun huh() = "huh"
};
val foo = ordinal
fun bar(value: String) = value
fun bay() = name
}
class OuterClass {
enum class NestedEnum {
A,
B;
}
}
// FILE: main.mjs
// ENTRY_ES_MODULE
import { Foo, Bar, OuterClass } from "./exportFileWithEnumClass-export_enum_class_v5.mjs"
export function box() {
if (Foo.A !== Foo.A) return "fail1"
if (Foo.B !== Foo.B) return "fail2"
if (Foo.Companion.baz !== "baz") return "fail3"
if (Foo.A.foo !== 0) return "fail4"
if (Foo.B.foo !== 1) return "fail5"
if (Foo.A.bar("A") !== "A") return "fail6"
if (Foo.B.bar("B") !== "B") return "fail7"
if (Foo.A.bay() !== "A") return "fail8"
if (Foo.B.bay() !== "B") return "fail9"
if (Foo.A.constructorParameter !== "aConstructorParameter") return "fail10"
if (Foo.B.constructorParameter !== "bConstructorParameter") return "fail11"
if (Bar.A.foo !== 0) return "fail12"
if (Bar.B.foo !== 1) return "fail13"
if (Bar.A.bar("A") !== "A") return "fail14"
if (Bar.B.bar("B") !== "B") return "fail15"
if (Bar.A.bay() !== "A") return "fail15"
if (Bar.B.bay() !== "B") return "fail16"
if (Bar.B.constructor.prototype.hasOwnProperty('d')) return "fail17"
if (Bar.B.constructor.prototype.hasOwnProperty('huh')) return "fail18"
if (Foo.valueOf("A") !== Foo.A) return "fail19"
if (Foo.valueOf("B") !== Foo.B) return "fail20"
if (Foo.values().indexOf(Foo.A) === -1) return "fail21"
if (Foo.values().indexOf(Foo.B) === -1) return "fail22"
if (Foo.A.name !== "A") return "fail23"
if (Foo.B.name !== "B") return "fail24"
if (Foo.A.ordinal !== 0) return "fail25"
if (Foo.B.ordinal !== 1) return "fail26"
if (OuterClass.NestedEnum.A.name !== "A") return "fail27"
if (OuterClass.NestedEnum.B.name !== "B") return "fail28"
if (OuterClass.NestedEnum.A.ordinal !== 0) return "fail29"
if (OuterClass.NestedEnum.B.ordinal !== 1) return "fail30"
return "OK"
}
@@ -0,0 +1,99 @@
// DONT_TARGET_EXACT_BACKEND: JS
// ES_MODULES
// MODULE: export_interface
// FILE: not_exported.kt
interface ParentI {
val str: String
}
interface ExtendedI: I {
fun bar(): Int
}
open class NotExportedClass(override var value: Int) : ExtendedI {
override var variable: Int = value
override open fun foo(): String = "Not Exported"
override val str: String = "test 1"
override open fun bar(): Int = 42
}
// FILE: exportes.kt
@file:JsExport
interface I : ParentI {
val value: Int
var variable: Int
fun foo(): String
}
class ExportedClass(override val value: Int) : ExtendedI {
override var variable: Int = value
override fun foo(): String = "Exported"
override val str: String = "test 2"
override open fun bar(): Int = 43
}
class AnotherOne : NotExportedClass(42) {
override fun foo(): String = "Another One Exported"
}
fun generateNotExported(value: Int): NotExportedClass {
return NotExportedClass(value)
}
fun consume(i: I): String {
return "Value is ${i.value}, variable is ${i.variable} and result is '${i.foo()}'"
}
// FILE: main.mjs
// ENTRY_ES_MODULE
import * as pkg from "./exportFileWithInterface-export_interface_v5.mjs"
export function box() {
const { I, ExportedClass, AnotherOne, generateNotExported, consume } = pkg
if (I !== undefined) return "Fail: module should not export interface in runtime"
const exported = new ExportedClass(1)
const another = new AnotherOne()
const notExported = generateNotExported (3)
if (exported.foo() !== "Exported") return "Fail: foo function was not generated for ExportedClass"
if (another.foo() !== "Another One Exported") return "Fail: foo function was not generated for AnotherOne"
if (notExported.foo() !== "Not Exported") return "Fail: foo function was not generated for NotExportedClass"
if (exported.value !== 1) return "Fail: value getter was not generated for ExportedClass"
if (another.value !== 42) return "Fail: value getter was not generated for AnotherOne"
if (notExported.value !== 3) return "Fail: value getter was not generated for NotExportedClass"
if (exported.variable !== 1) return "Fail: variable getter was not generated for ExportedClass"
if (another.variable !== 42) return "Fail: variable getter was not generated for AnotherOne"
if (notExported.variable !== 3) return "Fail: variable getter was not generated for NotExportedClass"
exported.variable = 101
another.variable = 102
notExported.variable = 103
if (exported.variable !== 101) return "Fail: variable setter was not generated for ExportedClass"
if (another.variable !== 102) return "Fail: variable setter was not generated for AnotherOne"
if (notExported.variable !== 103) return "Fail: variable setter was not generated for NotExportedClass"
try {
notExported.value = 42
} catch(e) {}
if (notExported.value !== 3) return "Fail: value setter was generated for NotExportedClass, but it shouldn't"
if (consume(exported) !== "Value is 1, variable is 101 and result is 'Exported'") return "Fail: methods or fields of ExportedClass was mangled"
if (consume(another) !== "Value is 42, variable is 102 and result is 'Another One Exported'") return "Fail: methods or fields of AnotherOne was mangled"
if (consume(notExported) !== "Value is 3, variable is 103 and result is 'Not Exported'") return "Fail: methods or fields of NotExported was mangled"
if (notExported.str !== undefined) return "Fail: str should not exist inside NotExportedClass"
if (exported.str !== undefined) return "Fail: str should not exist inside ExportedClass"
if (notExported.bar !== undefined) return "Fail: bar should not exist inside NotExportedClass"
if (exported.bar !== undefined) return "Fail: bar should not exist inside ExportedClass"
return "OK"
}
@@ -0,0 +1,51 @@
// EXPECTED_REACHABLE_NODES: 1252
// DONT_TARGET_EXACT_BACKEND: JS
// ES_MODULES
// SKIP_DCE_DRIVEN
// MODULE: export_nested_class
// FILE: lib.kt
@file:JsExport
abstract class A {
abstract fun foo(k: String): String
}
class B {
class Foo : A() {
override fun foo(k: String): String {
return "O" + k
}
fun bar(k: String): String {
return foo(k)
}
}
}
object MyObject {
class A {
fun valueA() = "OK"
}
class B {
fun valueB() = "OK"
}
class C {
fun valueC() = "OK"
}
}
// FILE: test.mjs
// ENTRY_ES_MODULE
import { B, MyObject } from "./exportFileWithNestedClass-export_nested_class_v5.mjs"
export function box() {
if (new B.Foo().bar("K") != "OK") return "fail 1";
const myObject = MyObject.getInstance()
if (new myObject.A().valueA() != "OK") return "fail 2";
if (new myObject.B().valueB() != "OK") return "fail 3";
if (new myObject.C().valueC() != "OK") return "fail 4";
return "OK"
}
@@ -0,0 +1,70 @@
// EXPECTED_REACHABLE_NODES: 1265
// ES_MODULES
// DONT_TARGET_EXACT_BACKEND: JS
// SKIP_MINIFICATION
// SKIP_DCE_DRIVEN
// SKIP_NODE_JS
// See KT-43783
// MODULE: nestedObjectExport
// FILE: lib.kt
@file:JsExport
class Abc {
companion object AbcCompanion {
fun xyz(): String = "Companion object method OK"
val prop: String
get() = "Companion object property OK"
}
}
class Foo {
companion object {
fun xyz(): String = "Companion object method OK"
val prop: String
get() = "Companion object property OK"
}
}
sealed class MyEnum(val name: String) {
object A: MyEnum("A")
object B: MyEnum("B")
object C: MyEnum("C")
}
object MyObject {
object A {
fun valueA() = "OK"
}
object B {
fun valueB() = "OK"
}
object C {
fun valueC() = "OK"
}
}
// FILE: main.mjs
// ENTRY_ES_MODULE
import { Foo, Abc, MyEnum, MyObject } from "./exportFileWithNestedObject-nestedObjectExport_v5.mjs"
export function box() {
if (Abc.AbcCompanion.xyz() != 'Companion object method OK') return 'companion object function failure';
if (Abc.AbcCompanion.prop != 'Companion object property OK') return 'companion object property failure';
if (Foo.Companion.xyz() != 'Companion object method OK') return 'companion object function failure';
if (Foo.Companion.prop != 'Companion object property OK') return 'companion object property failure';
if (MyEnum.A.name != 'A') return 'MyEnum.A failure';
if (MyEnum.B.name != 'B') return 'MyEnum.B failure';
if (MyEnum.C.name != 'C') return 'MyEnum.C failure';
if (MyObject.getInstance().A.valueA() != "OK") return 'MyObject.A failure';
if (MyObject.getInstance().B.valueB() != "OK") return 'MyObject.B failure';
if (MyObject.getInstance().C.valueC() != "OK") return 'MyObject.C failure';
return 'OK';
}
@@ -0,0 +1,69 @@
// EXPECTED_REACHABLE_NODES: 1265
// ES_MODULES
// DONT_TARGET_EXACT_BACKEND: JS
// SKIP_MINIFICATION
// SKIP_NODE_JS
// SKIP_DCE_DRIVEN
// MODULE: exportProtectedMembers
// FILE: lib.kt
@file:JsExport
open class Foo protected constructor() {
protected fun bar(): String = "protected method"
private var _baz: String = "baz"
protected var baz: String
get() = _baz
set(value) {
_baz = value
}
protected val bazReadOnly: String
get() = _baz
protected val quux: String = "quux"
protected var quuz: String = "quuz"
protected class NestedClass {
val prop: String = "nested class property"
}
protected object NestedObject {
val prop: String = "nested object property"
}
protected companion object {
val prop: String = "companion object property"
}
}
// FILE: main.mjs
// ENTRY_ES_MODULE
import { Foo } from "./exportFileWithProtectedMembers-exportProtectedMembers_v5.mjs"
export function box() {
var foo = new Foo();
if (foo.bar() != 'protected method') return 'failed to call protected method';
if (foo.baz != 'baz') return 'failed to read `baz`';
if (foo.bazReadOnly != 'baz') return 'failed to read `bazReadOnly`';
foo.baz = 'beer';
if (foo.baz != 'beer') return 'failed to write protected var';
if (foo.bazReadOnly != 'beer') return 'unexpected value of `bazReadOnly` after modifying `baz`';
if (foo.quux != 'quux') return 'failed to read `quux`';
if (foo.quuz != 'quuz') return 'failed to read `quuz`';
foo.quuz = 'ale';
if (foo.quuz != 'ale') return 'failed to write `quuz`';
var nestedClass = new Foo.NestedClass()
if (nestedClass.prop != 'nested class property')
return 'failed to read protected class property'
if (Foo.NestedObject.prop != 'nested object property')
return 'failed to read protected nested object property'
if (Foo.Companion.prop != 'companion object property')
return 'failed to read protected companion object property'
return 'OK';
}
@@ -0,0 +1,58 @@
// DONT_TARGET_EXACT_BACKEND: JS
// EXPECTED_REACHABLE_NODES: 1252
// INFER_MAIN_MODULE
// ES_MODULES
// MODULE: exported_properites
// FILE: lib.kt
@file:JsExport
val regularValueProperty: String = "regularValueProperty"
val regularPropertyGetter: String
get() = "regularPropertyGetter"
var regularVariableProperty: String = "regularVariableProperty"
var regularVariableGetterWithSetter: String = "regularVariableGetterWithSetter"
get() = "$field by custom getter"
set(value) { field = "$value set by custom setter" }
// FILE: entry.mjs
// ENTRY_ES_MODULE
import {
regularValueProperty,
regularPropertyGetter,
regularVariableProperty,
regularVariableGetterWithSetter
} from "./exportFileWithTopLevelProperty-exported_properites_v5.mjs";
export function box() {
if (typeof regularValueProperty.get !== "function" || regularValueProperty.get() !== "regularValueProperty") {
return "Fail: wrongly exported getter for regular `val` property"
}
if (typeof regularValueProperty.set !== "undefined") {
return "Fail: wrongly exported setter for regular `val` property"
}
if (typeof regularPropertyGetter.get !== "function" || regularPropertyGetter.get() !== "regularPropertyGetter") {
return "Fail: wrongly exported getter for a `val` property with custom getter"
}
if (typeof regularPropertyGetter.set !== "undefined") {
return "Fail: wrongly exported setter for a `val` property with custom getter"
}
if (typeof regularVariableProperty.get !== "function" || regularVariableProperty.get() !== "regularVariableProperty") {
return "Fail: wrongly exported getter for regular `var` property"
}
if (typeof regularVariableProperty.set !== "function" || (regularVariableProperty.set("test1"), regularVariableProperty.get()) !== "test1") {
return "Fail: wrongly exported setter for regular `var` property"
}
if (typeof regularVariableGetterWithSetter.get !== "function" || regularVariableGetterWithSetter.get() !== "regularVariableGetterWithSetter by custom getter") {
return "Fail: wrongly exported getter for a `var` property with custom getter and setter"
}
if (typeof regularVariableGetterWithSetter.set !== "function" || (regularVariableGetterWithSetter.set("test1"), regularVariableGetterWithSetter.get()) !== "test1 set by custom setter by custom getter") {
return "Fail: wrongly exported setter for a `var` property with custom getter and setter"
}
return "OK"
}
@@ -0,0 +1,66 @@
// EXPECTED_REACHABLE_NODES: 1252
// IGNORE_BACKEND: JS
// ES_MODULES
// DONT_TARGET_EXACT_BACKEND: JS
// MODULE: export_inner_class
// FILE: lib.kt
@JsExport
class RegularParent(val value: String) {
inner class RegularInner(val message: String, val anotherValue: Int) {
fun getResult() = value + message
}
}
@JsExport
class ParentForSecondary {
inner class InnerWithSecondaryConstructor(val value: String) {
@JsName("innerSuccess")
constructor(): this("OK")
}
}
@JsExport
class ParentWithSecondary(val value: String) {
@JsName("createO")
constructor(): this("O")
inner class InnerWithSecondaryConstructor(val anotherValue: String) {
@JsName("createK")
constructor(): this("K")
fun getResult() = value + anotherValue
}
}
// FILE: main.mjs
// ENTRY_ES_MODULE
import { RegularParent, ParentForSecondary, ParentWithSecondary } from "./exportInnerClass-export_inner_class_v5.mjs"
export function box() {
var regularParent = new RegularParent("O")
var regularInner = new regularParent.RegularInner("K", 42)
if (regularInner.anotherValue !== 42) return "Fail: second parameter of the RegularInner primary constructor was ignored"
if (regularInner.getResult() !== "OK") return "Fail: something is going wrong with the outer this capturing logic"
var parentForSecondary = new ParentForSecondary()
var innerWithSecondary = new parentForSecondary.InnerWithSecondaryConstructor("OK")
if (innerWithSecondary.value !== "OK") return "Fail: something is going wrong with primary constructor when a secondary one exists"
var fromSecondary = parentForSecondary.InnerWithSecondaryConstructor.innerSuccess()
if (fromSecondary.value !== "OK") return "Fail: something is going wrong with secondary constructor inside the inner class"
var parentFromSecondary = ParentWithSecondary.createO()
var innerFromSecondary = parentFromSecondary.InnerWithSecondaryConstructor.createK()
if (innerFromSecondary.getResult() !== "OK") return "Fail: there is a problem when both parent and inner class have secondary constructors"
return "OK"
}
@@ -0,0 +1,105 @@
// IGNORE_BACKEND: JS
// RUN_PLAIN_BOX_FUNCTION
// DONT_TARGET_EXACT_BACKEND: JS
// ES_MODULES
// MODULE: export_interface
// FILE: lib.kt
interface ParentI {
val str: String
}
@JsExport
interface I : ParentI {
val value: Int
var variable: Int
fun foo(): String
}
interface ExtendedI: I {
fun bar(): Int
}
open class NotExportedClass(override var value: Int) : ExtendedI {
override var variable: Int = value
override open fun foo(): String = "Not Exported"
override val str: String = "test 1"
override open fun bar(): Int = 42
}
@JsExport
class ExportedClass(override val value: Int) : ExtendedI {
override var variable: Int = value
override fun foo(): String = "Exported"
override val str: String = "test 2"
override open fun bar(): Int = 43
}
@JsExport
class AnotherOne : NotExportedClass(42) {
override fun foo(): String = "Another One Exported"
}
@JsExport
fun generateNotExported(value: Int): NotExportedClass {
return NotExportedClass(value)
}
@JsExport
fun consume(i: I): String {
return "Value is ${i.value}, variable is ${i.variable} and result is '${i.foo()}'"
}
// FILE: main.mjs
// ENTRY_ES_MODULE
import * as pkg from "./exportInterface-export_interface_v5.mjs"
export function box() {
const { I, ExportedClass, AnotherOne, generateNotExported, consume } = pkg
if (I !== undefined) return "Fail: module should not export interface in runtime"
const exported = new ExportedClass(1)
const another = new AnotherOne()
const notExported = generateNotExported (3)
if (exported.foo() !== "Exported") return "Fail: foo function was not generated for ExportedClass"
if (another.foo() !== "Another One Exported") return "Fail: foo function was not generated for AnotherOne"
if (notExported.foo() !== "Not Exported") return "Fail: foo function was not generated for NotExportedClass"
if (exported.value !== 1) return "Fail: value getter was not generated for ExportedClass"
if (another.value !== 42) return "Fail: value getter was not generated for AnotherOne"
if (notExported.value !== 3) return "Fail: value getter was not generated for NotExportedClass"
if (exported.variable !== 1) return "Fail: variable getter was not generated for ExportedClass"
if (another.variable !== 42) return "Fail: variable getter was not generated for AnotherOne"
if (notExported.variable !== 3) return "Fail: variable getter was not generated for NotExportedClass"
exported.variable = 101
another.variable = 102
notExported.variable = 103
if (exported.variable !== 101) return "Fail: variable setter was not generated for ExportedClass"
if (another.variable !== 102) return "Fail: variable setter was not generated for AnotherOne"
if (notExported.variable !== 103) return "Fail: variable setter was not generated for NotExportedClass"
try {
notExported.value = 42
} catch(e) {}
if (notExported.value !== 3) return "Fail: value setter was generated for NotExportedClass, but it shouldn't"
if (consume(exported) !== "Value is 1, variable is 101 and result is 'Exported'") return "Fail: methods or fields of ExportedClass was mangled"
if (consume(another) !== "Value is 42, variable is 102 and result is 'Another One Exported'") return "Fail: methods or fields of AnotherOne was mangled"
if (consume(notExported) !== "Value is 3, variable is 103 and result is 'Not Exported'") return "Fail: methods or fields of NotExported was mangled"
if (notExported.str !== undefined) return "Fail: str should not exist inside NotExportedClass"
if (exported.str !== undefined) return "Fail: str should not exist inside ExportedClass"
if (notExported.bar !== undefined) return "Fail: bar should not exist inside NotExportedClass"
if (exported.bar !== undefined) return "Fail: bar should not exist inside ExportedClass"
return "OK"
}
@@ -0,0 +1,52 @@
// EXPECTED_REACHABLE_NODES: 1252
// IGNORE_BACKEND: JS
// ES_MODULES
// DONT_TARGET_EXACT_BACKEND: JS
// SKIP_DCE_DRIVEN
// MODULE: export_nested_class
// FILE: lib.kt
abstract class A {
abstract fun foo(k: String): String
}
@JsExport
class B {
class Foo : A() {
override fun foo(k: String): String {
return "O" + k
}
fun bar(k: String): String {
return foo(k)
}
}
}
@JsExport
object MyObject {
class A {
fun valueA() = "OK"
}
class B {
fun valueB() = "OK"
}
class C {
fun valueC() = "OK"
}
}
// FILE: main.mjs
// ENTRY_ES_MODULE
import { B, MyObject } from "./exportNestedClass-export_nested_class_v5.mjs"
export function box() {
if (new B.Foo().bar("K") != "OK") return "fail 1";
const myObject = MyObject.getInstance()
if (new myObject.A().valueA() != "OK") return "fail 2";
if (new myObject.B().valueB() != "OK") return "fail 3";
if (new myObject.C().valueC() != "OK") return "fail 4";
return "OK"
}
@@ -0,0 +1,73 @@
// EXPECTED_REACHABLE_NODES: 1265
// ES_MODULES
// DONT_TARGET_EXACT_BACKEND: JS
// 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")
}
@JsExport
object MyObject {
object A {
fun valueA() = "OK"
}
object B {
fun valueB() = "OK"
}
object C {
fun valueC() = "OK"
}
}
// FILE: main.mjs
// ENTRY_ES_MODULE
import { Abc, Foo, MyEnum, MyObject } from "./exportNestedObject-nestedObjectExport_v5.mjs"
export function box() {
if (Abc.AbcCompanion.xyz() != 'Companion object method OK') return 'companion object function failure';
if (Abc.AbcCompanion.prop != 'Companion object property OK') return 'companion object property failure';
if (Foo.Companion.xyz() != 'Companion object method OK') return 'companion object function failure';
if (Foo.Companion.prop != 'Companion object property OK') return 'companion object property failure';
if (MyEnum.A.name != 'A') return 'MyEnum.A failure';
if (MyEnum.B.name != 'B') return 'MyEnum.B failure';
if (MyEnum.C.name != 'C') return 'MyEnum.C failure';
if (MyObject.getInstance().A.valueA() != "OK") return 'MyObject.A failure';
if (MyObject.getInstance().B.valueB() != "OK") return 'MyObject.B failure';
if (MyObject.getInstance().C.valueC() != "OK") return 'MyObject.C failure';
return 'OK';
}
@@ -0,0 +1,69 @@
// EXPECTED_REACHABLE_NODES: 1265
// ES_MODULES
// DONT_TARGET_EXACT_BACKEND: JS
// SKIP_MINIFICATION
// SKIP_NODE_JS
// SKIP_DCE_DRIVEN
// MODULE: exportProtectedMembers
// FILE: lib.kt
@JsExport
open class Foo protected constructor() {
protected fun bar(): String = "protected method"
private var _baz: String = "baz"
protected var baz: String
get() = _baz
set(value) {
_baz = value
}
protected val bazReadOnly: String
get() = _baz
protected val quux: String = "quux"
protected var quuz: String = "quuz"
protected class NestedClass {
val prop: String = "nested class property"
}
protected object NestedObject {
val prop: String = "nested object property"
}
protected companion object {
val prop: String = "companion object property"
}
}
// FILE: main.mjs
// ENTRY_ES_MODULE
import { Foo } from "./exportProtectedMembers-exportProtectedMembers_v5.mjs"
export function box() {
var foo = new Foo();
if (foo.bar() != 'protected method') return 'failed to call protected method';
if (foo.baz != 'baz') return 'failed to read `baz`';
if (foo.bazReadOnly != 'baz') return 'failed to read `bazReadOnly`';
foo.baz = 'beer';
if (foo.baz != 'beer') return 'failed to write protected var';
if (foo.bazReadOnly != 'beer') return 'unexpected value of `bazReadOnly` after modifying `baz`';
if (foo.quux != 'quux') return 'failed to read `quux`';
if (foo.quuz != 'quuz') return 'failed to read `quuz`';
foo.quuz = 'ale';
if (foo.quuz != 'ale') return 'failed to write `quuz`';
var nestedClass = new Foo.NestedClass()
if (nestedClass.prop != 'nested class property')
return 'failed to read protected class property'
if (Foo.NestedObject.prop != 'nested object property')
return 'failed to read protected nested object property'
if (Foo.Companion.prop != 'companion object property')
return 'failed to read protected companion object property'
return 'OK';
}
@@ -0,0 +1,60 @@
// DONT_TARGET_EXACT_BACKEND: JS
// EXPECTED_REACHABLE_NODES: 1252
// ES_MODULES
// MODULE: exported_properites
// FILE: lib.kt
@JsExport
val regularValueProperty: String = "regularValueProperty"
@JsExport
val regularPropertyGetter: String
get() = "regularPropertyGetter"
@JsExport
var regularVariableProperty: String = "regularVariableProperty"
@JsExport
var regularVariableGetterWithSetter: String = "regularVariableGetterWithSetter"
get() = "$field by custom getter"
set(value) { field = "$value set by custom setter" }
// FILE: entry.mjs
// ENTRY_ES_MODULE
import {
regularValueProperty,
regularPropertyGetter,
regularVariableProperty,
regularVariableGetterWithSetter
} from "./exportTopLevelProperty-exported_properites_v5.mjs";
export function box() {
if (typeof regularValueProperty.get !== "function" || regularValueProperty.get() !== "regularValueProperty") {
return "Fail: wrongly exported getter for regular `val` property"
}
if (typeof regularValueProperty.set !== "undefined") {
return "Fail: wrongly exported setter for regular `val` property"
}
if (typeof regularPropertyGetter.get !== "function" || regularPropertyGetter.get() !== "regularPropertyGetter") {
return "Fail: wrongly exported getter for a `val` property with custom getter"
}
if (typeof regularPropertyGetter.set !== "undefined") {
return "Fail: wrongly exported setter for a `val` property with custom getter"
}
if (typeof regularVariableProperty.get !== "function" || regularVariableProperty.get() !== "regularVariableProperty") {
return "Fail: wrongly exported getter for regular `var` property"
}
if (typeof regularVariableProperty.set !== "function" || (regularVariableProperty.set("test1"), regularVariableProperty.get()) !== "test1") {
return "Fail: wrongly exported setter for regular `var` property"
}
if (typeof regularVariableGetterWithSetter.get !== "function" || regularVariableGetterWithSetter.get() !== "regularVariableGetterWithSetter by custom getter") {
return "Fail: wrongly exported getter for a `var` property with custom getter and setter"
}
if (typeof regularVariableGetterWithSetter.set !== "function" || (regularVariableGetterWithSetter.set("test1"), regularVariableGetterWithSetter.get()) !== "test1 set by custom setter by custom getter") {
return "Fail: wrongly exported setter for a `var` property with custom getter and setter"
}
return "OK"
}
@@ -1,10 +1,9 @@
// DONT_TARGET_EXACT_BACKEND: JS
// SKIP_MINIFICATION
// INFER_MAIN_MODULE
// SKIP_NODE_JS
// ES_MODULES
// MODULE: non_identifier_module_name
// MODULE: lib
// FILE: lib.kt
@JsName("foo")
@JsExport
@@ -12,5 +11,8 @@ public fun foo(k: String): String = "O$k"
// FILE: entry.mjs
// ENTRY_ES_MODULE
import { foo } from "./non_identifier_module_name/index.js";
console.assert(foo("K") == "OK");
import { foo } from "./nonIndetifierModuleName-lib_v5.mjs";
export function box() {
return foo("K")
}
@@ -0,0 +1,21 @@
// EXPECTED_REACHABLE_NODES: 1270
// DONT_TARGET_EXACT_BACKEND: JS
// ES_MODULES
// SKIP_MINIFICATION
// SKIP_NODE_JS
// MODULE: lib
// FILE: lib.kt
@file:JsExport
@JsName("foo")
public fun foo(k: String): String = "O$k"
// FILE: enty.mjs
// ENTRY_ES_MODULE
import { foo } from "./nonIndetifierModuleNameInExportedFile-lib_v5.mjs";
export function box() {
return foo("K")
}
@@ -1,6 +1,5 @@
// DONT_TARGET_EXACT_BACKEND: JS
// EXPECTED_REACHABLE_NODES: 1252
// INFER_MAIN_MODULE
// ES_MODULES
// MODULE: overriden_chain_non_export_intermediate
@@ -28,12 +27,19 @@ class C : B() {
// FILE: entry.mjs
// ENTRY_ES_MODULE
import { C } from "./overriden_chain_non_export_intermediate/index.js";
import { C } from "./overriddenChainNonExportIntermediate-overriden_chain_non_export_intermediate_v5.mjs";
function test(c) {
if (c.foo() === "foo" && c.bar() === "bar" && c.bay() == "bay") return "OK"
export function box() {
const c = new C()
return "fail"
}
const foo = c.foo()
if (foo !== "foo") return `Fail: expect c.foo() to return 'foo' but it returns ${foo}`
console.assert(test(new C()) == "OK");
const bar = c.bar()
if (bar !== "bar") return `Fail: expect c.bar() to return 'bar' but it returns ${bar}`
const bay = c.bay()
if (bay !== "bay") return `Fail: expect c.bay() to return 'bay' but it returns ${bay}`
return "OK"
}
@@ -0,0 +1,39 @@
// EXPECTED_REACHABLE_NODES: 1252
// DONT_TARGET_EXACT_BACKEND: JS
// ES_MODULES
// MODULE: overriden_chain_non_export_intermediate
// FILE: not_exported.kt
abstract class B : A() {
abstract fun baz(): String
override fun foo(): String = "foo"
}
// FILE: exported.kt
@file:JsExport
abstract class A {
abstract fun foo(): String
abstract fun bar(): String
}
class C : B() {
override fun bar(): String = "bar"
override fun baz(): String = "baz"
fun bay(): String = "bay"
}
// FILE: main.mjs
// ENTRY_ES_MODULE
import { C } from "./overriddenChainNonExportIntermediateInExportedFile-overriden_chain_non_export_intermediate_v5.mjs"
export function box() {
var c = new C();
if (c.foo() === "foo" && c.bar() === "bar" && c.bay() == "bay") return "OK"
return "fail"
}
@@ -1,9 +1,8 @@
// EXPECTED_REACHABLE_NODES: 1252
// INFER_MAIN_MODULE
// DONT_TARGET_EXACT_BACKEND: JS
// ES_MODULES
// MODULE: overriden_external_method_with_same_name_method
// MODULE: lib
// FILE: lib.kt
external abstract class Foo {
abstract fun o(): String
@@ -32,10 +31,9 @@ Foo.prototype.k = function() {
// FILE: entry.mjs
// ENTRY_ES_MODULE
import { Baz } from "./overriden_external_method_with_same_name_method/index.js";
import { Baz } from "./overriddenExternalMethodWithSameNameMethod-lib_v5.mjs";
function test(foo) {
export function box() {
const foo = new Baz()
return foo.o() + foo.k()
}
console.assert(test(new Baz()) == "OK");
}
@@ -1,12 +1,8 @@
// EXPECTED_REACHABLE_NODES: 1252
// IGNORE_BACKEND: JS
// INFER_MAIN_MODULE
// DONT_TARGET_EXACT_BACKEND: JS
// ES_MODULES
// TODO: Fix tests on Windows
// DONT_TARGET_EXACT_BACKEND: JS_IR
// MODULE: overriden_external_method_with_same_stable_name_method
// MODULE: lib
// FILE: lib.kt
external abstract class Foo {
abstract fun o(): String
@@ -36,12 +32,11 @@ Foo.prototype.k = function() {
// FILE: entry.mjs
// ENTRY_ES_MODULE
import { Baz } from "./overriden-external-method-with-same-stable-name-method/index.js";
import { Baz } from "./overriddenExternalMethodWithSameStableNameMethod-lib_v5.mjs";
function test(foo) {
export function box() {
const foo = new Baz()
const oStable = foo.oStable("OK")
if (oStable !== "OK") return "false: " + oStable
return foo.o() + foo.k()
}
console.assert(test(new Baz()) == "OK");
}
@@ -0,0 +1,49 @@
// EXPECTED_REACHABLE_NODES: 1252
// DONT_TARGET_EXACT_BACKEND: JS
// ES_MODULES
// MODULE: lib
// FILE: not_exported.kt
external abstract class Foo {
abstract fun o(): String
}
abstract class Bar : Foo() {
@JsName("oStable")
abstract fun String.o(): String
override fun o(): String {
return "O".o()
}
}
// FILE: exported.kt
@file:JsExport
class Baz : Bar() {
override fun String.o(): String {
return this
}
}
// FILE: foo.js
function Foo() {}
Foo.prototype.k = function() {
return "K"
}
// FILE: main.mjs
// ENTRY_ES_MODULE
import { Baz } from "./overriddenExternalMethodWithSameStableNameMethodInExportedFile-lib_v5.mjs"
export function box() {
return test(new Baz());
}
function test(foo) {
const oStable = foo.oStable("OK")
if (oStable !== "OK") return "false: " + oStable
return foo.o() + foo.k()
}
@@ -1,7 +1,6 @@
// IGNORE_BACKEND: JS
// DONT_TARGET_EXACT_BACKEND: JS
// EXPECTED_REACHABLE_NODES: 1270
// SKIP_MINIFICATION
// INFER_MAIN_MODULE
// ES_MODULES
// MODULE: if
@@ -12,6 +11,8 @@ public fun foo(k: String): String = "O$k"
// FILE: entry.mjs
// ENTRY_ES_MODULE
import { foo } from "./if/index.js";
import { foo } from "./reservedModuleName-if_v5.mjs";
console.assert(foo("K") == "OK");
export function box() {
return foo("K")
}
@@ -0,0 +1,19 @@
// DONT_TARGET_EXACT_BACKEND: JS
// EXPECTED_REACHABLE_NODES: 1270
// SKIP_MINIFICATION
// ES_MODULES
// MODULE: if
// FILE: lib.kt
@file:JsExport
@JsName("foo")
public fun foo(k: String): String = "O$k"
// FILE: entry.mjs
// ENTRY_ES_MODULE
import { foo } from "./reservedModuleNameInExportedFile-if_v5.mjs";
export function box() {
return foo("K")
}
@@ -0,0 +1,28 @@
// DONT_TARGET_EXACT_BACKEND: JS
// EXPECTED_REACHABLE_NODES: 1270
// SKIP_MINIFICATION
// ES_MODULES
// MODULE: vararg
// FILE: lib.kt
@JsExport
fun uintVararg(vararg uints: UInt): String {
for (u in uints) {
if (u == 0u) return "Failed"
}
return "OK"
}
@JsExport
fun uint(a: Int): UInt {
return a.toUInt()
}
// FILE: main.mjs
// ENTRY_ES_MODULE
import { uint, uintVararg } from "./vararg-vararg_v5.mjs"
export function box() {
return uintVararg([uint(1), uint(2), uint(3)])
}
@@ -30,6 +30,8 @@ fun testOk(ok: Any): String {
// FILE: entry.mjs
// ENTRY_ES_MODULE
import { convolutedOk, testOk } from "./main/index.js";
import { convolutedOk, testOk } from "./inlinedObjectLiteralIsCheck_v5.mjs";
console.assert(testOk(convolutedOk()) == "OK");
export function box() {
return testOk(convolutedOk())
}
@@ -48,8 +48,5 @@ fun box(): String {
return "Fail6: ${res.component2}"
}
return "OK"
}
@@ -1,4 +1,4 @@
import { Point } from "./main/index.js";
import { Point } from "./dataClass_v5.mjs";
export default function() {
var p = new Point(3, 7);
@@ -1,4 +1,4 @@
import * as api from "./main/index.js";
import * as api from "./exportedDefaultStub_v5.mjs";
export default function() {
var ping = api.ping;
@@ -1,4 +1,4 @@
import { A, B } from "./main/index.js";
import { A, B } from "./jsExportInClass_v5.mjs";
export default function() {
return {
@@ -1,4 +1,4 @@
import { ping, Something } from "./main/index.js"
import { ping, Something } from "./recursiveExport_v5.mjs"
export default function() {
return {
@@ -24,7 +24,7 @@ open class B {
// FILE: entry.mjs
// ENTRY_ES_MODULE
import { A, B } from "./main/index.js";
import { A, B } from "./inheritanceInNativeClass_v5.mjs";
function createA() {
function ADerived() {
@@ -46,7 +46,7 @@ function createB() {
return new BDerived();
}
function box() {
export function box() {
let a = createA();
if (a.bar(0) != 124) return "fail1";
@@ -54,6 +54,4 @@ function box() {
if (b.bar(0) != 42) return "fail2";
return "OK";
}
console.assert(box() == "OK");
}