[Wasm] Support JsModule and JsQualifier
This commit is contained in:
committed by
Space Team
parent
75d3ae4466
commit
d14d4c8510
+4
-1
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.wasm
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.ir.Ir
|
import org.jetbrains.kotlin.backend.common.ir.Ir
|
||||||
import org.jetbrains.kotlin.backend.common.ir.Symbols
|
import org.jetbrains.kotlin.backend.common.ir.Symbols
|
||||||
|
import org.jetbrains.kotlin.backend.wasm.ir2wasm.JsModuleAndQualifierReference
|
||||||
import org.jetbrains.kotlin.backend.wasm.lower.WasmSharedVariablesManager
|
import org.jetbrains.kotlin.backend.wasm.lower.WasmSharedVariablesManager
|
||||||
import org.jetbrains.kotlin.backend.wasm.utils.WasmInlineClassesUtils
|
import org.jetbrains.kotlin.backend.wasm.utils.WasmInlineClassesUtils
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
@@ -23,7 +24,6 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
|
|||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.DescriptorlessExternalPackageFragmentSymbol
|
import org.jetbrains.kotlin.ir.symbols.impl.DescriptorlessExternalPackageFragmentSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
|
||||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||||
import org.jetbrains.kotlin.ir.types.IrTypeSystemContext
|
import org.jetbrains.kotlin.ir.types.IrTypeSystemContext
|
||||||
import org.jetbrains.kotlin.ir.types.IrTypeSystemContextImpl
|
import org.jetbrains.kotlin.ir.types.IrTypeSystemContextImpl
|
||||||
@@ -63,6 +63,9 @@ class WasmBackendContext(
|
|||||||
val jsClosureCallers = mutableMapOf<IrSimpleType, IrSimpleFunction>()
|
val jsClosureCallers = mutableMapOf<IrSimpleType, IrSimpleFunction>()
|
||||||
val jsToKotlinClosures = mutableMapOf<IrSimpleType, IrSimpleFunction>()
|
val jsToKotlinClosures = mutableMapOf<IrSimpleType, IrSimpleFunction>()
|
||||||
|
|
||||||
|
val jsModuleAndQualifierReferences =
|
||||||
|
mutableSetOf<JsModuleAndQualifierReference>()
|
||||||
|
|
||||||
override val coroutineSymbols =
|
override val coroutineSymbols =
|
||||||
JsCommonCoroutineSymbols(symbolTable, module,this)
|
JsCommonCoroutineSymbols(symbolTable, module,this)
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.backend.wasm
|
|||||||
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
|
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
|
||||||
import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel
|
import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel
|
||||||
import org.jetbrains.kotlin.backend.common.serialization.linkerissues.checkNoUnboundSymbols
|
import org.jetbrains.kotlin.backend.common.serialization.linkerissues.checkNoUnboundSymbols
|
||||||
|
import org.jetbrains.kotlin.backend.wasm.ir2wasm.JsModuleAndQualifierReference
|
||||||
import org.jetbrains.kotlin.backend.wasm.ir2wasm.WasmCompiledModuleFragment
|
import org.jetbrains.kotlin.backend.wasm.ir2wasm.WasmCompiledModuleFragment
|
||||||
import org.jetbrains.kotlin.backend.wasm.ir2wasm.WasmModuleFragmentGenerator
|
import org.jetbrains.kotlin.backend.wasm.ir2wasm.WasmModuleFragmentGenerator
|
||||||
import org.jetbrains.kotlin.backend.wasm.ir2wasm.toJsStringLiteral
|
import org.jetbrains.kotlin.backend.wasm.ir2wasm.toJsStringLiteral
|
||||||
@@ -107,7 +108,10 @@ fun compileWasm(
|
|||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
val jsUninstantiatedWrapper = compiledWasmModule.generateAsyncJsWrapper("./$baseFileName.wasm")
|
val jsUninstantiatedWrapper = compiledWasmModule.generateAsyncJsWrapper(
|
||||||
|
"./$baseFileName.wasm",
|
||||||
|
backendContext.jsModuleAndQualifierReferences
|
||||||
|
)
|
||||||
val jsWrapper = generateEsmExportsWrapper("./$baseFileName.uninstantiated.mjs")
|
val jsWrapper = generateEsmExportsWrapper("./$baseFileName.uninstantiated.mjs")
|
||||||
|
|
||||||
val os = ByteArrayOutputStream()
|
val os = ByteArrayOutputStream()
|
||||||
@@ -172,43 +176,74 @@ private fun generateSourceMap(
|
|||||||
return sourceMapBuilder.build()
|
return sourceMapBuilder.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun WasmCompiledModuleFragment.generateAsyncJsWrapper(wasmFilePath: String): String {
|
fun WasmCompiledModuleFragment.generateAsyncJsWrapper(
|
||||||
|
wasmFilePath: String,
|
||||||
|
jsModuleAndQualifierReferences: Set<JsModuleAndQualifierReference>
|
||||||
|
): String {
|
||||||
|
|
||||||
val jsCodeBody = jsFuns.joinToString(",\n") {
|
val jsCodeBody = jsFuns.joinToString(",\n") {
|
||||||
"${it.importName.toJsStringLiteral()} : ${it.jsCode}"
|
"${it.importName.toJsStringLiteral()} : ${it.jsCode}"
|
||||||
}
|
}
|
||||||
|
|
||||||
val jsCodeBodyIndented = jsCodeBody.prependIndent(" ")
|
val jsCodeBodyIndented = jsCodeBody.prependIndent(" ")
|
||||||
|
|
||||||
val imports = jsModuleImports
|
val imports = jsModuleImports
|
||||||
.toList()
|
.toList()
|
||||||
.sorted()
|
.sorted()
|
||||||
.joinToString("") {
|
.joinToString("") {
|
||||||
val moduleSpecifier = it.toJsStringLiteral()
|
val moduleSpecifier = it.toJsStringLiteral()
|
||||||
" $moduleSpecifier: imports[$moduleSpecifier] ?? await import($moduleSpecifier),\n"
|
" $moduleSpecifier: await _importModule($moduleSpecifier),\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val referencesToQualifiedAndImportedDeclarations = jsModuleAndQualifierReferences
|
||||||
|
.map {
|
||||||
|
val module = it.module
|
||||||
|
val qualifier = it.qualifier
|
||||||
|
buildString {
|
||||||
|
append(" const ")
|
||||||
|
append(it.jsVariableName)
|
||||||
|
append(" = ")
|
||||||
|
if (module != null) {
|
||||||
|
append("(await _importModule(${module.toJsStringLiteral()}))")
|
||||||
|
if (qualifier != null)
|
||||||
|
append(".")
|
||||||
|
}
|
||||||
|
if (qualifier != null) {
|
||||||
|
append(qualifier)
|
||||||
|
}
|
||||||
|
append(";")
|
||||||
|
}
|
||||||
|
}.sorted()
|
||||||
|
.joinToString("\n")
|
||||||
|
|
||||||
//language=js
|
//language=js
|
||||||
return """
|
return """
|
||||||
const externrefBoxes = new WeakMap();
|
|
||||||
// ref must be non-null
|
|
||||||
function tryGetOrSetExternrefBox(ref, ifNotCached) {
|
|
||||||
if (typeof ref !== 'object') return ifNotCached;
|
|
||||||
const cachedBox = externrefBoxes.get(ref);
|
|
||||||
if (cachedBox !== void 0) return cachedBox;
|
|
||||||
externrefBoxes.set(ref, ifNotCached);
|
|
||||||
return ifNotCached;
|
|
||||||
}
|
|
||||||
|
|
||||||
const js_code = {
|
|
||||||
$jsCodeBodyIndented
|
|
||||||
}
|
|
||||||
|
|
||||||
// Placed here to give access to it from externals (js_code)
|
|
||||||
let wasmInstance;
|
|
||||||
let require;
|
|
||||||
let wasmExports;
|
|
||||||
|
|
||||||
export async function instantiate(imports={}, runInitializer=true) {
|
export async function instantiate(imports={}, runInitializer=true) {
|
||||||
|
const externrefBoxes = new WeakMap();
|
||||||
|
// ref must be non-null
|
||||||
|
function tryGetOrSetExternrefBox(ref, ifNotCached) {
|
||||||
|
if (typeof ref !== 'object') return ifNotCached;
|
||||||
|
const cachedBox = externrefBoxes.get(ref);
|
||||||
|
if (cachedBox !== void 0) return cachedBox;
|
||||||
|
externrefBoxes.set(ref, ifNotCached);
|
||||||
|
return ifNotCached;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function _importModule(x) {
|
||||||
|
return imports[x] ?? await import(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
$referencesToQualifiedAndImportedDeclarations
|
||||||
|
|
||||||
|
const js_code = {
|
||||||
|
$jsCodeBodyIndented
|
||||||
|
}
|
||||||
|
|
||||||
|
// Placed here to give access to it from externals (js_code)
|
||||||
|
let wasmInstance;
|
||||||
|
let require;
|
||||||
|
let wasmExports;
|
||||||
|
|
||||||
const isNodeJs = (typeof process !== 'undefined') && (process.release.name === 'node');
|
const isNodeJs = (typeof process !== 'undefined') && (process.release.name === 'node');
|
||||||
const isD8 = !isNodeJs && (typeof d8 !== 'undefined');
|
const isD8 = !isNodeJs && (typeof d8 !== 'undefined');
|
||||||
const isBrowser = !isNodeJs && !isD8 && (typeof window !== 'undefined');
|
const isBrowser = !isNodeJs && !isD8 && (typeof window !== 'undefined');
|
||||||
|
|||||||
+15
-1
@@ -6,6 +6,20 @@
|
|||||||
package org.jetbrains.kotlin.backend.wasm.ir2wasm
|
package org.jetbrains.kotlin.backend.wasm.ir2wasm
|
||||||
|
|
||||||
import org.jetbrains.kotlin.js.backend.JsToStringGenerationVisitor
|
import org.jetbrains.kotlin.js.backend.JsToStringGenerationVisitor
|
||||||
|
import java.util.Base64
|
||||||
|
|
||||||
fun String.toJsStringLiteral(): CharSequence =
|
fun String.toJsStringLiteral(): CharSequence =
|
||||||
JsToStringGenerationVisitor.javaScriptString(this)
|
JsToStringGenerationVisitor.javaScriptString(this)
|
||||||
|
|
||||||
|
data class JsModuleAndQualifierReference(
|
||||||
|
val module: String?,
|
||||||
|
val qualifier: String?,
|
||||||
|
) {
|
||||||
|
val jsVariableName = run {
|
||||||
|
// Encode variable name as base64 to have a valid unique JS identifier
|
||||||
|
val encoder = Base64.getEncoder().withoutPadding()
|
||||||
|
val moduleBase64 = module?.let { encoder.encodeToString(module.encodeToByteArray()) }.orEmpty()
|
||||||
|
val qualifierBase64 = qualifier?.let { encoder.encodeToString(qualifier.encodeToByteArray()) }.orEmpty()
|
||||||
|
"_ref_${moduleBase64}_$qualifierBase64"
|
||||||
|
}
|
||||||
|
}
|
||||||
+46
-5
@@ -8,12 +8,15 @@ package org.jetbrains.kotlin.backend.wasm.lower
|
|||||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||||
import org.jetbrains.kotlin.backend.wasm.WasmBackendContext
|
import org.jetbrains.kotlin.backend.wasm.WasmBackendContext
|
||||||
|
import org.jetbrains.kotlin.backend.wasm.ir2wasm.JsModuleAndQualifierReference
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.backend.wasm.utils.getJsFunAnnotation
|
import org.jetbrains.kotlin.backend.wasm.utils.getJsFunAnnotation
|
||||||
import org.jetbrains.kotlin.backend.wasm.utils.getWasmImportDescriptor
|
import org.jetbrains.kotlin.backend.wasm.utils.getWasmImportDescriptor
|
||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.utils.getJsModule
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.getJsNameOrKotlinName
|
import org.jetbrains.kotlin.ir.backend.js.utils.getJsNameOrKotlinName
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.utils.getJsQualifier
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget
|
import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
|
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
||||||
@@ -108,7 +111,7 @@ class ComplexExternalDeclarationsToTopLevelFunctionsLowering(val context: WasmBa
|
|||||||
val dispatchReceiver = getter.dispatchReceiverParameter
|
val dispatchReceiver = getter.dispatchReceiverParameter
|
||||||
val jsCode =
|
val jsCode =
|
||||||
if (dispatchReceiver == null)
|
if (dispatchReceiver == null)
|
||||||
"() => $propName"
|
"() => ${referenceTopLevelExternalDeclaration(property)}"
|
||||||
else
|
else
|
||||||
"(_this) => _this.$propName"
|
"(_this) => _this.$propName"
|
||||||
|
|
||||||
@@ -130,7 +133,7 @@ class ComplexExternalDeclarationsToTopLevelFunctionsLowering(val context: WasmBa
|
|||||||
val dispatchReceiver = setter.dispatchReceiverParameter
|
val dispatchReceiver = setter.dispatchReceiverParameter
|
||||||
val jsCode =
|
val jsCode =
|
||||||
if (dispatchReceiver == null)
|
if (dispatchReceiver == null)
|
||||||
"(v) => $propName = v"
|
"(v) => ${referenceTopLevelExternalDeclaration(property)} = v"
|
||||||
else
|
else
|
||||||
"(_this, v) => _this.$propName = v"
|
"(_this, v) => _this.$propName = v"
|
||||||
|
|
||||||
@@ -159,12 +162,19 @@ class ComplexExternalDeclarationsToTopLevelFunctionsLowering(val context: WasmBa
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
append('.')
|
append('.')
|
||||||
|
append(klass.getJsNameOrKotlinName())
|
||||||
|
} else {
|
||||||
|
append(referenceTopLevelExternalDeclaration(klass))
|
||||||
}
|
}
|
||||||
append(klass.getJsNameOrKotlinName())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun processExternalConstructor(constructor: IrConstructor) {
|
fun processExternalConstructor(constructor: IrConstructor) {
|
||||||
val klass = constructor.constructedClass
|
val klass = constructor.constructedClass
|
||||||
|
|
||||||
|
// External interfaces can have synthetic primary constructors in K/JS
|
||||||
|
if (klass.isInterface)
|
||||||
|
return
|
||||||
|
|
||||||
processFunctionOrConstructor(
|
processFunctionOrConstructor(
|
||||||
function = constructor,
|
function = constructor,
|
||||||
name = klass.name,
|
name = klass.name,
|
||||||
@@ -183,14 +193,26 @@ class ComplexExternalDeclarationsToTopLevelFunctionsLowering(val context: WasmBa
|
|||||||
val jsFun = function.getJsFunAnnotation()
|
val jsFun = function.getJsFunAnnotation()
|
||||||
// Wrap external functions without @JsFun to lambdas `foo` -> `(a, b) => foo(a, b)`.
|
// Wrap external functions without @JsFun to lambdas `foo` -> `(a, b) => foo(a, b)`.
|
||||||
// This way we wouldn't fail if we don't call them.
|
// This way we wouldn't fail if we don't call them.
|
||||||
if (jsFun != null && function.valueParameters.all { it.defaultValue == null && it.varargElementType == null })
|
if (jsFun != null &&
|
||||||
|
function.valueParameters.all { it.defaultValue == null && it.varargElementType == null } &&
|
||||||
|
currentFile.getJsQualifier() == null &&
|
||||||
|
currentFile.getJsModule() == null
|
||||||
|
) {
|
||||||
return
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val jsFunctionReference = when {
|
||||||
|
jsFun != null -> "($jsFun)"
|
||||||
|
function.isTopLevelDeclaration -> referenceTopLevelExternalDeclaration(function)
|
||||||
|
else -> function.getJsNameOrKotlinName().identifier
|
||||||
|
}
|
||||||
|
|
||||||
processFunctionOrConstructor(
|
processFunctionOrConstructor(
|
||||||
function = function,
|
function = function,
|
||||||
name = function.name,
|
name = function.name,
|
||||||
returnType = function.returnType,
|
returnType = function.returnType,
|
||||||
isConstructor = false,
|
isConstructor = false,
|
||||||
jsFunctionReference = jsFun?.let { "($it)" } ?: function.getJsNameOrKotlinName().identifier
|
jsFunctionReference = jsFunctionReference
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -341,6 +363,25 @@ class ComplexExternalDeclarationsToTopLevelFunctionsLowering(val context: WasmBa
|
|||||||
addedDeclarations += res
|
addedDeclarations += res
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun referenceTopLevelExternalDeclaration(declaration: IrDeclarationWithName): String {
|
||||||
|
var name = declaration.getJsNameOrKotlinName().identifier
|
||||||
|
|
||||||
|
val qualifier = currentFile.getJsQualifier()
|
||||||
|
|
||||||
|
val module = currentFile.getJsModule()
|
||||||
|
?: declaration.getJsModule()?.also {
|
||||||
|
// JsModule on top level declarations imports "default"
|
||||||
|
name = "default"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qualifier == null && module == null)
|
||||||
|
return name
|
||||||
|
|
||||||
|
val qualifieReference = JsModuleAndQualifierReference(module, qualifier)
|
||||||
|
context.jsModuleAndQualifierReferences += qualifieReference
|
||||||
|
return qualifieReference.jsVariableName + "." + name
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
// ES_MODULES
|
||||||
|
// FILE: jsModule.mjs
|
||||||
|
let x = 10;
|
||||||
|
function f() { return 10; };
|
||||||
|
class C {
|
||||||
|
constructor(x) {
|
||||||
|
this.x = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { x, f, C };
|
||||||
|
export default { defaultX: x, defaultF: f, defaultC: C };
|
||||||
|
|
||||||
|
// FILE: lib1.kt
|
||||||
|
@file:JsModule("./jsModule.mjs")
|
||||||
|
|
||||||
|
package named
|
||||||
|
|
||||||
|
external val x: Int
|
||||||
|
external fun f(): Int
|
||||||
|
external class C {
|
||||||
|
constructor(x: String)
|
||||||
|
val x: String
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: lib2.kt
|
||||||
|
package default
|
||||||
|
|
||||||
|
@JsModule("./jsModule.mjs")
|
||||||
|
external object jsModule {
|
||||||
|
val defaultX: Int
|
||||||
|
fun defaultF(): Int
|
||||||
|
class defaultC {
|
||||||
|
constructor(x: String)
|
||||||
|
|
||||||
|
val x: String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// FILE: main.kt
|
||||||
|
fun box(): String {
|
||||||
|
if (named.x != 10) return "Fail1"
|
||||||
|
if (named.f() != 10) return "Fail2"
|
||||||
|
if (named.C("10").x != "10") return "Fail3"
|
||||||
|
|
||||||
|
if (default.jsModule.defaultX != 10) return "Fail4"
|
||||||
|
if (default.jsModule.defaultF() != 10) return "Fail5"
|
||||||
|
if (default.jsModule.defaultC("10").x != "10") return "Fail6"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
// ES_MODULES
|
||||||
|
// FILE: jsModuleWithQualifier.mjs
|
||||||
|
let a = {
|
||||||
|
b: {
|
||||||
|
c: {
|
||||||
|
d: {
|
||||||
|
x: 10,
|
||||||
|
f() { return 10; },
|
||||||
|
C: class C {
|
||||||
|
constructor(x) {
|
||||||
|
this.x = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export { a };
|
||||||
|
|
||||||
|
// FILE: lib1.kt
|
||||||
|
@file:JsQualifier("a.b.c.d")
|
||||||
|
@file:JsModule("./jsModuleWithQualifier.mjs")
|
||||||
|
|
||||||
|
package abcd
|
||||||
|
|
||||||
|
external var x: Int
|
||||||
|
external fun f(): Int
|
||||||
|
external class C {
|
||||||
|
constructor(x: String)
|
||||||
|
val x: String
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsName("x")
|
||||||
|
external var x2: Int
|
||||||
|
|
||||||
|
@JsName("f")
|
||||||
|
external fun f2(): Int
|
||||||
|
|
||||||
|
@JsName("C")
|
||||||
|
external class C2 {
|
||||||
|
constructor(x: String)
|
||||||
|
@JsName("x")
|
||||||
|
val x2: String
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: lib2.kt
|
||||||
|
@file:JsQualifier("a")
|
||||||
|
@file:JsModule("./jsModuleWithQualifier.mjs")
|
||||||
|
package a
|
||||||
|
|
||||||
|
external object b {
|
||||||
|
class c {
|
||||||
|
companion object {
|
||||||
|
@JsName("d")
|
||||||
|
object d2 {
|
||||||
|
var x: Int
|
||||||
|
fun f(): Int
|
||||||
|
class C {
|
||||||
|
constructor(x: String)
|
||||||
|
val x: String
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsName("x")
|
||||||
|
var x2: Int
|
||||||
|
|
||||||
|
@JsName("f")
|
||||||
|
fun f2(): Int
|
||||||
|
|
||||||
|
@JsName("C")
|
||||||
|
class C2 {
|
||||||
|
constructor(x: String)
|
||||||
|
@JsName("x")
|
||||||
|
val x2: String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// FILE: main.kt
|
||||||
|
fun box(): String {
|
||||||
|
if (abcd.x != 10) return "Fail1"
|
||||||
|
if (abcd.f() != 10) return "Fail2"
|
||||||
|
if (abcd.C("10").x != "10") return "Fail3"
|
||||||
|
|
||||||
|
if (abcd.x2 != 10) return "Fail4"
|
||||||
|
if (abcd.f2() != 10) return "Fail5"
|
||||||
|
if (abcd.C2("10").x2 != "10") return "Fail6"
|
||||||
|
|
||||||
|
if (a.b.c.Companion.d2.x != 10) return "Fail7"
|
||||||
|
if (a.b.c.Companion.d2.f() != 10) return "Fail8"
|
||||||
|
if (a.b.c.Companion.d2.C("10").x != "10") return "Fail9"
|
||||||
|
|
||||||
|
if (a.b.c.Companion.d2.x2 != 10) return "Fail10"
|
||||||
|
if (a.b.c.Companion.d2.f2() != 10) return "Fail11"
|
||||||
|
if (a.b.c.Companion.d2.C2("10").x2 != "10") return "Fail12"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
// FILE: jsQualifier.js
|
||||||
|
let a = {
|
||||||
|
b: {
|
||||||
|
c: {
|
||||||
|
d: {
|
||||||
|
x: 10,
|
||||||
|
f() { return 10; },
|
||||||
|
C: class C {
|
||||||
|
constructor(x) {
|
||||||
|
this.x = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// FILE: lib1.kt
|
||||||
|
@file:JsQualifier("a.b.c.d")
|
||||||
|
package abcd
|
||||||
|
|
||||||
|
external var x: Int
|
||||||
|
external fun f(): Int
|
||||||
|
external class C {
|
||||||
|
constructor(x: String)
|
||||||
|
val x: String
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsName("x")
|
||||||
|
external var x2: Int
|
||||||
|
|
||||||
|
@JsName("f")
|
||||||
|
external fun f2(): Int
|
||||||
|
|
||||||
|
@JsName("C")
|
||||||
|
external class C2 {
|
||||||
|
constructor(x: String)
|
||||||
|
@JsName("x")
|
||||||
|
val x2: String
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: lib2.kt
|
||||||
|
@file:JsQualifier("a")
|
||||||
|
package a
|
||||||
|
|
||||||
|
external object b {
|
||||||
|
class c {
|
||||||
|
companion object {
|
||||||
|
@JsName("d")
|
||||||
|
object d2 {
|
||||||
|
var x: Int
|
||||||
|
fun f(): Int
|
||||||
|
class C {
|
||||||
|
constructor(x: String)
|
||||||
|
val x: String
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsName("x")
|
||||||
|
var x2: Int
|
||||||
|
|
||||||
|
@JsName("f")
|
||||||
|
fun f2(): Int
|
||||||
|
|
||||||
|
@JsName("C")
|
||||||
|
class C2 {
|
||||||
|
constructor(x: String)
|
||||||
|
@JsName("x")
|
||||||
|
val x2: String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// FILE: main.kt
|
||||||
|
fun box(): String {
|
||||||
|
if (abcd.x != 10) return "Fail1"
|
||||||
|
if (abcd.f() != 10) return "Fail2"
|
||||||
|
if (abcd.C("10").x != "10") return "Fail3"
|
||||||
|
|
||||||
|
if (abcd.x2 != 10) return "Fail4"
|
||||||
|
if (abcd.f2() != 10) return "Fail5"
|
||||||
|
if (abcd.C2("10").x2 != "10") return "Fail6"
|
||||||
|
|
||||||
|
if (a.b.c.Companion.d2.x != 10) return "Fail7"
|
||||||
|
if (a.b.c.Companion.d2.f() != 10) return "Fail8"
|
||||||
|
if (a.b.c.Companion.d2.C("10").x != "10") return "Fail9"
|
||||||
|
|
||||||
|
if (a.b.c.Companion.d2.x2 != 10) return "Fail10"
|
||||||
|
if (a.b.c.Companion.d2.f2() != 10) return "Fail11"
|
||||||
|
if (a.b.c.Companion.d2.C2("10").x2 != "10") return "Fail12"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -34,6 +34,15 @@ fun main(args: Array<String>) {
|
|||||||
testClass<AbstractJsTranslatorWasmTest> {
|
testClass<AbstractJsTranslatorWasmTest> {
|
||||||
model("box/main", pattern = "^([^_](.+))\\.kt$", targetBackend = TargetBackend.WASM)
|
model("box/main", pattern = "^([^_](.+))\\.kt$", targetBackend = TargetBackend.WASM)
|
||||||
model("box/native/", pattern = "^([^_](.+))\\.kt$", targetBackend = TargetBackend.WASM)
|
model("box/native/", pattern = "^([^_](.+))\\.kt$", targetBackend = TargetBackend.WASM)
|
||||||
|
model("box/esModules/", pattern = "^([^_](.+))\\.kt$", targetBackend = TargetBackend.WASM,
|
||||||
|
excludeDirs = listOf(
|
||||||
|
// JsExport is not supported for classes
|
||||||
|
"jsExport", "native", "export",
|
||||||
|
// Multimodal infra is not supported. Also, we don't use ES modules for cross-module refs in Wasm
|
||||||
|
"crossModuleRef", "crossModuleRefPerFile", "crossModuleRefPerModule"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
model("box/jsQualifier/", pattern = "^([^_](.+))\\.kt$", targetBackend = TargetBackend.WASM)
|
||||||
}
|
}
|
||||||
|
|
||||||
testClass<AbstractJsTranslatorUnitWasmTest> {
|
testClass<AbstractJsTranslatorUnitWasmTest> {
|
||||||
|
|||||||
Generated
+18
@@ -55,6 +55,24 @@ public class FirJsCodegenWasmJsInteropTestGenerated extends AbstractFirJsCodegen
|
|||||||
runTest("compiler/testData/codegen/boxWasmJsInterop/jsExport.kt");
|
runTest("compiler/testData/codegen/boxWasmJsInterop/jsExport.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("jsModule.kt")
|
||||||
|
public void testJsModule() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxWasmJsInterop/jsModule.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("jsModuleWithQualifier.kt")
|
||||||
|
public void testJsModuleWithQualifier() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxWasmJsInterop/jsModuleWithQualifier.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("jsQualifier.kt")
|
||||||
|
public void testJsQualifier() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxWasmJsInterop/jsQualifier.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("jsToKotlinAdapters.kt")
|
@TestMetadata("jsToKotlinAdapters.kt")
|
||||||
public void testJsToKotlinAdapters() throws Exception {
|
public void testJsToKotlinAdapters() throws Exception {
|
||||||
|
|||||||
Generated
+18
@@ -55,6 +55,24 @@ public class IrCodegenWasmJsInteropJsTestGenerated extends AbstractIrCodegenWasm
|
|||||||
runTest("compiler/testData/codegen/boxWasmJsInterop/jsExport.kt");
|
runTest("compiler/testData/codegen/boxWasmJsInterop/jsExport.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("jsModule.kt")
|
||||||
|
public void testJsModule() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxWasmJsInterop/jsModule.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("jsModuleWithQualifier.kt")
|
||||||
|
public void testJsModuleWithQualifier() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxWasmJsInterop/jsModuleWithQualifier.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("jsQualifier.kt")
|
||||||
|
public void testJsQualifier() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxWasmJsInterop/jsQualifier.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("jsToKotlinAdapters.kt")
|
@TestMetadata("jsToKotlinAdapters.kt")
|
||||||
public void testJsToKotlinAdapters() throws Exception {
|
public void testJsToKotlinAdapters() throws Exception {
|
||||||
|
|||||||
+15
@@ -70,6 +70,21 @@ public class IrCodegenWasmJsInteropWasmTestGenerated extends AbstractIrCodegenWa
|
|||||||
runTest("compiler/testData/codegen/boxWasmJsInterop/jsExport.kt");
|
runTest("compiler/testData/codegen/boxWasmJsInterop/jsExport.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("jsModule.kt")
|
||||||
|
public void testJsModule() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxWasmJsInterop/jsModule.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("jsModuleWithQualifier.kt")
|
||||||
|
public void testJsModuleWithQualifier() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxWasmJsInterop/jsModuleWithQualifier.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("jsQualifier.kt")
|
||||||
|
public void testJsQualifier() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxWasmJsInterop/jsQualifier.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("jsToKotlinAdapters.kt")
|
@TestMetadata("jsToKotlinAdapters.kt")
|
||||||
public void testJsToKotlinAdapters() throws Exception {
|
public void testJsToKotlinAdapters() throws Exception {
|
||||||
runTest("compiler/testData/codegen/boxWasmJsInterop/jsToKotlinAdapters.kt");
|
runTest("compiler/testData/codegen/boxWasmJsInterop/jsToKotlinAdapters.kt");
|
||||||
|
|||||||
+158
@@ -205,4 +205,162 @@ public class JsTranslatorWasmTestGenerated extends AbstractJsTranslatorWasmTest
|
|||||||
runTest("js/js.translator/testData/box/native/vararg.kt");
|
runTest("js/js.translator/testData/box/native/vararg.kt");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("js/js.translator/testData/box/esModules")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class EsModules extends AbstractJsTranslatorWasmTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInEsModules() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true, "jsExport", "native", "export", "crossModuleRef", "crossModuleRefPerFile", "crossModuleRefPerModule");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("js/js.translator/testData/box/esModules/incremental")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Incremental extends AbstractJsTranslatorWasmTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInIncremental() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/incremental"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("jsModule.kt")
|
||||||
|
public void testJsModule() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/esModules/incremental/jsModule.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("js/js.translator/testData/box/esModules/inline")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Inline extends AbstractJsTranslatorWasmTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInInline() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/inline"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("js/js.translator/testData/box/esModules/jsModule")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class JsModule extends AbstractJsTranslatorWasmTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInJsModule() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/jsModule"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("externalClass.kt")
|
||||||
|
public void testExternalClass() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/esModules/jsModule/externalClass.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("externalClassNameClash.kt")
|
||||||
|
public void testExternalClassNameClash() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/esModules/jsModule/externalClassNameClash.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("externalFunction.kt")
|
||||||
|
public void testExternalFunction() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/esModules/jsModule/externalFunction.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("externalFunctionNameClash.kt")
|
||||||
|
public void testExternalFunctionNameClash() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/esModules/jsModule/externalFunctionNameClash.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("externalObject.kt")
|
||||||
|
public void testExternalObject() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/esModules/jsModule/externalObject.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("externalPackage.kt")
|
||||||
|
public void testExternalPackage() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/esModules/jsModule/externalPackage.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("externalPackageInDifferentFile.kt")
|
||||||
|
public void testExternalPackageInDifferentFile() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/esModules/jsModule/externalPackageInDifferentFile.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("externalProperty.kt")
|
||||||
|
public void testExternalProperty() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/esModules/jsModule/externalProperty.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("interfaces.kt")
|
||||||
|
public void testInterfaces() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/esModules/jsModule/interfaces.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("topLevelVarargFun.kt")
|
||||||
|
public void testTopLevelVarargFun() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/esModules/jsModule/topLevelVarargFun.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("js/js.translator/testData/box/esModules/jsName")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class JsName extends AbstractJsTranslatorWasmTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInJsName() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/jsName"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("defaultJsName.kt")
|
||||||
|
public void testDefaultJsName() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/esModules/jsName/defaultJsName.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("jsTopLevelClashes.kt")
|
||||||
|
public void testJsTopLevelClashes() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/esModules/jsName/jsTopLevelClashes.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("js/js.translator/testData/box/jsQualifier")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class JsQualifier extends AbstractJsTranslatorWasmTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInJsQualifier() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/jsQualifier"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("classes.kt")
|
||||||
|
public void testClasses() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/jsQualifier/classes.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("interfaces.kt")
|
||||||
|
public void testInterfaces() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/jsQualifier/interfaces.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("simple.kt")
|
||||||
|
public void testSimple() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/jsQualifier/simple.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
// DONT_TARGET_EXACT_BACKEND: JS
|
// DONT_TARGET_EXACT_BACKEND: JS
|
||||||
// ES_MODULES
|
// ES_MODULES
|
||||||
|
|
||||||
|
// Generated .mjs name is different in Wasm
|
||||||
|
// DONT_TARGET_EXACT_BACKEND: WASM
|
||||||
|
|
||||||
// FILE: main.kt
|
// FILE: main.kt
|
||||||
interface I {
|
interface I {
|
||||||
fun ok(): String
|
fun ok(): String
|
||||||
|
|||||||
@@ -2,6 +2,9 @@
|
|||||||
// ES_MODULES
|
// ES_MODULES
|
||||||
// DONT_TARGET_EXACT_BACKEND: JS
|
// DONT_TARGET_EXACT_BACKEND: JS
|
||||||
|
|
||||||
|
// DONT_TARGET_EXACT_BACKEND: WASM
|
||||||
|
// WASM_MUTE_REASON: UNSUPPORTED_JS_INTEROP
|
||||||
|
|
||||||
package foo
|
package foo
|
||||||
|
|
||||||
@JsModule("./externalClassWithDefaults.mjs")
|
@JsModule("./externalClassWithDefaults.mjs")
|
||||||
|
|||||||
@@ -2,6 +2,9 @@
|
|||||||
// ES_MODULES
|
// ES_MODULES
|
||||||
// DONT_TARGET_EXACT_BACKEND: JS
|
// DONT_TARGET_EXACT_BACKEND: JS
|
||||||
|
|
||||||
|
// DONT_TARGET_EXACT_BACKEND: WASM
|
||||||
|
// WASM_MUTE_REASON: UNSUPPORTED_JS_INTEROP
|
||||||
|
|
||||||
package foo
|
package foo
|
||||||
|
|
||||||
@JsModule("./externalConstructor.mjs")
|
@JsModule("./externalConstructor.mjs")
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
// IGNORE_FIR
|
// IGNORE_FIR
|
||||||
// EXPECTED_REACHABLE_NODES: 1284
|
// EXPECTED_REACHABLE_NODES: 1284
|
||||||
|
|
||||||
|
// DONT_TARGET_EXACT_BACKEND: WASM
|
||||||
|
// WASM_MUTE_REASON: MODULE_KIND
|
||||||
|
|
||||||
// NO_JS_MODULE_SYSTEM
|
// NO_JS_MODULE_SYSTEM
|
||||||
// MODULE: lib
|
// MODULE: lib
|
||||||
// MODULE_KIND: UMD
|
// MODULE_KIND: UMD
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
// IGNORE_FIR
|
// IGNORE_FIR
|
||||||
// EXPECTED_REACHABLE_NODES: 1282
|
// EXPECTED_REACHABLE_NODES: 1282
|
||||||
|
|
||||||
|
// DONT_TARGET_EXACT_BACKEND: WASM
|
||||||
|
// WASM_MUTE_REASON: MODULE_KIND
|
||||||
|
|
||||||
// MODULE: lib
|
// MODULE: lib
|
||||||
// MODULE_KIND: AMD
|
// MODULE_KIND: AMD
|
||||||
// FILE: lib.kt
|
// FILE: lib.kt
|
||||||
|
|||||||
@@ -37,4 +37,65 @@ public actual annotation class JsExport {
|
|||||||
AnnotationTarget.PROPERTY_GETTER,
|
AnnotationTarget.PROPERTY_GETTER,
|
||||||
AnnotationTarget.PROPERTY_SETTER
|
AnnotationTarget.PROPERTY_SETTER
|
||||||
)
|
)
|
||||||
public actual annotation class JsName(actual val name: String)
|
public actual annotation class JsName(actual val name: String)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Denotes an `external` declaration that must be imported from JavaScript module.
|
||||||
|
*
|
||||||
|
* The annotation can be used on top-level external declarations (classes, properties, functions) and files.
|
||||||
|
* In case of file (which can't be `external`) the following rule applies: all the declarations in
|
||||||
|
* the file must be `external`. By applying `@JsModule(...)` on a file you tell the compiler to import a JavaScript object
|
||||||
|
* that contain all the declarations from the file.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* ``` kotlin
|
||||||
|
* @JsModule("jquery")
|
||||||
|
* external abstract class JQuery() {
|
||||||
|
* // some declarations here
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* @JsModule("jquery")
|
||||||
|
* external fun JQuery(element: Element): JQuery
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @property import name of a module to import declaration from.
|
||||||
|
* It is not interpreted by the Kotlin compiler, it's passed as is directly to the target module system.
|
||||||
|
*/
|
||||||
|
@Retention(AnnotationRetention.BINARY)
|
||||||
|
@Target(AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.FILE)
|
||||||
|
public annotation class JsModule(val import: String)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds prefix to `external` declarations in a source file.
|
||||||
|
*
|
||||||
|
* JavaScript does not have concept of packages (namespaces). They are usually emulated by nested objects.
|
||||||
|
* The compiler turns references to `external` declarations either to plain unprefixed names
|
||||||
|
* or to plain imports.
|
||||||
|
* However, if a JavaScript library provides its declarations in packages, you won't be satisfied with this.
|
||||||
|
* You can tell the compiler to generate additional prefix before references to `external` declarations using the `@JsQualifier(...)`
|
||||||
|
* annotation.
|
||||||
|
*
|
||||||
|
* Note that a file marked with the `@JsQualifier(...)` annotation can't contain non-`external` declarations.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* @file:JsQualifier("my.jsPackageName")
|
||||||
|
* package some.kotlinPackage
|
||||||
|
*
|
||||||
|
* external fun foo(x: Int)
|
||||||
|
*
|
||||||
|
* external fun bar(): String
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @property value the qualifier to add to the declarations in the generated code.
|
||||||
|
* It must be a sequence of valid JavaScript identifiers separated by the `.` character.
|
||||||
|
* Examples of valid qualifiers are: `foo`, `bar.Baz`, `_.$0.f`.
|
||||||
|
*
|
||||||
|
* @see JsModule
|
||||||
|
*/
|
||||||
|
@Retention(AnnotationRetention.BINARY)
|
||||||
|
@Target(AnnotationTarget.FILE)
|
||||||
|
public annotation class JsQualifier(val value: String)
|
||||||
Reference in New Issue
Block a user