[K/JS] Support companion objects in external and exported declarations

This commit is contained in:
Artem Kobzar
2024-02-27 16:30:13 +00:00
committed by Space Team
parent 5cda3fba12
commit 3429cbd321
51 changed files with 551 additions and 56 deletions
@@ -0,0 +1,24 @@
// SKIP_MINIFICATION
// ES_MODULES
// FILE: api.kt
package api
@JsExport
interface A {
companion object {
fun ok() = "OK"
}
}
// FILE: main.kt
external interface JsResult {
val res: String
}
@JsModule("./interfaceWithCompanion.mjs")
external fun jsBox(): JsResult
fun box(): String {
return jsBox().res
}
@@ -0,0 +1,7 @@
import * as api from "./interfaceWithCompanion_v5.mjs";
export default function() {
return {
"res": api.A.getInstance().ok()
};
};
@@ -0,0 +1,20 @@
// TARGET_BACKEND: JS_IR
// TARGET_BACKEND: JS_IR_ES6
// EXPECTED_REACHABLE_NODES: 1238
// ES_MODULES
// FILE: bar.kt
@file:JsModule("./interfacesWithCompanion.mjs")
package bar
external interface Bar {
companion object {
fun ok(): String
}
}
// FILE: test.kt
import bar.Bar
fun box(): String {
return Bar.ok()
}
@@ -0,0 +1,3 @@
export const Bar = {
ok() { return "OK" }
};
@@ -0,0 +1,12 @@
$kotlin_test_internal$.beginModule();
module.exports = function() {
var { A } = require("main").api
return {
"res": A.ok()
};
};
$kotlin_test_internal$.endModule("lib");
@@ -0,0 +1,24 @@
// MODULE_KIND: COMMON_JS
// SKIP_MINIFICATION
// FILE: api.kt
package api
@JsExport
interface A {
companion object {
fun ok() = "OK"
}
}
// FILE: main.kt
external interface JsResult {
val res: String
}
@JsModule("lib")
external fun jsBox(): JsResult
fun box(): String {
return jsBox().res
}
@@ -0,0 +1,7 @@
define("bar", [], function() {
return {
Bar: {
ok() { return "OK" }
}
};
});
@@ -0,0 +1,23 @@
// TARGET_BACKEND: JS_IR
// TARGET_BACKEND: JS_IR_ES6
// EXPECTED_REACHABLE_NODES: 1238
// MODULE_KIND: AMD
// FILE: bar.kt
@file:JsModule("bar")
package bar
external interface Bar {
companion object {
fun ok(): String
}
}
// FILE: test.kt
import bar.Bar
inline fun Bar.Companion.test() = "CHECK"
fun box(): String {
Bar.test()
return Bar.ok()
}
@@ -0,0 +1,31 @@
// TARGET_BACKEND: JS_IR
// TARGET_BACKEND: JS_IR_ES6
// EXPECTED_REACHABLE_NODES: 1238
// FILE: bar.kt
@file:JsQualifier("bar")
package bar
external interface Bar {
companion object {
fun ok(): String
}
}
// FILE: test.kt
import bar.Bar
fun box(): String {
return Bar.ok()
}
// FILE: test.js
var bar = function() {
var Bar = {
ok() {
return "OK"
}
};
return {
Bar: Bar
}
}();
@@ -30,6 +30,15 @@ declare namespace JS_TESTS {
readonly __doNotUseOrImplementIt: foo.TestInterfaceImpl["__doNotUseOrImplementIt"] & foo.AnotherExportedInterface["__doNotUseOrImplementIt"];
}
function processInterface(test: foo.TestInterface): string;
interface WithTheCompanion {
readonly interfaceField: string;
readonly __doNotUseOrImplementIt: {
readonly "foo.WithTheCompanion": unique symbol;
};
}
const WithTheCompanion: {
companionFunction(): string;
};
function processOptionalInterface(a: foo.OptionalFieldsInterface): string;
interface InterfaceWithCompanion {
readonly __doNotUseOrImplementIt: {
@@ -37,4 +46,4 @@ declare namespace JS_TESTS {
};
}
}
}
}
@@ -43,6 +43,15 @@ external interface OptionalFieldsInterface {
}
interface WithTheCompanion {
val interfaceField: String
companion object {
fun companionFunction(): String = "FUNCTION"
}
}
fun processOptionalInterface(a: OptionalFieldsInterface): String {
return "${a.required}${a.notRequired ?: "unknown"}"
}
@@ -52,6 +61,7 @@ fun processOptionalInterface(a: OptionalFieldsInterface): String {
interface InterfaceWithCompanion {
// Emulate added by plugin companion like kotlinx.serialization does
@Suppress("WRONG_EXPORTED_DECLARATION")
@JsExport.Ignore
companion object {
fun foo() = "String"
}
@@ -2,6 +2,7 @@ import TestInterfaceImpl = JS_TESTS.foo.TestInterfaceImpl;
import ChildTestInterfaceImpl = JS_TESTS.foo.ChildTestInterfaceImpl;
import processInterface = JS_TESTS.foo.processInterface;
import processOptionalInterface = JS_TESTS.foo.processOptionalInterface;
import WithTheCompanion = JS_TESTS.foo.WithTheCompanion;
function assert(condition: boolean) {
if (!condition) {
@@ -20,5 +21,7 @@ function box(): string {
assert(processOptionalInterface({ required: 4, notRequired: null }) == "4unknown")
assert(processOptionalInterface({ required: 4, notRequired: 5 }) == "45")
assert(WithTheCompanion.companionFunction() == "FUNCTION")
return "OK";
}
@@ -30,6 +30,15 @@ declare namespace JS_TESTS {
readonly __doNotUseOrImplementIt: foo.TestInterfaceImpl["__doNotUseOrImplementIt"] & foo.AnotherExportedInterface["__doNotUseOrImplementIt"];
}
function processInterface(test: foo.TestInterface): string;
interface WithTheCompanion {
readonly interfaceField: string;
readonly __doNotUseOrImplementIt: {
readonly "foo.WithTheCompanion": unique symbol;
};
}
const WithTheCompanion: {
companionFunction(): string;
};
function processOptionalInterface(a: foo.OptionalFieldsInterface): string;
interface InterfaceWithCompanion {
readonly __doNotUseOrImplementIt: {
@@ -37,4 +46,4 @@ declare namespace JS_TESTS {
};
}
}
}
}
@@ -38,6 +38,15 @@ external interface OptionalFieldsInterface {
val notRequired: Int?
}
@JsExport
interface WithTheCompanion {
val interfaceField: String
companion object {
fun companionFunction(): String = "FUNCTION"
}
}
@JsExport
fun processOptionalInterface(a: OptionalFieldsInterface): String {
return "${a.required}${a.notRequired ?: "unknown"}"
@@ -48,6 +57,7 @@ fun processOptionalInterface(a: OptionalFieldsInterface): String {
interface InterfaceWithCompanion {
// Emulate added by plugin companion like kotlinx.serialization does
@Suppress("WRONG_EXPORTED_DECLARATION")
@JsExport.Ignore
companion object {
fun foo() = "String"
}
@@ -2,6 +2,7 @@ import TestInterfaceImpl = JS_TESTS.foo.TestInterfaceImpl;
import ChildTestInterfaceImpl = JS_TESTS.foo.ChildTestInterfaceImpl;
import processInterface = JS_TESTS.foo.processInterface;
import processOptionalInterface = JS_TESTS.foo.processOptionalInterface;
import WithTheCompanion = JS_TESTS.foo.WithTheCompanion;
function assert(condition: boolean) {
if (!condition) {
@@ -20,5 +21,7 @@ function box(): string {
assert(processOptionalInterface({ required: 4, notRequired: null }) == "4unknown")
assert(processOptionalInterface({ required: 4, notRequired: 5 }) == "45")
assert(WithTheCompanion.companionFunction() == "FUNCTION")
return "OK";
}