[K/JS] test: add @file:JsExport tests for each @JsExport test + auto-generate TypeScript export tests.
This commit is contained in:
+28
@@ -0,0 +1,28 @@
|
||||
// TARGET_BACKEND: JS_IR
|
||||
// RUN_PLAIN_BOX_FUNCTION
|
||||
// INFER_MAIN_MODULE
|
||||
|
||||
// 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: test.js
|
||||
function box() {
|
||||
var a = new this["bridge_saving_after_export"].A()
|
||||
var aFoo = a.foo("ok")
|
||||
if (aFoo != "ok") return "fail 1"
|
||||
|
||||
var b = new this["bridge_saving_after_export"].B()
|
||||
var bFoo = b.foo("ok")
|
||||
if (bFoo != "ok") return "fail 2"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// IGNORE_FIR
|
||||
// KT-49225
|
||||
// RUN_PLAIN_BOX_FUNCTION
|
||||
// IGNORE_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: main.js
|
||||
function box() {
|
||||
return new kotlin_lib.Bar().koo;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// FILE: lib.kt
|
||||
@file:JsExport
|
||||
|
||||
class Foo(internal val constructorParameter: String) {
|
||||
internal val nonDefaultAccessor: String
|
||||
get() = "hello"
|
||||
|
||||
internal val defaultAccessor: String = constructorParameter + "!"
|
||||
}
|
||||
|
||||
enum class Bar(internal val constructorParameter: String) {
|
||||
A("a");
|
||||
|
||||
internal val nonDefaultAccessor: String
|
||||
get() = "hello"
|
||||
|
||||
internal val defaultAccessor: String = constructorParameter + "!"
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
fun box(): String {
|
||||
val foo = Foo("foo")
|
||||
if (foo.constructorParameter != "foo") return "fail1"
|
||||
if (foo.nonDefaultAccessor != "hello") return "fail2"
|
||||
if (foo.defaultAccessor != "foo!") return "fail3"
|
||||
|
||||
if (Bar.A.constructorParameter != "a") return "fail4"
|
||||
if (Bar.A.nonDefaultAccessor != "hello") return "fail5"
|
||||
if (Bar.A.defaultAccessor != "a!") return "fail6"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
// IGNORE_BACKEND: JS
|
||||
// RUN_PLAIN_BOX_FUNCTION
|
||||
// INFER_MAIN_MODULE
|
||||
|
||||
// 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: test.js
|
||||
function box() {
|
||||
if (this["export_enum_class"].Foo.A !== this["export_enum_class"].Foo.A) return "fail1"
|
||||
if (this["export_enum_class"].Foo.B !== this["export_enum_class"].Foo.B) return "fail2"
|
||||
|
||||
if (this["export_enum_class"].Foo.Companion.baz !== "baz") return "fail3"
|
||||
|
||||
if (this["export_enum_class"].Foo.A.foo !== 0) return "fail4"
|
||||
if (this["export_enum_class"].Foo.B.foo !== 1) return "fail5"
|
||||
|
||||
if (this["export_enum_class"].Foo.A.bar("A") !== "A") return "fail6"
|
||||
if (this["export_enum_class"].Foo.B.bar("B") !== "B") return "fail7"
|
||||
|
||||
if (this["export_enum_class"].Foo.A.bay() !== "A") return "fail8"
|
||||
if (this["export_enum_class"].Foo.B.bay() !== "B") return "fail9"
|
||||
|
||||
if (this["export_enum_class"].Foo.A.constructorParameter !== "aConstructorParameter") return "fail10"
|
||||
if (this["export_enum_class"].Foo.B.constructorParameter !== "bConstructorParameter") return "fail11"
|
||||
|
||||
if (this["export_enum_class"].Bar.A.foo !== 0) return "fail12"
|
||||
if (this["export_enum_class"].Bar.B.foo !== 1) return "fail13"
|
||||
|
||||
if (this["export_enum_class"].Bar.A.bar("A") !== "A") return "fail14"
|
||||
if (this["export_enum_class"].Bar.B.bar("B") !== "B") return "fail15"
|
||||
|
||||
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('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 "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 "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 "fail23"
|
||||
if (this["export_enum_class"].Foo.B.name !== "B") return "fail24"
|
||||
|
||||
if (this["export_enum_class"].Foo.A.ordinal !== 0) return "fail25"
|
||||
if (this["export_enum_class"].Foo.B.ordinal !== 1) return "fail26"
|
||||
|
||||
if (this["export_enum_class"].OuterClass.NestedEnum.A.name !== "A") return "fail27"
|
||||
if (this["export_enum_class"].OuterClass.NestedEnum.B.name !== "B") return "fail28"
|
||||
|
||||
if (this["export_enum_class"].OuterClass.NestedEnum.A.ordinal !== 0) return "fail29"
|
||||
if (this["export_enum_class"].OuterClass.NestedEnum.B.ordinal !== 1) return "fail30"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
// IGNORE_BACKEND: JS
|
||||
// RUN_PLAIN_BOX_FUNCTION
|
||||
// INFER_MAIN_MODULE
|
||||
|
||||
// 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: test.js
|
||||
function box() {
|
||||
const { I, ExportedClass, AnotherOne, generateNotExported, consume } = this["export_interface"]
|
||||
|
||||
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"
|
||||
|
||||
notExported.value = 42
|
||||
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,47 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1252
|
||||
// IGNORE_BACKEND: JS
|
||||
// RUN_PLAIN_BOX_FUNCTION
|
||||
// INFER_MAIN_MODULE
|
||||
// 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.js
|
||||
function box() {
|
||||
if (new this["export_nested_class"].B.Foo().bar("K") != "OK") return "fail 1";
|
||||
if (new this["export_nested_class"].MyObject.A().valueA() != "OK") return "fail 2";
|
||||
if (new this["export_nested_class"].MyObject.B().valueB() != "OK") return "fail 3";
|
||||
if (new this["export_nested_class"].MyObject.C().valueC() != "OK") return "fail 4";
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
// 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
|
||||
@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: 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';
|
||||
|
||||
if (nestedObjectExport.MyObject.A.valueA() != "OK") return 'MyObject.A failure';
|
||||
if (nestedObjectExport.MyObject.B.valueB() != "OK") return 'MyObject.B failure';
|
||||
if (nestedObjectExport.MyObject.C.valueC() != "OK") return 'MyObject.C failure';
|
||||
|
||||
return 'OK';
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1265
|
||||
// RUN_PLAIN_BOX_FUNCTION
|
||||
// INFER_MAIN_MODULE
|
||||
// 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: test.js
|
||||
function box() {
|
||||
foo = new exportProtectedMembers.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`';
|
||||
|
||||
nestedClass = new exportProtectedMembers.Foo.NestedClass()
|
||||
if (nestedClass.prop != 'nested class property')
|
||||
return 'failed to read protected class property'
|
||||
if (exportProtectedMembers.Foo.NestedObject.prop != 'nested object property')
|
||||
return 'failed to read protected nested object property'
|
||||
if (exportProtectedMembers.Foo.Companion.prop != 'companion object property')
|
||||
return 'failed to read protected companion object property'
|
||||
|
||||
return 'OK';
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1270
|
||||
// SKIP_MINIFICATION
|
||||
// RUN_PLAIN_BOX_FUNCTION
|
||||
// INFER_MAIN_MODULE
|
||||
// SKIP_NODE_JS
|
||||
|
||||
// MODULE: non_identifier_module_name
|
||||
// FILE: lib.kt
|
||||
@file:JsExport
|
||||
|
||||
@JsName("foo")
|
||||
public fun foo(k: String): String = "O$k"
|
||||
|
||||
// FILE: test.js
|
||||
function box() {
|
||||
return this["non_identifier_module_name"].foo("K");
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1252
|
||||
// IGNORE_BACKEND: JS
|
||||
// RUN_PLAIN_BOX_FUNCTION
|
||||
// INFER_MAIN_MODULE
|
||||
|
||||
// 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: test.js
|
||||
|
||||
function box() {
|
||||
return test(new this["overriden_chain_non_export_intermediate"].C());
|
||||
}
|
||||
|
||||
function test(c) {
|
||||
if (c.foo() === "foo" && c.bar() === "bar" && c.bay() == "bay") return "OK"
|
||||
|
||||
return "fail"
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1252
|
||||
// IGNORE_BACKEND: JS
|
||||
// RUN_PLAIN_BOX_FUNCTION
|
||||
// INFER_MAIN_MODULE
|
||||
|
||||
// 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: test.js
|
||||
function Foo() {}
|
||||
Foo.prototype.k = function() {
|
||||
return "K"
|
||||
}
|
||||
|
||||
function box() {
|
||||
return test(new this["lib"].Baz());
|
||||
}
|
||||
|
||||
function test(foo) {
|
||||
const oStable = foo.oStable("OK")
|
||||
if (oStable !== "OK") return "false: " + oStable
|
||||
return foo.o() + foo.k()
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// IGNORE_BACKEND: JS
|
||||
// EXPECTED_REACHABLE_NODES: 1270
|
||||
// SKIP_MINIFICATION
|
||||
// RUN_PLAIN_BOX_FUNCTION
|
||||
// INFER_MAIN_MODULE
|
||||
|
||||
// MODULE: if
|
||||
// FILE: lib.kt
|
||||
@file:JsExport
|
||||
|
||||
@JsName("foo")
|
||||
public fun foo(k: String): String = "O$k"
|
||||
|
||||
// FILE: test.js
|
||||
function box() {
|
||||
return this["if"].foo("K");
|
||||
}
|
||||
Reference in New Issue
Block a user