[JS IR BE] Initial export generation
This commit is contained in:
@@ -189,7 +189,7 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
|
|||||||
mainArguments = mainCallArguments
|
mainArguments = mainCallArguments
|
||||||
)
|
)
|
||||||
|
|
||||||
outputFile.writeText(compiledModule)
|
outputFile.writeText(compiledModule.jsCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
return OK
|
return OK
|
||||||
|
|||||||
@@ -29,10 +29,7 @@ import org.jetbrains.kotlin.ir.backend.js.utils.OperatorNames
|
|||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
|
||||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
import org.jetbrains.kotlin.ir.symbols.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol
|
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.types.impl.IrDynamicTypeImpl
|
import org.jetbrains.kotlin.ir.types.impl.IrDynamicTypeImpl
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
@@ -54,7 +51,7 @@ class JsIrBackendContext(
|
|||||||
|
|
||||||
override var inVerbosePhase: Boolean = false
|
override var inVerbosePhase: Boolean = false
|
||||||
|
|
||||||
var externalPackageFragment = mutableMapOf<FqName, IrPackageFragment>()
|
var externalPackageFragment = mutableMapOf<IrFileSymbol, IrFile>()
|
||||||
lateinit var bodilessBuiltInsPackageFragment: IrPackageFragment
|
lateinit var bodilessBuiltInsPackageFragment: IrPackageFragment
|
||||||
|
|
||||||
val externalNestedClasses = mutableListOf<IrClass>()
|
val externalNestedClasses = mutableListOf<IrClass>()
|
||||||
|
|||||||
@@ -78,14 +78,6 @@ private val validateIrAfterLowering = makeCustomJsModulePhase(
|
|||||||
description = "Validate IR after lowering"
|
description = "Validate IR after lowering"
|
||||||
)
|
)
|
||||||
|
|
||||||
private val moveBodilessDeclarationsToSeparatePlacePhase = makeCustomJsModulePhase(
|
|
||||||
{ context, module ->
|
|
||||||
moveBodilessDeclarationsToSeparatePlace(context, module)
|
|
||||||
},
|
|
||||||
name = "MoveBodilessDeclarationsToSeparatePlace",
|
|
||||||
description = "Move `external` and `built-in` declarations into separate place to make the following lowerings do not care about them"
|
|
||||||
)
|
|
||||||
|
|
||||||
private val expectDeclarationsRemovingPhase = makeJsModulePhase(
|
private val expectDeclarationsRemovingPhase = makeJsModulePhase(
|
||||||
::ExpectDeclarationsRemoveLowering,
|
::ExpectDeclarationsRemoveLowering,
|
||||||
name = "ExpectDeclarationsRemoving",
|
name = "ExpectDeclarationsRemoving",
|
||||||
@@ -419,7 +411,6 @@ val jsPhases = namedIrModulePhase(
|
|||||||
primaryConstructorLoweringPhase then
|
primaryConstructorLoweringPhase then
|
||||||
initializersLoweringPhase then
|
initializersLoweringPhase then
|
||||||
// Common prefix ends
|
// Common prefix ends
|
||||||
moveBodilessDeclarationsToSeparatePlacePhase then
|
|
||||||
enumClassLoweringPhase then
|
enumClassLoweringPhase then
|
||||||
enumUsageLoweringPhase then
|
enumUsageLoweringPhase then
|
||||||
suspendFunctionsLoweringPhase then
|
suspendFunctionsLoweringPhase then
|
||||||
@@ -447,6 +438,5 @@ val jsPhases = namedIrModulePhase(
|
|||||||
objectDeclarationLoweringPhase then
|
objectDeclarationLoweringPhase then
|
||||||
objectUsageLoweringPhase then
|
objectUsageLoweringPhase then
|
||||||
callsLoweringPhase then
|
callsLoweringPhase then
|
||||||
staticMembersLoweringPhase then
|
|
||||||
validateIrAfterLowering
|
validateIrAfterLowering
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import com.intellij.openapi.project.Project
|
|||||||
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.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.lower.moveBodilessDeclarationsToSeparatePlace
|
||||||
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformer
|
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformer
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.JsMainFunctionDetector
|
import org.jetbrains.kotlin.ir.backend.js.utils.JsMainFunctionDetector
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||||
@@ -28,6 +29,11 @@ fun sortDependencies(dependencies: Collection<IrModuleFragment>): Collection<IrM
|
|||||||
}.reversed()
|
}.reversed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CompilerResult(
|
||||||
|
val jsCode: String,
|
||||||
|
val tsDefinitions: String? = null
|
||||||
|
)
|
||||||
|
|
||||||
fun compile(
|
fun compile(
|
||||||
project: Project,
|
project: Project,
|
||||||
files: List<KtFile>,
|
files: List<KtFile>,
|
||||||
@@ -37,7 +43,7 @@ fun compile(
|
|||||||
friendDependencies: List<KotlinLibrary>,
|
friendDependencies: List<KotlinLibrary>,
|
||||||
mainArguments: List<String>?,
|
mainArguments: List<String>?,
|
||||||
exportedDeclarations: Set<FqName> = emptySet()
|
exportedDeclarations: Set<FqName> = emptySet()
|
||||||
): String {
|
): CompilerResult {
|
||||||
val (moduleFragment, dependencyModules, irBuiltIns, symbolTable, deserializer) =
|
val (moduleFragment, dependencyModules, irBuiltIns, symbolTable, deserializer) =
|
||||||
loadIr(project, files, configuration, allDependencies, friendDependencies)
|
loadIr(project, files, configuration, allDependencies, friendDependencies)
|
||||||
|
|
||||||
@@ -71,9 +77,10 @@ fun compile(
|
|||||||
).generateUnboundSymbolsAsDependencies()
|
).generateUnboundSymbolsAsDependencies()
|
||||||
moduleFragment.patchDeclarationParents()
|
moduleFragment.patchDeclarationParents()
|
||||||
|
|
||||||
|
moveBodilessDeclarationsToSeparatePlace(context, moduleFragment)
|
||||||
|
|
||||||
jsPhases.invokeToplevel(phaseConfig, context, moduleFragment)
|
jsPhases.invokeToplevel(phaseConfig, context, moduleFragment)
|
||||||
|
|
||||||
val jsProgram =
|
val transformer = IrModuleToJsTransformer(context, mainFunction, mainArguments)
|
||||||
moduleFragment.accept(IrModuleToJsTransformer(context, mainFunction, mainArguments), null)
|
return transformer.generateModule(moduleFragment)
|
||||||
return jsProgram.toString()
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.ir.backend.js.export
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
|
||||||
|
sealed class ExportedDeclaration
|
||||||
|
|
||||||
|
data class ExportedModule(
|
||||||
|
val name: String,
|
||||||
|
val declarations: List<ExportedDeclaration>
|
||||||
|
)
|
||||||
|
|
||||||
|
class ExportedNamespace(
|
||||||
|
val name: String,
|
||||||
|
val declarations: List<ExportedDeclaration>
|
||||||
|
) : ExportedDeclaration()
|
||||||
|
|
||||||
|
class ExportedFunction(
|
||||||
|
val name: String,
|
||||||
|
val returnType: ExportedType,
|
||||||
|
val parameters: List<ExportedParameter>,
|
||||||
|
val typeParameters: List<String> = emptyList(),
|
||||||
|
val isMember: Boolean = false,
|
||||||
|
val isStatic: Boolean = false,
|
||||||
|
val isAbstract: Boolean = false,
|
||||||
|
val ir: IrSimpleFunction
|
||||||
|
) : ExportedDeclaration()
|
||||||
|
|
||||||
|
class ExportedConstructor(
|
||||||
|
val parameters: List<ExportedParameter>
|
||||||
|
) : ExportedDeclaration()
|
||||||
|
|
||||||
|
class ExportedProperty(
|
||||||
|
val name: String,
|
||||||
|
val type: ExportedType,
|
||||||
|
val mutable: Boolean,
|
||||||
|
val isMember: Boolean = false,
|
||||||
|
val isStatic: Boolean = false,
|
||||||
|
val isAbstract: Boolean,
|
||||||
|
val ir: IrProperty
|
||||||
|
) : ExportedDeclaration()
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: Cover all cases with frontend and disable error declarations
|
||||||
|
class ErrorDeclaration(val message: String) : ExportedDeclaration()
|
||||||
|
|
||||||
|
class ExportedClass(
|
||||||
|
val name: String,
|
||||||
|
val isInterface: Boolean = false,
|
||||||
|
val isAbstract: Boolean = false,
|
||||||
|
val superClass: ExportedType? = null,
|
||||||
|
val superInterfaces: List<ExportedType> = emptyList(),
|
||||||
|
val typeParameters: List<String>,
|
||||||
|
val members: List<ExportedDeclaration>,
|
||||||
|
val statics: List<ExportedDeclaration>,
|
||||||
|
val ir: IrClass
|
||||||
|
) : ExportedDeclaration()
|
||||||
|
|
||||||
|
class ExportedParameter(
|
||||||
|
val name: String,
|
||||||
|
val type: ExportedType
|
||||||
|
)
|
||||||
|
|
||||||
|
sealed class ExportedType {
|
||||||
|
sealed class Primitive(val typescript: kotlin.String) : ExportedType() {
|
||||||
|
object Boolean : Primitive("boolean")
|
||||||
|
object Number : Primitive("number")
|
||||||
|
object ByteArray : Primitive("Int8Array")
|
||||||
|
object ShortArray : Primitive("Int16Array")
|
||||||
|
object IntArray : Primitive("Int32Array")
|
||||||
|
object FloatArray : Primitive("Float32Array")
|
||||||
|
object DoubleArray : Primitive("Float64Array")
|
||||||
|
object String : Primitive("string")
|
||||||
|
object Throwable : Primitive("Error")
|
||||||
|
object Any : Primitive("any")
|
||||||
|
object Unit : Primitive("void")
|
||||||
|
object Nothing : Primitive("never")
|
||||||
|
}
|
||||||
|
|
||||||
|
class Array(val elementType: ExportedType) : ExportedType()
|
||||||
|
class Function(
|
||||||
|
val parameterTypes: List<ExportedType>,
|
||||||
|
val returnType: ExportedType
|
||||||
|
) : ExportedType()
|
||||||
|
|
||||||
|
class ClassType(val name: String, val arguments: List<ExportedType>) : ExportedType()
|
||||||
|
class TypeParameter(val name: String) : ExportedType()
|
||||||
|
class Nullable(val baseType: ExportedType) : ExportedType()
|
||||||
|
class ErrorType(val comment: String) : ExportedType()
|
||||||
|
|
||||||
|
fun withNullability(nullable: Boolean) =
|
||||||
|
if (nullable) Nullable(this) else this
|
||||||
|
}
|
||||||
+408
@@ -0,0 +1,408 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.ir.backend.js.export
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.ir.isExpect
|
||||||
|
import org.jetbrains.kotlin.backend.common.ir.isMethodOfAny
|
||||||
|
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.*
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.utils.getJsNameOrKotlinName
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.utils.isJsExport
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.utils.sanitizeName
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||||
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
|
|
||||||
|
class ExportModelGenerator(val context: JsIrBackendContext) {
|
||||||
|
|
||||||
|
private fun generateExport(file: IrPackageFragment): List<ExportedDeclaration> {
|
||||||
|
val namespaceFqName = file.fqName
|
||||||
|
val exports = file.declarations.flatMap { declaration -> listOfNotNull(exportDeclaration(declaration)) }
|
||||||
|
return when {
|
||||||
|
exports.isEmpty() -> emptyList()
|
||||||
|
namespaceFqName.isRoot -> exports
|
||||||
|
else -> listOf(ExportedNamespace(namespaceFqName.toString(), exports))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun generateExport(module: IrModuleFragment): ExportedModule =
|
||||||
|
ExportedModule(
|
||||||
|
sanitizeName(context.configuration[CommonConfigurationKeys.MODULE_NAME]!!),
|
||||||
|
(context.externalPackageFragment.values + module.files).flatMap {
|
||||||
|
generateExport(it)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun getExportCandidate(declaration: IrDeclaration): IrDeclarationWithName? {
|
||||||
|
// Only actual public declarations with name can be exported
|
||||||
|
if (declaration !is IrDeclarationWithVisibility ||
|
||||||
|
declaration !is IrDeclarationWithName ||
|
||||||
|
declaration.visibility != Visibilities.PUBLIC ||
|
||||||
|
declaration.isExpect
|
||||||
|
) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
// Workaround to get property declarations instead of its lowered accessors.
|
||||||
|
if (declaration is IrSimpleFunction) {
|
||||||
|
val property = declaration.correspondingPropertySymbol?.owner
|
||||||
|
if (property != null) {
|
||||||
|
// Return property for getter accessors only to prevent
|
||||||
|
// returning it twice (for getter and setter) in the same scope
|
||||||
|
return if (property.getter == declaration)
|
||||||
|
property
|
||||||
|
else
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return declaration
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun exportDeclaration(declaration: IrDeclaration): ExportedDeclaration? {
|
||||||
|
val candidate = getExportCandidate(declaration) ?: return null
|
||||||
|
if (!shouldDeclarationBeExported(candidate)) return null
|
||||||
|
|
||||||
|
return when (candidate) {
|
||||||
|
is IrSimpleFunction -> exportFunction(candidate)
|
||||||
|
is IrProperty -> exportProperty(candidate)
|
||||||
|
is IrClass -> exportClass(candidate)
|
||||||
|
is IrField -> null
|
||||||
|
else -> error("Can't export declaration $candidate")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun exportFunction(function: IrSimpleFunction): ExportedDeclaration? =
|
||||||
|
when (val exportability = functionExportability(function)) {
|
||||||
|
is Exportability.NotNeeded -> null
|
||||||
|
is Exportability.Prohibited -> ErrorDeclaration(exportability.reason)
|
||||||
|
is Exportability.Allowed -> {
|
||||||
|
val parent = function.parent
|
||||||
|
ExportedFunction(
|
||||||
|
function.getExportedIdentifier(),
|
||||||
|
returnType = exportType(function.returnType),
|
||||||
|
parameters = (listOfNotNull(function.extensionReceiverParameter) + function.valueParameters).map { exportParameter(it) },
|
||||||
|
typeParameters = function.typeParameters.map { it.name.identifier },
|
||||||
|
isMember = parent is IrClass,
|
||||||
|
isStatic = function.isStaticMethodOfClass,
|
||||||
|
isAbstract = parent is IrClass && !parent.isInterface && function.modality == Modality.ABSTRACT,
|
||||||
|
ir = function
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun exportConstructor(constructor: IrConstructor): ExportedDeclaration? {
|
||||||
|
if (!constructor.isPrimary) return null
|
||||||
|
val allValueParameters = listOfNotNull(constructor.extensionReceiverParameter) + constructor.valueParameters
|
||||||
|
return ExportedConstructor(allValueParameters.map { exportParameter(it) })
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun exportParameter(parameter: IrValueParameter): ExportedParameter {
|
||||||
|
// Parameter names do not matter in d.ts files. They can be renamed as we like
|
||||||
|
var parameterName = sanitizeName(parameter.name.asString())
|
||||||
|
if (parameterName in allReservedWords)
|
||||||
|
parameterName = "_$parameterName"
|
||||||
|
|
||||||
|
return ExportedParameter(parameterName, exportType(parameter.type))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun exportProperty(property: IrProperty): ExportedDeclaration? {
|
||||||
|
for (accessor in listOfNotNull(property.getter, property.setter)) {
|
||||||
|
// TODO: Report a frontend error
|
||||||
|
if (accessor.extensionReceiverParameter != null)
|
||||||
|
return null
|
||||||
|
if (accessor.isFakeOverride) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val parentClass = property.parent as? IrClass
|
||||||
|
|
||||||
|
return ExportedProperty(
|
||||||
|
property.getExportedIdentifier(),
|
||||||
|
exportType(property.getter!!.returnType),
|
||||||
|
mutable = property.isVar,
|
||||||
|
isMember = parentClass != null,
|
||||||
|
isStatic = false,
|
||||||
|
isAbstract = parentClass?.isInterface == false && property.modality == Modality.ABSTRACT,
|
||||||
|
ir = property
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun classExportability(klass: IrClass): Exportability {
|
||||||
|
when (klass.kind) {
|
||||||
|
ClassKind.ANNOTATION_CLASS,
|
||||||
|
ClassKind.ENUM_CLASS,
|
||||||
|
ClassKind.ENUM_ENTRY,
|
||||||
|
ClassKind.OBJECT ->
|
||||||
|
return Exportability.Prohibited("Class ${klass.fqNameWhenAvailable} with kind: ${klass.kind}")
|
||||||
|
|
||||||
|
ClassKind.CLASS,
|
||||||
|
ClassKind.INTERFACE -> {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (klass.isInline)
|
||||||
|
return Exportability.Prohibited("Inline class ${klass.fqNameWhenAvailable}")
|
||||||
|
|
||||||
|
return Exportability.Allowed
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun exportClass(
|
||||||
|
klass: IrClass
|
||||||
|
): ExportedDeclaration? {
|
||||||
|
when (val exportability = classExportability(klass)) {
|
||||||
|
is Exportability.Prohibited -> return ErrorDeclaration(exportability.reason)
|
||||||
|
is Exportability.NotNeeded -> return null
|
||||||
|
}
|
||||||
|
|
||||||
|
val members = mutableListOf<ExportedDeclaration>()
|
||||||
|
val statics = mutableListOf<ExportedDeclaration>()
|
||||||
|
|
||||||
|
for (declaration in klass.declarations) {
|
||||||
|
val candidate = getExportCandidate(declaration) ?: continue
|
||||||
|
if (!shouldDeclarationBeExported(candidate)) continue
|
||||||
|
|
||||||
|
when (candidate) {
|
||||||
|
is IrSimpleFunction ->
|
||||||
|
members.addIfNotNull(exportFunction(candidate))
|
||||||
|
|
||||||
|
is IrConstructor ->
|
||||||
|
members.addIfNotNull(exportConstructor(candidate))
|
||||||
|
|
||||||
|
is IrProperty ->
|
||||||
|
members.addIfNotNull(exportProperty(candidate))
|
||||||
|
|
||||||
|
is IrClass ->
|
||||||
|
statics.addIfNotNull(exportClass(candidate))
|
||||||
|
|
||||||
|
is IrField -> {
|
||||||
|
assert(candidate.correspondingPropertySymbol != null) {
|
||||||
|
"Properties without fields are not supported ${candidate.fqNameWhenAvailable}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> error("Can't export member declaration $declaration")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val typeParameters = klass.typeParameters.map { it.name.identifier }
|
||||||
|
|
||||||
|
// TODO: Handle non-exported super types
|
||||||
|
|
||||||
|
val superType = klass.superTypes
|
||||||
|
.firstOrNull { !it.classifierOrFail.isInterface && !it.isAny() }
|
||||||
|
?.let { exportType(it).takeIf { it !is ExportedType.ErrorType } }
|
||||||
|
|
||||||
|
val superInterfaces = klass.superTypes
|
||||||
|
.filter {it.classifierOrFail.isInterface }
|
||||||
|
.map { exportType(it) }
|
||||||
|
.filter { it !is ExportedType.ErrorType }
|
||||||
|
|
||||||
|
val name = klass.getExportedIdentifier()
|
||||||
|
|
||||||
|
return ExportedClass(
|
||||||
|
name = name,
|
||||||
|
isInterface = klass.isInterface,
|
||||||
|
isAbstract = klass.modality == Modality.ABSTRACT,
|
||||||
|
superClass = superType,
|
||||||
|
superInterfaces = superInterfaces,
|
||||||
|
typeParameters = typeParameters,
|
||||||
|
members = members,
|
||||||
|
statics = statics,
|
||||||
|
ir = klass
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun exportTypeArgument(type: IrTypeArgument): ExportedType {
|
||||||
|
if (type is IrTypeProjection)
|
||||||
|
return exportType(type.type)
|
||||||
|
|
||||||
|
if (type is IrType)
|
||||||
|
return exportType(type)
|
||||||
|
|
||||||
|
return ExportedType.ErrorType("UnknownType ${type.render()}")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun exportType(type: IrType): ExportedType {
|
||||||
|
if (type is IrDynamicType)
|
||||||
|
return ExportedType.Primitive.Any
|
||||||
|
|
||||||
|
if (type !is IrSimpleType)
|
||||||
|
return ExportedType.ErrorType("NonSimpleType ${type.render()}")
|
||||||
|
|
||||||
|
val classifier = type.classifier
|
||||||
|
val isNullable = type.hasQuestionMark
|
||||||
|
val nonNullType = type.makeNotNull() as IrSimpleType
|
||||||
|
|
||||||
|
val exportedType = when {
|
||||||
|
nonNullType.isBoolean() -> ExportedType.Primitive.Boolean
|
||||||
|
nonNullType.isPrimitiveType() && (!nonNullType.isLong() && !nonNullType.isChar()) ->
|
||||||
|
ExportedType.Primitive.Number
|
||||||
|
|
||||||
|
nonNullType.isByteArray() -> ExportedType.Primitive.ByteArray
|
||||||
|
nonNullType.isShortArray() -> ExportedType.Primitive.ShortArray
|
||||||
|
nonNullType.isIntArray() -> ExportedType.Primitive.IntArray
|
||||||
|
nonNullType.isFloatArray() -> ExportedType.Primitive.FloatArray
|
||||||
|
nonNullType.isDoubleArray() -> ExportedType.Primitive.DoubleArray
|
||||||
|
|
||||||
|
// TODO: Cover these in frontend
|
||||||
|
nonNullType.isBooleanArray() -> ExportedType.ErrorType("BooleanArray")
|
||||||
|
nonNullType.isLongArray() -> ExportedType.ErrorType("LongArray")
|
||||||
|
nonNullType.isCharArray() -> ExportedType.ErrorType("CharArray")
|
||||||
|
|
||||||
|
nonNullType.isString() -> ExportedType.Primitive.String
|
||||||
|
nonNullType.isThrowable() -> ExportedType.Primitive.Throwable
|
||||||
|
nonNullType.isAny() -> ExportedType.Primitive.Any // TODO: Should we wrap Any in a Nullable type?
|
||||||
|
nonNullType.isUnit() -> ExportedType.Primitive.Unit
|
||||||
|
nonNullType.isNothing() -> ExportedType.Primitive.Nothing
|
||||||
|
nonNullType.isArray() -> ExportedType.Array(exportTypeArgument(nonNullType.arguments[0]))
|
||||||
|
nonNullType.isSuspendFunction() -> ExportedType.ErrorType("Suspend functions are not supported")
|
||||||
|
nonNullType.isFunction() -> ExportedType.Function(
|
||||||
|
parameterTypes = nonNullType.arguments.dropLast(1).map { exportTypeArgument(it) },
|
||||||
|
returnType = exportTypeArgument(nonNullType.arguments.last())
|
||||||
|
)
|
||||||
|
|
||||||
|
classifier is IrTypeParameterSymbol -> ExportedType.TypeParameter(classifier.owner.name.identifier)
|
||||||
|
|
||||||
|
classifier is IrClassSymbol -> {
|
||||||
|
val klass = classifier.owner
|
||||||
|
when (val exportability = classExportability(klass)) {
|
||||||
|
is Exportability.Prohibited -> ExportedType.ErrorType(exportability.reason)
|
||||||
|
is Exportability.NotNeeded -> error("Not needed classes types cannot be used")
|
||||||
|
else -> ExportedType.ClassType(
|
||||||
|
klass.fqNameWhenAvailable!!.asString(),
|
||||||
|
type.arguments.map { exportTypeArgument(it) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> error("Unexpected classifier $classifier")
|
||||||
|
}
|
||||||
|
|
||||||
|
return exportedType.withNullability(isNullable)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrDeclarationWithName.getExportedIdentifier(): String =
|
||||||
|
with(getJsNameOrKotlinName()) {
|
||||||
|
if (isSpecial)
|
||||||
|
error("Cannot export special name: ${name.asString()} for declaration $fqNameWhenAvailable")
|
||||||
|
else identifier
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun shouldDeclarationBeExported(declaration: IrDeclarationWithName): Boolean {
|
||||||
|
if (declaration.fqNameWhenAvailable in context.additionalExportedDeclarations)
|
||||||
|
return true
|
||||||
|
|
||||||
|
if (declaration.isJsExport())
|
||||||
|
return true
|
||||||
|
|
||||||
|
return when (val parent = declaration.parent) {
|
||||||
|
is IrDeclarationWithName -> shouldDeclarationBeExported(parent)
|
||||||
|
is IrAnnotationContainer -> parent.isJsExport()
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun functionExportability(function: IrSimpleFunction): Exportability {
|
||||||
|
if (function.isInline && function.typeParameters.any { it.isReified })
|
||||||
|
return Exportability.Prohibited("Inline reified function")
|
||||||
|
if (function.isSuspend)
|
||||||
|
return Exportability.Prohibited("Suspend function")
|
||||||
|
if (function.isFakeOverride)
|
||||||
|
return Exportability.NotNeeded
|
||||||
|
if (function.origin == IrDeclarationOrigin.BRIDGE ||
|
||||||
|
function.origin == JsLoweredDeclarationOrigin.BRIDGE_TO_EXTERNAL_FUNCTION ||
|
||||||
|
function.origin == IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER
|
||||||
|
) {
|
||||||
|
return Exportability.NotNeeded
|
||||||
|
}
|
||||||
|
|
||||||
|
if (function.isFakeOverriddenFromAny())
|
||||||
|
return Exportability.NotNeeded
|
||||||
|
if (function.name.asString().endsWith("-impl"))
|
||||||
|
return Exportability.NotNeeded
|
||||||
|
|
||||||
|
val name = function.getExportedIdentifier()
|
||||||
|
// TODO: Use [] syntax instead of prohibiting
|
||||||
|
if (name in allReservedWords)
|
||||||
|
return Exportability.Prohibited("Name is a reserved word")
|
||||||
|
|
||||||
|
return Exportability.Allowed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class Exportability {
|
||||||
|
object Allowed : Exportability()
|
||||||
|
object NotNeeded : Exportability()
|
||||||
|
class Prohibited(val reason: String) : Exportability()
|
||||||
|
}
|
||||||
|
|
||||||
|
private val IrClassifierSymbol.isInterface
|
||||||
|
get() = (owner as? IrClass)?.isInterface == true
|
||||||
|
|
||||||
|
private val reservedWords = setOf(
|
||||||
|
"break",
|
||||||
|
"case",
|
||||||
|
"catch",
|
||||||
|
"class",
|
||||||
|
"const",
|
||||||
|
"continue",
|
||||||
|
"debugger",
|
||||||
|
"default",
|
||||||
|
"delete",
|
||||||
|
"do",
|
||||||
|
"else",
|
||||||
|
"enum",
|
||||||
|
"export",
|
||||||
|
"extends",
|
||||||
|
"false",
|
||||||
|
"finally",
|
||||||
|
"for",
|
||||||
|
"function",
|
||||||
|
"if",
|
||||||
|
"import",
|
||||||
|
"in",
|
||||||
|
"instanceof",
|
||||||
|
"new",
|
||||||
|
"null",
|
||||||
|
"return",
|
||||||
|
"super",
|
||||||
|
"switch",
|
||||||
|
"this",
|
||||||
|
"throw",
|
||||||
|
"true",
|
||||||
|
"try",
|
||||||
|
"typeof",
|
||||||
|
"var",
|
||||||
|
"void",
|
||||||
|
"while",
|
||||||
|
"with"
|
||||||
|
)
|
||||||
|
|
||||||
|
val strictModeReservedWords = setOf(
|
||||||
|
"as",
|
||||||
|
"implements",
|
||||||
|
"interface",
|
||||||
|
"let",
|
||||||
|
"package",
|
||||||
|
"private",
|
||||||
|
"protected",
|
||||||
|
"public",
|
||||||
|
"static",
|
||||||
|
"yield"
|
||||||
|
)
|
||||||
|
|
||||||
|
private val allReservedWords = reservedWords + strictModeReservedWords
|
||||||
+93
@@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.ir.backend.js.export
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.JsAstUtils
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.defineProperty
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.jsAssignment
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.utils.*
|
||||||
|
import org.jetbrains.kotlin.js.backend.ast.*
|
||||||
|
|
||||||
|
|
||||||
|
class ExportModelToJsStatements(
|
||||||
|
private val internalModuleName: JsName,
|
||||||
|
private val nameTables: NameTables
|
||||||
|
) {
|
||||||
|
private val namespaceToRefMap = mutableMapOf<String, JsNameRef>()
|
||||||
|
private val globalNames = NameTable<String>(nameTables.globalNames)
|
||||||
|
|
||||||
|
fun generateModuleExport(module: ExportedModule): List<JsStatement> {
|
||||||
|
return module.declarations.flatMap { generateDeclarationExport(it, JsNameRef(internalModuleName)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateDeclarationExport(declaration: ExportedDeclaration, namespace: JsNameRef): List<JsStatement> {
|
||||||
|
return when (declaration) {
|
||||||
|
is ExportedNamespace -> {
|
||||||
|
val statements = mutableListOf<JsStatement>()
|
||||||
|
val elements = declaration.name.split(".")
|
||||||
|
var currentNamespace = ""
|
||||||
|
var currentRef = namespace
|
||||||
|
for (element in elements) {
|
||||||
|
val newNamespace = "$currentNamespace$$element"
|
||||||
|
val newNameSpaceRef = namespaceToRefMap.getOrPut(newNamespace) {
|
||||||
|
val varName = globalNames.declareFreshName(newNamespace, newNamespace)
|
||||||
|
val varRef = JsNameRef(varName)
|
||||||
|
val namespaceRef = JsNameRef(element, currentRef)
|
||||||
|
statements += JsVars(
|
||||||
|
JsVars.JsVar(JsName(varName),
|
||||||
|
JsAstUtils.or(
|
||||||
|
namespaceRef,
|
||||||
|
jsAssignment(
|
||||||
|
namespaceRef,
|
||||||
|
JsObjectLiteral()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
varRef
|
||||||
|
}
|
||||||
|
currentRef = newNameSpaceRef
|
||||||
|
currentNamespace = newNamespace
|
||||||
|
}
|
||||||
|
statements + declaration.declarations.flatMap { generateDeclarationExport(it, currentRef) }
|
||||||
|
}
|
||||||
|
|
||||||
|
is ExportedFunction -> {
|
||||||
|
listOf(
|
||||||
|
jsAssignment(
|
||||||
|
JsNameRef(declaration.name, namespace),
|
||||||
|
JsNameRef(nameTables.getNameForStaticDeclaration(declaration.ir))
|
||||||
|
).makeStmt()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
is ExportedConstructor -> emptyList()
|
||||||
|
|
||||||
|
is ExportedProperty -> {
|
||||||
|
val getter = declaration.ir.getter?.let { JsNameRef(nameTables.getNameForStaticDeclaration(it)) }
|
||||||
|
val setter = declaration.ir.setter?.let { JsNameRef(nameTables.getNameForStaticDeclaration(it)) }
|
||||||
|
listOf(defineProperty(namespace, declaration.name, getter, setter).makeStmt())
|
||||||
|
}
|
||||||
|
|
||||||
|
is ErrorDeclaration -> emptyList()
|
||||||
|
|
||||||
|
is ExportedClass -> {
|
||||||
|
if (declaration.isInterface) return emptyList()
|
||||||
|
val newNameSpace = JsNameRef(declaration.name, namespace)
|
||||||
|
val klassExport = jsAssignment(
|
||||||
|
newNameSpace,
|
||||||
|
JsNameRef(
|
||||||
|
nameTables.getNameForStaticDeclaration(
|
||||||
|
declaration.ir
|
||||||
|
)
|
||||||
|
)
|
||||||
|
).makeStmt()
|
||||||
|
val staticsExport = declaration.statics.flatMap { generateDeclarationExport(it, newNameSpace) }
|
||||||
|
listOf(klassExport) + staticsExport
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+101
@@ -0,0 +1,101 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.ir.backend.js.export
|
||||||
|
|
||||||
|
// TODO: Support module kinds other than plain
|
||||||
|
|
||||||
|
fun ExportedModule.toTypeScript(): String {
|
||||||
|
val prefix = " type Nullable<T> = T | null | undefined\n"
|
||||||
|
val body = declarations.joinToString("\n") { it.toTypeScript(" ") }
|
||||||
|
return "declare namespace $name {\n$prefix$body\n}\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun List<ExportedDeclaration>.toTypeScript(indent: String): String =
|
||||||
|
joinToString("") { it.toTypeScript(indent) + "\n" }
|
||||||
|
|
||||||
|
fun ExportedDeclaration.toTypeScript(indent: String): String = indent + when (this) {
|
||||||
|
is ErrorDeclaration -> "/* ErrorDeclaration: $message */"
|
||||||
|
|
||||||
|
is ExportedNamespace ->
|
||||||
|
"namespace $name {\n" + declarations.toTypeScript("$indent ") + "$indent}"
|
||||||
|
|
||||||
|
is ExportedFunction -> {
|
||||||
|
val keyword: String = when {
|
||||||
|
isMember -> when {
|
||||||
|
isStatic -> "static "
|
||||||
|
isAbstract -> "abstract "
|
||||||
|
else -> ""
|
||||||
|
}
|
||||||
|
else -> "function "
|
||||||
|
}
|
||||||
|
|
||||||
|
val renderedParameters = parameters.joinToString(", ") { it.toTypeScript() }
|
||||||
|
|
||||||
|
val renderedTypeParameters =
|
||||||
|
if (typeParameters.isNotEmpty())
|
||||||
|
"<" + typeParameters.joinToString(", ") + ">"
|
||||||
|
else
|
||||||
|
""
|
||||||
|
|
||||||
|
val renderedReturnType = returnType.toTypeScript()
|
||||||
|
|
||||||
|
"$keyword$name$renderedTypeParameters($renderedParameters): $renderedReturnType"
|
||||||
|
}
|
||||||
|
is ExportedConstructor ->
|
||||||
|
"constructor(${parameters.joinToString(", ") { it.toTypeScript() }})"
|
||||||
|
|
||||||
|
is ExportedProperty -> {
|
||||||
|
val keyword = when {
|
||||||
|
isMember -> (if (isAbstract) "abstract " else "") + (if (!mutable) "readonly " else "")
|
||||||
|
else -> if (mutable) "let " else "const "
|
||||||
|
}
|
||||||
|
keyword + name + ": " + type.toTypeScript() + ";"
|
||||||
|
}
|
||||||
|
|
||||||
|
is ExportedClass -> {
|
||||||
|
val keyword = if (isInterface) "interface" else "class"
|
||||||
|
val superInterfacesKeyword = if (isInterface) "extends" else "implements"
|
||||||
|
|
||||||
|
val superClassClause = superClass?.let { " extends ${it.toTypeScript()}" } ?: ""
|
||||||
|
val superInterfacesClause = if (superInterfaces.isNotEmpty()) {
|
||||||
|
" $superInterfacesKeyword " + superInterfaces.joinToString(", ") { it.toTypeScript() }
|
||||||
|
} else ""
|
||||||
|
|
||||||
|
val membersString = members.joinToString("") { it.toTypeScript("$indent ") + "\n" }
|
||||||
|
|
||||||
|
val renderedTypeParameters =
|
||||||
|
if (typeParameters.isNotEmpty())
|
||||||
|
"<" + typeParameters.joinToString(", ") + ">"
|
||||||
|
else
|
||||||
|
""
|
||||||
|
|
||||||
|
val modifiers = if (isAbstract && !isInterface) "abstract " else ""
|
||||||
|
|
||||||
|
val klassExport = "$modifiers$keyword $name$renderedTypeParameters$superClassClause$superInterfacesClause {\n$membersString$indent}"
|
||||||
|
val staticsExport = if (statics.isNotEmpty()) "\n" + ExportedNamespace(name, statics).toTypeScript(indent) else ""
|
||||||
|
klassExport + staticsExport
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ExportedParameter.toTypeScript(): String =
|
||||||
|
"$name: ${type.toTypeScript()}"
|
||||||
|
|
||||||
|
fun ExportedType.toTypeScript(): String = when (this) {
|
||||||
|
is ExportedType.Primitive -> typescript
|
||||||
|
is ExportedType.Array -> "Array<${elementType.toTypeScript()}>"
|
||||||
|
is ExportedType.Function -> "(" + parameterTypes
|
||||||
|
.withIndex()
|
||||||
|
.joinToString(", ") { (index, type) ->
|
||||||
|
"p$index: ${type.toTypeScript()}"
|
||||||
|
} + ") => " + returnType.toTypeScript()
|
||||||
|
|
||||||
|
is ExportedType.ClassType ->
|
||||||
|
name + if (arguments.isNotEmpty()) "<${arguments.joinToString(", ") { it.toTypeScript() }}>" else ""
|
||||||
|
|
||||||
|
is ExportedType.ErrorType -> "any /*$comment*/"
|
||||||
|
is ExportedType.TypeParameter -> name
|
||||||
|
is ExportedType.Nullable -> "Nullable<" + baseType.toTypeScript() + ">"
|
||||||
|
}
|
||||||
+22
-5
@@ -12,7 +12,9 @@ import org.jetbrains.kotlin.ir.backend.js.utils.getJsModule
|
|||||||
import org.jetbrains.kotlin.ir.backend.js.utils.getJsQualifier
|
import org.jetbrains.kotlin.ir.backend.js.utils.getJsQualifier
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrExternalPackageFragmentSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrExternalPackageFragmentSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrFileSymbol
|
||||||
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
||||||
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
|
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
|
||||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||||
@@ -54,6 +56,22 @@ private class DescriptorlessExternalPackageFragmentSymbol : IrExternalPackageFra
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class DescriptorlessIrFileSymbol : IrFileSymbol {
|
||||||
|
override fun bind(owner: IrFile) {
|
||||||
|
_owner = owner
|
||||||
|
}
|
||||||
|
|
||||||
|
override val descriptor: PackageFragmentDescriptor
|
||||||
|
get() = error("Operation is unsupported")
|
||||||
|
|
||||||
|
private var _owner: IrFile? = null
|
||||||
|
override val owner get() = _owner!!
|
||||||
|
|
||||||
|
override val isBound get() = _owner != null
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fun moveBodilessDeclarationsToSeparatePlace(context: JsIrBackendContext, module: IrModuleFragment) {
|
fun moveBodilessDeclarationsToSeparatePlace(context: JsIrBackendContext, module: IrModuleFragment) {
|
||||||
|
|
||||||
val bodilessBuiltInsPackageFragment = IrExternalPackageFragmentImpl(
|
val bodilessBuiltInsPackageFragment = IrExternalPackageFragmentImpl(
|
||||||
@@ -81,11 +99,10 @@ fun moveBodilessDeclarationsToSeparatePlace(context: JsIrBackendContext, module:
|
|||||||
|
|
||||||
fun lowerFile(irFile: IrFile): IrFile? {
|
fun lowerFile(irFile: IrFile): IrFile? {
|
||||||
val externalPackageFragment by lazy {
|
val externalPackageFragment by lazy {
|
||||||
context.externalPackageFragment.getOrPut(irFile.fqName) {
|
context.externalPackageFragment.getOrPut(irFile.symbol) {
|
||||||
IrExternalPackageFragmentImpl(
|
IrFileImpl(fileEntry = irFile.fileEntry, fqName = irFile.fqName, symbol = DescriptorlessIrFileSymbol()).also {
|
||||||
DescriptorlessExternalPackageFragmentSymbol(),
|
it.annotations += irFile.annotations
|
||||||
irFile.fqName
|
}
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+20
-100
@@ -6,30 +6,32 @@
|
|||||||
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
|
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
|
||||||
|
|
||||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.ir.backend.js.CompilerResult
|
||||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.export.ExportModelGenerator
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.export.ExportModelToJsStatements
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.lower.StaticMembersLowering
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.export.toTypeScript
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.*
|
import org.jetbrains.kotlin.ir.backend.js.utils.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.path
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
|
||||||
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
|
|
||||||
import org.jetbrains.kotlin.ir.util.isObject
|
|
||||||
import org.jetbrains.kotlin.js.backend.ast.*
|
import org.jetbrains.kotlin.js.backend.ast.*
|
||||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||||
import org.jetbrains.kotlin.utils.DFS
|
import org.jetbrains.kotlin.utils.DFS
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
|
||||||
|
|
||||||
class IrModuleToJsTransformer(
|
class IrModuleToJsTransformer(
|
||||||
private val backendContext: JsIrBackendContext,
|
private val backendContext: JsIrBackendContext,
|
||||||
private val mainFunction: IrSimpleFunction?,
|
private val mainFunction: IrSimpleFunction?,
|
||||||
private val mainArguments: List<String>?
|
private val mainArguments: List<String>?
|
||||||
) : BaseIrElementToJsNodeTransformer<JsNode, Nothing?> {
|
) {
|
||||||
|
|
||||||
val moduleName = backendContext.configuration[CommonConfigurationKeys.MODULE_NAME]!!
|
val moduleName = backendContext.configuration[CommonConfigurationKeys.MODULE_NAME]!!
|
||||||
private val moduleKind = backendContext.configuration[JSConfigurationKeys.MODULE_KIND]!!
|
private val moduleKind = backendContext.configuration[JSConfigurationKeys.MODULE_KIND]!!
|
||||||
|
|
||||||
private fun generateModuleBody(module: IrModuleFragment, context: JsGenerationContext): List<JsStatement> {
|
private fun generateModuleBody(module: IrModuleFragment, context: JsGenerationContext): List<JsStatement> {
|
||||||
val statements = mutableListOf<JsStatement>(
|
val statements = mutableListOf(
|
||||||
JsStringLiteral("use strict").makeStmt()
|
JsStringLiteral("use strict").makeStmt()
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -56,68 +58,7 @@ class IrModuleToJsTransformer(
|
|||||||
return statements
|
return statements
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateExportStatements(
|
fun generateModule(module: IrModuleFragment): CompilerResult {
|
||||||
module: IrModuleFragment,
|
|
||||||
context: JsGenerationContext,
|
|
||||||
internalModuleName: JsName
|
|
||||||
): List<JsStatement> {
|
|
||||||
val exports = mutableListOf<JsExpressionStatement>()
|
|
||||||
|
|
||||||
for (file in module.files) {
|
|
||||||
for (declaration in file.declarations) {
|
|
||||||
exports.addIfNotNull(
|
|
||||||
generateExportStatement(declaration, context, internalModuleName)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return exports
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun generateExportStatement(
|
|
||||||
declaration: IrDeclaration,
|
|
||||||
context: JsGenerationContext,
|
|
||||||
internalModuleName: JsName
|
|
||||||
): JsExpressionStatement? {
|
|
||||||
if (declaration !is IrDeclarationWithVisibility ||
|
|
||||||
declaration !is IrDeclarationWithName ||
|
|
||||||
declaration.visibility != Visibilities.PUBLIC) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!declaration.isExported())
|
|
||||||
return null
|
|
||||||
|
|
||||||
if (declaration.isEffectivelyExternal())
|
|
||||||
return null
|
|
||||||
|
|
||||||
if (declaration is IrClass && declaration.isCompanion)
|
|
||||||
return null
|
|
||||||
|
|
||||||
val name: JsName = when (declaration) {
|
|
||||||
is IrSimpleFunction -> context.getNameForStaticFunction(declaration)
|
|
||||||
is IrClass -> context.getNameForClass(declaration)
|
|
||||||
// TODO: Fields must be exported as properties
|
|
||||||
is IrField -> context.getNameForField(declaration)
|
|
||||||
else -> return null
|
|
||||||
}
|
|
||||||
|
|
||||||
val exportName = sanitizeName(declaration.getJsNameOrKotlinName().asString())
|
|
||||||
|
|
||||||
val expression =
|
|
||||||
if (declaration is IrClass && declaration.isObject) {
|
|
||||||
// TODO: Use export names for properties
|
|
||||||
val instanceGetter = backendContext.objectToGetInstanceFunction[declaration.symbol]!!
|
|
||||||
val instanceGetterName: JsName = context.getNameForStaticFunction(instanceGetter)
|
|
||||||
defineProperty(internalModuleName.makeRef(), name.ident, getter = JsNameRef(instanceGetterName))
|
|
||||||
} else {
|
|
||||||
jsAssignment(JsNameRef(exportName, internalModuleName.makeRef()), name.makeRef())
|
|
||||||
}
|
|
||||||
|
|
||||||
return JsExpressionStatement(expression)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun generateModule(module: IrModuleFragment): JsProgram {
|
|
||||||
val additionalPackages = with(backendContext) {
|
val additionalPackages = with(backendContext) {
|
||||||
externalPackageFragment.values + listOf(
|
externalPackageFragment.values + listOf(
|
||||||
bodilessBuiltInsPackageFragment,
|
bodilessBuiltInsPackageFragment,
|
||||||
@@ -125,6 +66,11 @@ class IrModuleToJsTransformer(
|
|||||||
) + packageLevelJsModules
|
) + packageLevelJsModules
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val exportedModule = ExportModelGenerator(backendContext).generateExport(module)
|
||||||
|
val dts = exportedModule.toTypeScript()
|
||||||
|
|
||||||
|
module.files.forEach { StaticMembersLowering(backendContext).lower(it) }
|
||||||
|
|
||||||
val namer = NameTables(module.files + additionalPackages)
|
val namer = NameTables(module.files + additionalPackages)
|
||||||
|
|
||||||
val program = JsProgram()
|
val program = JsProgram()
|
||||||
@@ -151,7 +97,8 @@ class IrModuleToJsTransformer(
|
|||||||
)
|
)
|
||||||
|
|
||||||
val moduleBody = generateModuleBody(module, rootContext)
|
val moduleBody = generateModuleBody(module, rootContext)
|
||||||
val exportStatements = generateExportStatements(module, rootContext, internalModuleName)
|
val exportStatements = ExportModelToJsStatements(internalModuleName, namer)
|
||||||
|
.generateModuleExport(exportedModule)
|
||||||
|
|
||||||
with(rootFunction) {
|
with(rootFunction) {
|
||||||
parameters += JsParameter(internalModuleName)
|
parameters += JsParameter(internalModuleName)
|
||||||
@@ -173,7 +120,7 @@ class IrModuleToJsTransformer(
|
|||||||
kind = moduleKind
|
kind = moduleKind
|
||||||
)
|
)
|
||||||
|
|
||||||
return program
|
return CompilerResult(program.toString(), dts)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateMainArguments(mainFunction: IrSimpleFunction, rootContext: JsGenerationContext): List<JsExpression> {
|
private fun generateMainArguments(mainFunction: IrSimpleFunction, rootContext: JsGenerationContext): List<JsExpression> {
|
||||||
@@ -247,9 +194,6 @@ class IrModuleToJsTransformer(
|
|||||||
return Pair(importStatements, importedJsModules)
|
return Pair(importStatements, importedJsModules)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitModuleFragment(declaration: IrModuleFragment, data: Nothing?): JsNode =
|
|
||||||
generateModule(declaration)
|
|
||||||
|
|
||||||
private fun processClassModels(
|
private fun processClassModels(
|
||||||
classModelMap: Map<IrClassSymbol, JsIrClassModel>,
|
classModelMap: Map<IrClassSymbol, JsIrClassModel>,
|
||||||
preDeclarationBlock: JsBlock,
|
preDeclarationBlock: JsBlock,
|
||||||
@@ -271,28 +215,4 @@ class IrModuleToJsTransformer(
|
|||||||
declarationHandler
|
declarationHandler
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun IrDeclarationWithName.isExported(): Boolean {
|
|
||||||
if (fqNameWhenAvailable in backendContext.additionalExportedDeclarations)
|
|
||||||
return true
|
|
||||||
|
|
||||||
// Hack to support properties
|
|
||||||
val correspondingProperty = when {
|
|
||||||
this is IrField -> correspondingPropertySymbol
|
|
||||||
this is IrSimpleFunction -> correspondingPropertySymbol
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
correspondingProperty?.let {
|
|
||||||
return it.owner.isExported()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isJsExport())
|
|
||||||
return true
|
|
||||||
|
|
||||||
return when (val parent = parent) {
|
|
||||||
is IrDeclarationWithName -> parent.isExported()
|
|
||||||
is IrAnnotationContainer -> parent.isJsExport()
|
|
||||||
else -> false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.name.FqName
|
|||||||
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
|
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
|
||||||
|
|
||||||
class NameTable<T>(
|
class NameTable<T>(
|
||||||
val parent: NameTable<T>? = null,
|
val parent: NameTable<*>? = null,
|
||||||
private val reserved: MutableSet<String> = mutableSetOf(),
|
private val reserved: MutableSet<String> = mutableSetOf(),
|
||||||
val sanitizer: (String) -> String = ::sanitizeName
|
val sanitizer: (String) -> String = ::sanitizeName
|
||||||
) {
|
) {
|
||||||
@@ -135,7 +135,7 @@ fun functionSignature(declaration: IrFunction): Signature {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class NameTables(packages: List<IrPackageFragment>) {
|
class NameTables(packages: List<IrPackageFragment>) {
|
||||||
private val globalNames: NameTable<IrDeclaration>
|
val globalNames: NameTable<IrDeclaration>
|
||||||
private val memberNames: NameTable<Signature>
|
private val memberNames: NameTable<Signature>
|
||||||
private val localNames = mutableMapOf<IrDeclaration, NameTable<IrDeclaration>>()
|
private val localNames = mutableMapOf<IrDeclaration, NameTable<IrDeclaration>>()
|
||||||
private val loopNames = mutableMapOf<IrLoop, String>()
|
private val loopNames = mutableMapOf<IrLoop, String>()
|
||||||
@@ -297,7 +297,7 @@ class NameTables(packages: List<IrPackageFragment>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inner class LocalNameGenerator(parentDeclaration: IrDeclaration) : IrElementVisitorVoid {
|
inner class LocalNameGenerator(parentDeclaration: IrDeclaration) : IrElementVisitorVoid {
|
||||||
val table = NameTable(globalNames)
|
val table = NameTable<IrDeclaration>(globalNames)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
localNames[parentDeclaration] = table
|
localNames[parentDeclaration] = table
|
||||||
@@ -348,4 +348,4 @@ fun sanitizeName(name: String): String {
|
|||||||
|
|
||||||
val first = name.first().let { if (it.isES5IdentifierStart()) it else '_' }
|
val first = name.first().let { if (it.isES5IdentifierStart()) it else '_' }
|
||||||
return first.toString() + name.drop(1).map { if (it.isES5IdentifierPart()) it else '_' }.joinToString("")
|
return first.toString() + name.drop(1).map { if (it.isES5IdentifierPart()) it else '_' }.joinToString("")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.generators.tests
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.generators.tests.generator.testGroup
|
import org.jetbrains.kotlin.generators.tests.generator.testGroup
|
||||||
import org.jetbrains.kotlin.js.test.AbstractDceTest
|
import org.jetbrains.kotlin.js.test.AbstractDceTest
|
||||||
|
import org.jetbrains.kotlin.js.test.AbstractIrJsTypeScriptExportTest
|
||||||
import org.jetbrains.kotlin.js.test.AbstractJsLineNumberTest
|
import org.jetbrains.kotlin.js.test.AbstractJsLineNumberTest
|
||||||
import org.jetbrains.kotlin.js.test.ir.semantics.*
|
import org.jetbrains.kotlin.js.test.ir.semantics.*
|
||||||
import org.jetbrains.kotlin.js.test.semantics.*
|
import org.jetbrains.kotlin.js.test.semantics.*
|
||||||
@@ -28,6 +29,10 @@ fun main(args: Array<String>) {
|
|||||||
model("box/", pattern = "^([^_](.+))\\.kt$", targetBackend = TargetBackend.JS_IR)
|
model("box/", pattern = "^([^_](.+))\\.kt$", targetBackend = TargetBackend.JS_IR)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testClass<AbstractIrJsTypeScriptExportTest> {
|
||||||
|
model("typescript-export/", pattern = "^([^_](.+))\\.kt$", targetBackend = TargetBackend.JS_IR)
|
||||||
|
}
|
||||||
|
|
||||||
testClass<AbstractSourceMapGenerationSmokeTest> {
|
testClass<AbstractSourceMapGenerationSmokeTest> {
|
||||||
model("sourcemap/", pattern = "^([^_](.+))\\.kt$", targetBackend = TargetBackend.JS)
|
model("sourcemap/", pattern = "^([^_](.+))\\.kt$", targetBackend = TargetBackend.JS)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.js.test
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||||
|
import org.jetbrains.kotlin.utils.fileUtils.withReplacedExtensionOrNull
|
||||||
|
import java.io.File
|
||||||
|
import java.lang.Boolean.getBoolean
|
||||||
|
|
||||||
|
@Suppress("ConstantConditionIf")
|
||||||
|
abstract class AbstractIrJsTypeScriptExportTest : BasicIrBoxTest(
|
||||||
|
pathToTestDir = TEST_DATA_DIR_PATH + "typescript-export/",
|
||||||
|
testGroupOutputDirPrefix = "typescript-export/",
|
||||||
|
pathToRootOutputDir = TEST_DATA_DIR_PATH
|
||||||
|
) {
|
||||||
|
override val generateDts = true
|
||||||
|
private val updateReferenceDtsFiles = getBoolean("kotlin.js.updateReferenceDtsFiles")
|
||||||
|
|
||||||
|
override fun performAdditionalChecks(inputFile: File, outputFile: File) {
|
||||||
|
val referenceDtsFile = inputFile.withReplacedExtensionOrNull(".kt", ".d.ts")
|
||||||
|
?: error("Can't find reference .d.ts file")
|
||||||
|
val generatedDtsFile = outputFile.withReplacedExtensionOrNull("_v5", ".d.ts")
|
||||||
|
?: error("Can't find generated .d.ts file")
|
||||||
|
|
||||||
|
val generatedDts = generatedDtsFile.readText()
|
||||||
|
|
||||||
|
if (updateReferenceDtsFiles)
|
||||||
|
referenceDtsFile.writeText(generatedDts)
|
||||||
|
else
|
||||||
|
KotlinTestUtils.assertEqualsToFile(referenceDtsFile, generatedDts)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.cli.common.output.writeAllTo
|
|||||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||||
import org.jetbrains.kotlin.config.*
|
import org.jetbrains.kotlin.config.*
|
||||||
import org.jetbrains.kotlin.daemon.common.PackageMetadata
|
|
||||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||||
import org.jetbrains.kotlin.incremental.js.IncrementalDataProviderImpl
|
import org.jetbrains.kotlin.incremental.js.IncrementalDataProviderImpl
|
||||||
import org.jetbrains.kotlin.incremental.js.IncrementalResultsConsumerImpl
|
import org.jetbrains.kotlin.incremental.js.IncrementalResultsConsumerImpl
|
||||||
@@ -49,7 +48,6 @@ import org.jetbrains.kotlin.js.test.interop.ScriptEngineV8Lazy
|
|||||||
import org.jetbrains.kotlin.js.test.utils.*
|
import org.jetbrains.kotlin.js.test.utils.*
|
||||||
import org.jetbrains.kotlin.js.util.TextOutputImpl
|
import org.jetbrains.kotlin.js.util.TextOutputImpl
|
||||||
import org.jetbrains.kotlin.metadata.DebugProtoBuf
|
import org.jetbrains.kotlin.metadata.DebugProtoBuf
|
||||||
import org.jetbrains.kotlin.name.FqName
|
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||||
@@ -200,8 +198,14 @@ abstract class BasicBoxTest(
|
|||||||
additionalFiles += additionalJsFile
|
additionalFiles += additionalJsFile
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val additionalMainFiles = mutableListOf<String>()
|
||||||
|
val additionalMainJsFile = filePath.removeSuffix("." + KotlinFileType.EXTENSION) + "__main.js"
|
||||||
|
if (File(additionalMainJsFile).exists()) {
|
||||||
|
additionalMainFiles += additionalMainJsFile
|
||||||
|
}
|
||||||
|
|
||||||
val allJsFiles = additionalFiles + inputJsFiles + generatedJsFiles.map { it.first } + globalCommonFiles + localCommonFiles +
|
val allJsFiles = additionalFiles + inputJsFiles + generatedJsFiles.map { it.first } + globalCommonFiles + localCommonFiles +
|
||||||
additionalCommonFiles
|
additionalCommonFiles + additionalMainFiles
|
||||||
|
|
||||||
val dontRunGeneratedCode = InTextDirectivesUtils.dontRunGeneratedCode(targetBackend, file)
|
val dontRunGeneratedCode = InTextDirectivesUtils.dontRunGeneratedCode(targetBackend, file)
|
||||||
|
|
||||||
@@ -217,7 +221,7 @@ abstract class BasicBoxTest(
|
|||||||
}
|
}
|
||||||
|
|
||||||
performAdditionalChecks(generatedJsFiles.map { it.first }, outputPrefixFile, outputPostfixFile)
|
performAdditionalChecks(generatedJsFiles.map { it.first }, outputPrefixFile, outputPostfixFile)
|
||||||
|
performAdditionalChecks(file, File(mainModule.outputFileName(outputDir)))
|
||||||
val expectedReachableNodesMatcher = EXPECTED_REACHABLE_NODES.matcher(fileContent)
|
val expectedReachableNodesMatcher = EXPECTED_REACHABLE_NODES.matcher(fileContent)
|
||||||
val expectedReachableNodesFound = expectedReachableNodesMatcher.find()
|
val expectedReachableNodesFound = expectedReachableNodesMatcher.find()
|
||||||
|
|
||||||
@@ -277,6 +281,7 @@ abstract class BasicBoxTest(
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected open fun performAdditionalChecks(generatedJsFiles: List<String>, outputPrefixFile: File?, outputPostfixFile: File?) {}
|
protected open fun performAdditionalChecks(generatedJsFiles: List<String>, outputPrefixFile: File?, outputPostfixFile: File?) {}
|
||||||
|
protected open fun performAdditionalChecks(inputFile: File, outputFile: File) {}
|
||||||
|
|
||||||
private fun generateNodeRunner(
|
private fun generateNodeRunner(
|
||||||
files: Collection<String>,
|
files: Collection<String>,
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ import org.jetbrains.kotlin.js.facade.MainCallParameters
|
|||||||
import org.jetbrains.kotlin.js.facade.TranslationUnit
|
import org.jetbrains.kotlin.js.facade.TranslationUnit
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.test.TargetBackend
|
import org.jetbrains.kotlin.test.TargetBackend
|
||||||
|
import org.jetbrains.kotlin.utils.fileUtils.withReplacedExtensionOrNull
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.lang.Boolean.getBoolean
|
||||||
|
|
||||||
private val fullRuntimeKlib = loadKlib("compiler/ir/serialization.js/build/fullRuntime/klib")
|
private val fullRuntimeKlib = loadKlib("compiler/ir/serialization.js/build/fullRuntime/klib")
|
||||||
private val defaultRuntimeKlib = loadKlib("compiler/ir/serialization.js/build/reducedRuntime/klib")
|
private val defaultRuntimeKlib = loadKlib("compiler/ir/serialization.js/build/reducedRuntime/klib")
|
||||||
@@ -26,7 +28,7 @@ private val kotlinTestKLib = loadKlib("compiler/ir/serialization.js/build/kotlin
|
|||||||
abstract class BasicIrBoxTest(
|
abstract class BasicIrBoxTest(
|
||||||
pathToTestDir: String,
|
pathToTestDir: String,
|
||||||
testGroupOutputDirPrefix: String,
|
testGroupOutputDirPrefix: String,
|
||||||
pathToRootOutputDir: String = BasicBoxTest.TEST_DATA_DIR_PATH,
|
pathToRootOutputDir: String = TEST_DATA_DIR_PATH,
|
||||||
generateSourceMap: Boolean = false,
|
generateSourceMap: Boolean = false,
|
||||||
generateNodeJsRunner: Boolean = false
|
generateNodeJsRunner: Boolean = false
|
||||||
) : BasicBoxTest(
|
) : BasicBoxTest(
|
||||||
@@ -38,6 +40,7 @@ abstract class BasicIrBoxTest(
|
|||||||
generateNodeJsRunner = generateNodeJsRunner,
|
generateNodeJsRunner = generateNodeJsRunner,
|
||||||
targetBackend = TargetBackend.JS_IR
|
targetBackend = TargetBackend.JS_IR
|
||||||
) {
|
) {
|
||||||
|
open val generateDts = false
|
||||||
|
|
||||||
override val skipMinification = true
|
override val skipMinification = true
|
||||||
|
|
||||||
@@ -53,6 +56,7 @@ abstract class BasicIrBoxTest(
|
|||||||
|
|
||||||
override val testChecker get() = if (runTestInNashorn) NashornIrJsTestChecker() else V8IrJsTestChecker
|
override val testChecker get() = if (runTestInNashorn) NashornIrJsTestChecker() else V8IrJsTestChecker
|
||||||
|
|
||||||
|
@Suppress("ConstantConditionIf")
|
||||||
override fun translateFiles(
|
override fun translateFiles(
|
||||||
units: List<TranslationUnit>,
|
units: List<TranslationUnit>,
|
||||||
outputFile: File,
|
outputFile: File,
|
||||||
@@ -70,7 +74,7 @@ abstract class BasicIrBoxTest(
|
|||||||
val filesToCompile = units
|
val filesToCompile = units
|
||||||
.map { (it as TranslationUnit.SourceFile).file }
|
.map { (it as TranslationUnit.SourceFile).file }
|
||||||
// TODO: split input files to some parts (global common, local common, test)
|
// TODO: split input files to some parts (global common, local common, test)
|
||||||
.filterNot { it.virtualFilePath.contains(BasicBoxTest.COMMON_FILES_DIR_PATH) }
|
.filterNot { it.virtualFilePath.contains(COMMON_FILES_DIR_PATH) }
|
||||||
|
|
||||||
val runtimeKlibs = if (needsFullIrRuntime) listOf(fullRuntimeKlib, kotlinTestKLib) else listOf(defaultRuntimeKlib)
|
val runtimeKlibs = if (needsFullIrRuntime) listOf(fullRuntimeKlib, kotlinTestKLib) else listOf(defaultRuntimeKlib)
|
||||||
|
|
||||||
@@ -85,7 +89,7 @@ abstract class BasicIrBoxTest(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isMainModule) {
|
if (isMainModule) {
|
||||||
val debugMode = false
|
val debugMode = getBoolean("kotlin.js.debugMode")
|
||||||
|
|
||||||
val phaseConfig = if (debugMode) {
|
val phaseConfig = if (debugMode) {
|
||||||
val allPhasesSet = jsPhases.toPhaseMap().values.toSet()
|
val allPhasesSet = jsPhases.toPhaseMap().values.toSet()
|
||||||
@@ -102,7 +106,7 @@ abstract class BasicIrBoxTest(
|
|||||||
PhaseConfig(jsPhases)
|
PhaseConfig(jsPhases)
|
||||||
}
|
}
|
||||||
|
|
||||||
val jsCode = compile(
|
val compiledModule = compile(
|
||||||
project = config.project,
|
project = config.project,
|
||||||
files = filesToCompile,
|
files = filesToCompile,
|
||||||
configuration = config.configuration,
|
configuration = config.configuration,
|
||||||
@@ -113,9 +117,14 @@ abstract class BasicIrBoxTest(
|
|||||||
exportedDeclarations = setOf(FqName.fromSegments(listOfNotNull(testPackage, testFunction)))
|
exportedDeclarations = setOf(FqName.fromSegments(listOfNotNull(testPackage, testFunction)))
|
||||||
)
|
)
|
||||||
|
|
||||||
val wrappedCode = wrapWithModuleEmulationMarkers(jsCode, moduleId = config.moduleId, moduleKind = config.moduleKind)
|
val wrappedCode = wrapWithModuleEmulationMarkers(compiledModule.jsCode, moduleId = config.moduleId, moduleKind = config.moduleKind)
|
||||||
outputFile.write(wrappedCode)
|
outputFile.write(wrappedCode)
|
||||||
|
|
||||||
|
if (generateDts) {
|
||||||
|
val dtsFile = outputFile.withReplacedExtensionOrNull("_v5.js", ".d.ts")
|
||||||
|
dtsFile?.write(compiledModule.tsDefinitions ?: error("No ts definitions"))
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
generateKLib(
|
generateKLib(
|
||||||
project = config.project,
|
project = config.project,
|
||||||
@@ -142,7 +151,7 @@ abstract class BasicIrBoxTest(
|
|||||||
// TODO: should we do anything special for module systems?
|
// TODO: should we do anything special for module systems?
|
||||||
// TODO: return list of js from translateFiles and provide then to this function with other js files
|
// TODO: return list of js from translateFiles and provide then to this function with other js files
|
||||||
|
|
||||||
testChecker.check(jsFiles, testModuleName, null, testFunction, expectedResult, withModuleSystem)
|
testChecker.check(jsFiles, testModuleName, testPackage, testFunction, expectedResult, withModuleSystem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.test.KotlinTestUtils
|
|||||||
import org.jetbrains.kotlin.test.KotlinTestWithEnvironment
|
import org.jetbrains.kotlin.test.KotlinTestWithEnvironment
|
||||||
import java.io.Closeable
|
import java.io.Closeable
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.lang.Boolean.getBoolean
|
||||||
|
|
||||||
private val wasmRuntimeKlib =
|
private val wasmRuntimeKlib =
|
||||||
loadKlib("compiler/ir/serialization.js/build/wasmRuntime/klib")
|
loadKlib("compiler/ir/serialization.js/build/wasmRuntime/klib")
|
||||||
@@ -88,7 +89,7 @@ abstract class BasicWasmBoxTest(
|
|||||||
testFunction: String
|
testFunction: String
|
||||||
) {
|
) {
|
||||||
val filesToCompile = units.map { (it as TranslationUnit.SourceFile).file }
|
val filesToCompile = units.map { (it as TranslationUnit.SourceFile).file }
|
||||||
val debugMode = false
|
val debugMode = getBoolean("kotlin.js.debugMode")
|
||||||
|
|
||||||
val phaseConfig = if (debugMode) {
|
val phaseConfig = if (debugMode) {
|
||||||
val allPhasesSet = wasmPhases.toPhaseMap().values.toSet()
|
val allPhasesSet = wasmPhases.toPhaseMap().values.toSet()
|
||||||
|
|||||||
+139
@@ -0,0 +1,139 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.js.test;
|
||||||
|
|
||||||
|
import com.intellij.testFramework.TestDataPath;
|
||||||
|
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
|
||||||
|
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||||
|
import org.jetbrains.kotlin.test.TargetBackend;
|
||||||
|
import org.jetbrains.kotlin.test.TestMetadata;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
@TestMetadata("js/js.translator/testData/typescript-export")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public class IrJsTypeScriptExportTestGenerated extends AbstractIrJsTypeScriptExportTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInTypescript_export() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/typescript-export"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS_IR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("js/js.translator/testData/typescript-export/declarations")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Declarations extends AbstractIrJsTypeScriptExportTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInDeclarations() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/typescript-export/declarations"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS_IR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("declarations.kt")
|
||||||
|
public void testDeclarations() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/typescript-export/declarations/declarations.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("js/js.translator/testData/typescript-export/inheritance")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Inheritance extends AbstractIrJsTypeScriptExportTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInInheritance() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/typescript-export/inheritance"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS_IR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("inheritance.kt")
|
||||||
|
public void testInheritance() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/typescript-export/inheritance/inheritance.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("js/js.translator/testData/typescript-export/namespaces")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Namespaces extends AbstractIrJsTypeScriptExportTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInNamespaces() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/typescript-export/namespaces"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS_IR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("namespaces.kt")
|
||||||
|
public void testNamespaces() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/typescript-export/namespaces/namespaces.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("js/js.translator/testData/typescript-export/primitives")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Primitives extends AbstractIrJsTypeScriptExportTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInPrimitives() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/typescript-export/primitives"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS_IR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("primitives.kt")
|
||||||
|
public void testPrimitives() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/typescript-export/primitives/primitives.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("js/js.translator/testData/typescript-export/selectiveExport")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class SelectiveExport extends AbstractIrJsTypeScriptExportTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInSelectiveExport() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/typescript-export/selectiveExport"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS_IR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("selectiveExport.kt")
|
||||||
|
public void testSelectiveExport() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/typescript-export/selectiveExport/selectiveExport.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("js/js.translator/testData/typescript-export/visibility")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Visibility extends AbstractIrJsTypeScriptExportTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInVisibility() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/typescript-export/visibility"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS_IR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("visibility.kt")
|
||||||
|
public void testVisibility() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/typescript-export/visibility/visibility.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
-10
@@ -6425,11 +6425,6 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
|||||||
runTest("js/js.translator/testData/box/propertyAccess/accessToInstanceProperty.kt");
|
runTest("js/js.translator/testData/box/propertyAccess/accessToInstanceProperty.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("accessorsWithJsName.kt")
|
|
||||||
public void testAccessorsWithJsName() throws Exception {
|
|
||||||
runTest("js/js.translator/testData/box/propertyAccess/accessorsWithJsName.kt");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testAllFilesPresentInPropertyAccess() throws Exception {
|
public void testAllFilesPresentInPropertyAccess() throws Exception {
|
||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/box/propertyAccess"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS_IR, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/box/propertyAccess"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS_IR, true);
|
||||||
}
|
}
|
||||||
@@ -6449,11 +6444,6 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
|||||||
runTest("js/js.translator/testData/box/propertyAccess/customSetter.kt");
|
runTest("js/js.translator/testData/box/propertyAccess/customSetter.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("defaultAccessorsWithJsName.kt")
|
|
||||||
public void testDefaultAccessorsWithJsName() throws Exception {
|
|
||||||
runTest("js/js.translator/testData/box/propertyAccess/defaultAccessorsWithJsName.kt");
|
|
||||||
}
|
|
||||||
|
|
||||||
@TestMetadata("enumerable.kt")
|
@TestMetadata("enumerable.kt")
|
||||||
public void testEnumerable() throws Exception {
|
public void testEnumerable() throws Exception {
|
||||||
runTest("js/js.translator/testData/box/propertyAccess/enumerable.kt");
|
runTest("js/js.translator/testData/box/propertyAccess/enumerable.kt");
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// DONT_TARGET_EXACT_BACKEND: JS_IR
|
||||||
// EXPECTED_REACHABLE_NODES: 1291
|
// EXPECTED_REACHABLE_NODES: 1291
|
||||||
|
|
||||||
class A {
|
class A {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// DONT_TARGET_EXACT_BACKEND: JS_IR
|
||||||
// EXPECTED_REACHABLE_NODES: 1288
|
// EXPECTED_REACHABLE_NODES: 1288
|
||||||
package foo
|
package foo
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// IGNORE_BACKEND: JS_IR
|
||||||
// EXPECTED_REACHABLE_NODES: 1288
|
// EXPECTED_REACHABLE_NODES: 1288
|
||||||
|
|
||||||
@JsExport
|
@JsExport
|
||||||
|
|||||||
+6
-4
@@ -1,14 +1,16 @@
|
|||||||
{
|
{
|
||||||
"dependencies" : {
|
"dependencies": {
|
||||||
"require-from-string": "1.2.0"
|
"require-from-string": "1.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies" : {
|
"devDependencies": {
|
||||||
"mocha": "3.2.0",
|
"mocha": "3.2.0",
|
||||||
"mocha-teamcity-reporter": "1.1.1"
|
"mocha-teamcity-reporter": "1.1.1",
|
||||||
|
"typescript": "^3.5.3"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"runOnTeamcity": "mocha --reporter mocha-teamcity-reporter",
|
"runOnTeamcity": "mocha --reporter mocha-teamcity-reporter",
|
||||||
"test": "mocha",
|
"test": "mocha",
|
||||||
"runIrTestInNode" : "node $NODE_DEBUG_OPTION runIrTestInNode.js"
|
"runIrTestInNode": "node $NODE_DEBUG_OPTION runIrTestInNode.js",
|
||||||
|
"generateTypeScriptTests": "tsc --build typescript-export/*/"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"strict": true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
declare namespace JS_TESTS {
|
||||||
|
type Nullable<T> = T | null | undefined
|
||||||
|
namespace foo {
|
||||||
|
function sum(x: number, y: number): number
|
||||||
|
function varargInt(x: Int32Array): number
|
||||||
|
function varargNullableInt(x: Array<Nullable<number>>): number
|
||||||
|
function varargWithOtherParameters(x: string, y: Array<string>, z: string): number
|
||||||
|
function varargWithComplexType(x: Array<(p0: Array<Int32Array>) => Array<Int32Array>>): number
|
||||||
|
function sumNullable(x: Nullable<number>, y: Nullable<number>): number
|
||||||
|
function defaultParameters(x: number, y: string): string
|
||||||
|
function generic1<T>(x: T): T
|
||||||
|
function generic2<T>(x: Nullable<T>): boolean
|
||||||
|
function generic3<A, B, C, D, E>(a: A, b: B, c: C, d: D): Nullable<E>
|
||||||
|
function inlineFun(x: number, callback: (p0: number) => void): void
|
||||||
|
const _const_val: number;
|
||||||
|
const _val: number;
|
||||||
|
let _var: number;
|
||||||
|
const _valCustom: number;
|
||||||
|
const _valCustomWithField: number;
|
||||||
|
let _varCustom: number;
|
||||||
|
let _varCustomWithField: number;
|
||||||
|
class A {
|
||||||
|
constructor()
|
||||||
|
}
|
||||||
|
class A1 {
|
||||||
|
constructor(x: number)
|
||||||
|
readonly x: number;
|
||||||
|
}
|
||||||
|
class A2 {
|
||||||
|
constructor(x: string, y: boolean)
|
||||||
|
readonly x: string;
|
||||||
|
y: boolean;
|
||||||
|
}
|
||||||
|
class A3 {
|
||||||
|
constructor()
|
||||||
|
readonly x: number;
|
||||||
|
}
|
||||||
|
class A4 {
|
||||||
|
constructor()
|
||||||
|
readonly _valCustom: number;
|
||||||
|
readonly _valCustomWithField: number;
|
||||||
|
_varCustom: number;
|
||||||
|
_varCustomWithField: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
// TARGET_BACKEND: JS_IR
|
||||||
|
// CHECK_TYPESCRIPT_DECLARATIONS
|
||||||
|
// RUN_PLAIN_BOX_FUNCTION
|
||||||
|
|
||||||
|
@file:JsExport
|
||||||
|
|
||||||
|
package foo
|
||||||
|
|
||||||
|
// TODO: Test the same for member functions:
|
||||||
|
|
||||||
|
fun sum(x: Int, y: Int): Int =
|
||||||
|
x + y
|
||||||
|
|
||||||
|
fun varargInt(vararg x: Int): Int =
|
||||||
|
x.size
|
||||||
|
|
||||||
|
fun varargNullableInt(vararg x: Int?): Int =
|
||||||
|
x.size
|
||||||
|
|
||||||
|
fun varargWithOtherParameters(x: String, vararg y: String, z: String): Int =
|
||||||
|
x.length + y.size + z.length
|
||||||
|
|
||||||
|
fun varargWithComplexType(vararg x: (Array<IntArray>) -> Array<IntArray>): Int =
|
||||||
|
x.size
|
||||||
|
|
||||||
|
fun sumNullable(x: Int?, y: Int?): Int =
|
||||||
|
(x ?: 0) + (y ?: 0)
|
||||||
|
|
||||||
|
fun defaultParameters(x: Int = 10, y: String = "OK"): String =
|
||||||
|
x.toString() + y
|
||||||
|
|
||||||
|
fun <T> generic1(x: T): T = x
|
||||||
|
|
||||||
|
fun <T> generic2(x: T?): Boolean = (x == null)
|
||||||
|
|
||||||
|
fun <A, B, C, D, E> generic3(a: A, b: B, c: C, d: D): E? = null
|
||||||
|
|
||||||
|
inline fun inlineFun(x: Int, callback: (Int) -> Unit) {
|
||||||
|
callback(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Properties
|
||||||
|
|
||||||
|
const val _const_val: Int = 1
|
||||||
|
val _val: Int = 1
|
||||||
|
var _var: Int = 1
|
||||||
|
|
||||||
|
val _valCustom: Int
|
||||||
|
get() = 1
|
||||||
|
|
||||||
|
val _valCustomWithField: Int = 1
|
||||||
|
get() = field + 1
|
||||||
|
|
||||||
|
var _varCustom: Int
|
||||||
|
get() = 1
|
||||||
|
set(value) {}
|
||||||
|
|
||||||
|
var _varCustomWithField: Int = 1
|
||||||
|
get() = field * 10
|
||||||
|
set(value) { field = value * 10 }
|
||||||
|
|
||||||
|
// Classes
|
||||||
|
|
||||||
|
class A
|
||||||
|
class A1(val x: Int)
|
||||||
|
class A2(val x: String, var y: Boolean)
|
||||||
|
class A3 {
|
||||||
|
val x: Int = 100
|
||||||
|
}
|
||||||
|
class A4 {
|
||||||
|
val _valCustom: Int
|
||||||
|
get() = 1
|
||||||
|
|
||||||
|
val _valCustomWithField: Int = 1
|
||||||
|
get() = field + 1
|
||||||
|
|
||||||
|
var _varCustom: Int
|
||||||
|
get() = 1
|
||||||
|
set(value) {}
|
||||||
|
|
||||||
|
var _varCustomWithField: Int = 1
|
||||||
|
get() = field * 10
|
||||||
|
set(value) { field = value * 10 }
|
||||||
|
}
|
||||||
+79
@@ -0,0 +1,79 @@
|
|||||||
|
"use strict";
|
||||||
|
var foo = JS_TESTS.foo;
|
||||||
|
var varargInt = JS_TESTS.foo.varargInt;
|
||||||
|
var varargNullableInt = JS_TESTS.foo.varargNullableInt;
|
||||||
|
var varargWithOtherParameters = JS_TESTS.foo.varargWithOtherParameters;
|
||||||
|
var varargWithComplexType = JS_TESTS.foo.varargWithComplexType;
|
||||||
|
var sumNullable = JS_TESTS.foo.sumNullable;
|
||||||
|
var defaultParameters = JS_TESTS.foo.defaultParameters;
|
||||||
|
var generic1 = JS_TESTS.foo.generic1;
|
||||||
|
var generic2 = JS_TESTS.foo.generic2;
|
||||||
|
var generic3 = JS_TESTS.foo.generic3;
|
||||||
|
var inlineFun = JS_TESTS.foo.inlineFun;
|
||||||
|
var _const_val = JS_TESTS.foo._const_val;
|
||||||
|
var _val = JS_TESTS.foo._val;
|
||||||
|
var _var = JS_TESTS.foo._var;
|
||||||
|
var A = JS_TESTS.foo.A;
|
||||||
|
var A1 = JS_TESTS.foo.A1;
|
||||||
|
var A2 = JS_TESTS.foo.A2;
|
||||||
|
var A3 = JS_TESTS.foo.A3;
|
||||||
|
var _valCustom = JS_TESTS.foo._valCustom;
|
||||||
|
var _valCustomWithField = JS_TESTS.foo._valCustomWithField;
|
||||||
|
var A4 = JS_TESTS.foo.A4;
|
||||||
|
function assert(condition) {
|
||||||
|
if (!condition) {
|
||||||
|
throw "Assertion failed";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function box() {
|
||||||
|
assert(foo.sum(10, 20) === 30);
|
||||||
|
assert(varargInt(new Int32Array([1, 2, 3])) === 3);
|
||||||
|
assert(varargNullableInt([10, 20, 30, null, undefined, 40]) === 6);
|
||||||
|
assert(varargWithOtherParameters("1234", ["1", "2", "3"], "12") === 9);
|
||||||
|
assert(varargWithComplexType([]) === 0);
|
||||||
|
assert(varargWithComplexType([
|
||||||
|
function (x) { return x; },
|
||||||
|
function (x) { return [new Int32Array([1, 2, 3])]; },
|
||||||
|
function (x) { return []; },
|
||||||
|
]) === 3);
|
||||||
|
assert(sumNullable(10, null) === 10);
|
||||||
|
assert(sumNullable(undefined, 20) === 20);
|
||||||
|
assert(sumNullable(1, 2) === 3);
|
||||||
|
assert(defaultParameters(20, "OK") === "20OK");
|
||||||
|
assert(generic1("FOO") === "FOO");
|
||||||
|
assert(generic1({ x: 10 }).x === 10);
|
||||||
|
assert(generic2(null) === true);
|
||||||
|
assert(generic2(undefined) === true);
|
||||||
|
assert(generic2(10) === false);
|
||||||
|
assert(generic3(10, true, "__", {}) === null);
|
||||||
|
var result = 0;
|
||||||
|
inlineFun(10, function (x) { result = x; });
|
||||||
|
assert(result === 10);
|
||||||
|
assert(_const_val === 1);
|
||||||
|
assert(_val === 1);
|
||||||
|
assert(_var === 1);
|
||||||
|
foo._var = 1000;
|
||||||
|
assert(foo._var === 1000);
|
||||||
|
assert(foo._valCustom === 1);
|
||||||
|
assert(foo._valCustomWithField === 2);
|
||||||
|
assert(foo._varCustom === 1);
|
||||||
|
foo._varCustom = 20;
|
||||||
|
assert(foo._varCustom === 1);
|
||||||
|
assert(foo._varCustomWithField === 10);
|
||||||
|
foo._varCustomWithField = 10;
|
||||||
|
assert(foo._varCustomWithField === 1000);
|
||||||
|
new A();
|
||||||
|
assert(new A1(10).x === 10);
|
||||||
|
assert(new A2("10", true).x === "10");
|
||||||
|
assert(new A3().x === 100);
|
||||||
|
var a4 = new A4();
|
||||||
|
assert(a4._valCustom === 1);
|
||||||
|
assert(a4._valCustomWithField === 2);
|
||||||
|
assert(a4._varCustom === 1);
|
||||||
|
a4._varCustom = 20;
|
||||||
|
assert(a4._varCustom === 1);
|
||||||
|
assert(a4._varCustomWithField === 10);
|
||||||
|
a4._varCustomWithField = 10;
|
||||||
|
assert(a4._varCustomWithField === 1000);
|
||||||
|
return "OK";
|
||||||
|
}
|
||||||
+90
@@ -0,0 +1,90 @@
|
|||||||
|
|
||||||
|
import foo = JS_TESTS.foo;
|
||||||
|
import varargInt = JS_TESTS.foo.varargInt;
|
||||||
|
import varargNullableInt = JS_TESTS.foo.varargNullableInt;
|
||||||
|
import varargWithOtherParameters = JS_TESTS.foo.varargWithOtherParameters;
|
||||||
|
import varargWithComplexType = JS_TESTS.foo.varargWithComplexType;
|
||||||
|
import sumNullable = JS_TESTS.foo.sumNullable;
|
||||||
|
import defaultParameters = JS_TESTS.foo.defaultParameters;
|
||||||
|
import generic1 = JS_TESTS.foo.generic1;
|
||||||
|
import generic2 = JS_TESTS.foo.generic2;
|
||||||
|
import generic3 = JS_TESTS.foo.generic3;
|
||||||
|
import inlineFun = JS_TESTS.foo.inlineFun;
|
||||||
|
import _const_val = JS_TESTS.foo._const_val;
|
||||||
|
import _val = JS_TESTS.foo._val;
|
||||||
|
import _var = JS_TESTS.foo._var;
|
||||||
|
import A = JS_TESTS.foo.A;
|
||||||
|
import A1 = JS_TESTS.foo.A1;
|
||||||
|
import A2 = JS_TESTS.foo.A2;
|
||||||
|
import A3 = JS_TESTS.foo.A3;
|
||||||
|
import _valCustom = JS_TESTS.foo._valCustom;
|
||||||
|
import _valCustomWithField = JS_TESTS.foo._valCustomWithField;
|
||||||
|
import A4 = JS_TESTS.foo.A4;
|
||||||
|
|
||||||
|
function assert(condition: boolean) {
|
||||||
|
if (!condition) {
|
||||||
|
throw "Assertion failed";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function box(): string {
|
||||||
|
assert(foo.sum(10, 20) === 30);
|
||||||
|
assert(varargInt(new Int32Array([1, 2, 3])) === 3);
|
||||||
|
assert(varargNullableInt([10, 20, 30, null, undefined, 40]) === 6);
|
||||||
|
assert(varargWithOtherParameters("1234", ["1", "2", "3"], "12") === 9);
|
||||||
|
assert(varargWithComplexType([]) === 0);
|
||||||
|
assert(varargWithComplexType([
|
||||||
|
x => x,
|
||||||
|
x => [new Int32Array([1, 2, 3])],
|
||||||
|
x => [],
|
||||||
|
]) === 3);
|
||||||
|
|
||||||
|
assert(sumNullable(10, null) === 10);
|
||||||
|
assert(sumNullable(undefined, 20) === 20);
|
||||||
|
assert(sumNullable(1, 2) === 3);
|
||||||
|
assert(defaultParameters(20, "OK") === "20OK");
|
||||||
|
assert(generic1<string>("FOO") === "FOO");
|
||||||
|
assert(generic1({x: 10}).x === 10);
|
||||||
|
assert(generic2(null) === true);
|
||||||
|
assert(generic2(undefined) === true);
|
||||||
|
assert(generic2(10) === false);
|
||||||
|
assert(generic3(10, true, "__", {}) === null);
|
||||||
|
|
||||||
|
let result: number = 0;
|
||||||
|
inlineFun(10, x => { result = x; });
|
||||||
|
assert(result === 10);
|
||||||
|
|
||||||
|
assert(_const_val === 1);
|
||||||
|
assert(_val === 1);
|
||||||
|
assert(_var === 1);
|
||||||
|
foo._var = 1000;
|
||||||
|
assert(foo._var === 1000);
|
||||||
|
|
||||||
|
assert(foo._valCustom === 1);
|
||||||
|
assert(foo._valCustomWithField === 2);
|
||||||
|
assert(foo._varCustom === 1);
|
||||||
|
foo._varCustom = 20;
|
||||||
|
assert(foo._varCustom === 1);
|
||||||
|
assert(foo._varCustomWithField === 10);
|
||||||
|
foo._varCustomWithField = 10;
|
||||||
|
assert(foo._varCustomWithField === 1000);
|
||||||
|
|
||||||
|
new A();
|
||||||
|
assert(new A1(10).x === 10);
|
||||||
|
assert(new A2("10", true).x === "10");
|
||||||
|
assert(new A3().x === 100);
|
||||||
|
|
||||||
|
|
||||||
|
const a4 = new A4();
|
||||||
|
|
||||||
|
assert(a4._valCustom === 1);
|
||||||
|
assert(a4._valCustomWithField === 2);
|
||||||
|
assert(a4._varCustom === 1);
|
||||||
|
a4._varCustom = 20;
|
||||||
|
assert(a4._varCustom === 1);
|
||||||
|
assert(a4._varCustomWithField === 10);
|
||||||
|
a4._varCustomWithField = 10;
|
||||||
|
assert(a4._varCustomWithField === 1000);
|
||||||
|
|
||||||
|
return "OK";
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"include": [ "./*" ],
|
||||||
|
"extends": "../common.tsconfig.json"
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
declare namespace JS_TESTS {
|
||||||
|
type Nullable<T> = T | null | undefined
|
||||||
|
namespace foo {
|
||||||
|
interface I<T, S, U> {
|
||||||
|
x: T;
|
||||||
|
readonly y: S;
|
||||||
|
z(u: U): void
|
||||||
|
}
|
||||||
|
interface I2 {
|
||||||
|
x: string;
|
||||||
|
readonly y: boolean;
|
||||||
|
z(z: number): void
|
||||||
|
}
|
||||||
|
}
|
||||||
|
namespace foo {
|
||||||
|
abstract class AC implements foo.I2 {
|
||||||
|
constructor()
|
||||||
|
x: string;
|
||||||
|
abstract readonly y: boolean;
|
||||||
|
abstract z(z: number): void
|
||||||
|
readonly acProp: string;
|
||||||
|
abstract readonly acAbstractProp: string;
|
||||||
|
}
|
||||||
|
class OC extends foo.AC implements foo.I<string, boolean, number> {
|
||||||
|
constructor(y: boolean, acAbstractProp: string)
|
||||||
|
readonly y: boolean;
|
||||||
|
readonly acAbstractProp: string;
|
||||||
|
z(z: number): void
|
||||||
|
}
|
||||||
|
class FC extends foo.OC {
|
||||||
|
constructor()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
// TARGET_BACKEND: JS_IR
|
||||||
|
// CHECK_TYPESCRIPT_DECLARATIONS
|
||||||
|
// RUN_PLAIN_BOX_FUNCTION
|
||||||
|
|
||||||
|
@file:JsExport
|
||||||
|
|
||||||
|
package foo
|
||||||
|
|
||||||
|
external interface I<T, out S, in U> {
|
||||||
|
var x: T
|
||||||
|
val y: S
|
||||||
|
fun z(u: U)
|
||||||
|
}
|
||||||
|
|
||||||
|
external interface I2 {
|
||||||
|
var x: String
|
||||||
|
val y: Boolean
|
||||||
|
fun z(z: Int)
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class AC : I2 {
|
||||||
|
override var x = "AC"
|
||||||
|
override abstract val y: Boolean
|
||||||
|
override abstract fun z(z: Int)
|
||||||
|
|
||||||
|
val acProp: String = "acProp"
|
||||||
|
abstract val acAbstractProp: String
|
||||||
|
}
|
||||||
|
|
||||||
|
open class OC(
|
||||||
|
override val y: Boolean,
|
||||||
|
override val acAbstractProp: String
|
||||||
|
) : AC(), I<String, Boolean, Int> {
|
||||||
|
override fun z(z: Int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
private val privateX: String = "privateX"
|
||||||
|
private fun privateFun(): String = "privateFun"
|
||||||
|
}
|
||||||
|
|
||||||
|
final class FC : OC(true, "FC")
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
"use strict";
|
||||||
|
var __extends = (this && this.__extends) || (function () {
|
||||||
|
var extendStatics = function (d, b) {
|
||||||
|
extendStatics = Object.setPrototypeOf ||
|
||||||
|
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||||
|
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
||||||
|
return extendStatics(d, b);
|
||||||
|
};
|
||||||
|
return function (d, b) {
|
||||||
|
extendStatics(d, b);
|
||||||
|
function __() { this.constructor = d; }
|
||||||
|
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
var OC = JS_TESTS.foo.OC;
|
||||||
|
var AC = JS_TESTS.foo.AC;
|
||||||
|
var FC = JS_TESTS.foo.FC;
|
||||||
|
var Impl = /** @class */ (function (_super) {
|
||||||
|
__extends(Impl, _super);
|
||||||
|
function Impl() {
|
||||||
|
return _super !== null && _super.apply(this, arguments) || this;
|
||||||
|
}
|
||||||
|
Impl.prototype.z = function (z) {
|
||||||
|
};
|
||||||
|
Object.defineProperty(Impl.prototype, "acAbstractProp", {
|
||||||
|
get: function () { return "Impl"; },
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
Object.defineProperty(Impl.prototype, "y", {
|
||||||
|
get: function () { return true; },
|
||||||
|
enumerable: true,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
return Impl;
|
||||||
|
}(AC));
|
||||||
|
function box() {
|
||||||
|
var impl = new Impl();
|
||||||
|
if (impl.acProp !== "acProp")
|
||||||
|
return "Fail 1";
|
||||||
|
if (impl.x !== "AC")
|
||||||
|
return "Fail 2";
|
||||||
|
if (impl.acAbstractProp !== "Impl")
|
||||||
|
return "Fail 2.1";
|
||||||
|
if (impl.y !== true)
|
||||||
|
return "Fail 2.2";
|
||||||
|
var oc = new OC(false, "OC");
|
||||||
|
if (oc.y !== false)
|
||||||
|
return "Fail 3";
|
||||||
|
if (oc.acAbstractProp !== "OC")
|
||||||
|
return "Fail 4";
|
||||||
|
oc.z(10);
|
||||||
|
var fc = new FC();
|
||||||
|
if (fc.y !== true)
|
||||||
|
return "Fail 5";
|
||||||
|
if (fc.acAbstractProp !== "FC")
|
||||||
|
return "Fail 6";
|
||||||
|
fc.z(10);
|
||||||
|
return "OK";
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import OC = JS_TESTS.foo.OC;
|
||||||
|
import AC = JS_TESTS.foo.AC;
|
||||||
|
import FC = JS_TESTS.foo.FC;
|
||||||
|
|
||||||
|
class Impl extends AC {
|
||||||
|
z(z: number): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
get acAbstractProp(): string { return "Impl"; }
|
||||||
|
get y(): boolean { return true; }
|
||||||
|
}
|
||||||
|
|
||||||
|
function box(): string {
|
||||||
|
const impl = new Impl();
|
||||||
|
if (impl.acProp !== "acProp") return "Fail 1";
|
||||||
|
if (impl.x !== "AC") return "Fail 2";
|
||||||
|
if (impl.acAbstractProp !== "Impl") return "Fail 2.1";
|
||||||
|
if (impl.y !== true) return "Fail 2.2";
|
||||||
|
|
||||||
|
|
||||||
|
const oc = new OC(false, "OC");
|
||||||
|
if (oc.y !== false) return "Fail 3";
|
||||||
|
if (oc.acAbstractProp !== "OC") return "Fail 4";
|
||||||
|
oc.z(10);
|
||||||
|
|
||||||
|
|
||||||
|
const fc = new FC();
|
||||||
|
if (fc.y !== true) return "Fail 5";
|
||||||
|
if (fc.acAbstractProp !== "FC") return "Fail 6";
|
||||||
|
fc.z(10);
|
||||||
|
|
||||||
|
return "OK";
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"include": [ "./*" ],
|
||||||
|
"extends": "../common.tsconfig.json"
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
declare namespace JS_TESTS {
|
||||||
|
type Nullable<T> = T | null | undefined
|
||||||
|
namespace foo.bar.baz {
|
||||||
|
class C1 {
|
||||||
|
constructor(value: string)
|
||||||
|
readonly value: string;
|
||||||
|
component1(): string
|
||||||
|
copy(value: string): foo.bar.baz.C1
|
||||||
|
toString(): string
|
||||||
|
hashCode(): number
|
||||||
|
equals(other: Nullable<any>): boolean
|
||||||
|
}
|
||||||
|
function f(x1: foo.bar.baz.C1, x2: a.b.C2, x3: C3): string
|
||||||
|
}
|
||||||
|
namespace a.b {
|
||||||
|
class C2 {
|
||||||
|
constructor(value: string)
|
||||||
|
readonly value: string;
|
||||||
|
component1(): string
|
||||||
|
copy(value: string): a.b.C2
|
||||||
|
toString(): string
|
||||||
|
hashCode(): number
|
||||||
|
equals(other: Nullable<any>): boolean
|
||||||
|
}
|
||||||
|
function f(x1: foo.bar.baz.C1, x2: a.b.C2, x3: C3): string
|
||||||
|
}
|
||||||
|
class C3 {
|
||||||
|
constructor(value: string)
|
||||||
|
readonly value: string;
|
||||||
|
component1(): string
|
||||||
|
copy(value: string): C3
|
||||||
|
toString(): string
|
||||||
|
hashCode(): number
|
||||||
|
equals(other: Nullable<any>): boolean
|
||||||
|
}
|
||||||
|
function f(x1: foo.bar.baz.C1, x2: a.b.C2, x3: C3): string
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
// TARGET_BACKEND: JS_IR
|
||||||
|
// CHECK_TYPESCRIPT_DECLARATIONS
|
||||||
|
// RUN_PLAIN_BOX_FUNCTION
|
||||||
|
|
||||||
|
// FILE: file1.kt
|
||||||
|
|
||||||
|
package foo.bar.baz
|
||||||
|
|
||||||
|
import a.b.*
|
||||||
|
import C3
|
||||||
|
|
||||||
|
@JsExport
|
||||||
|
data class C1(val value: String)
|
||||||
|
|
||||||
|
@JsExport
|
||||||
|
fun f(x1: C1, x2: C2, x3: C3): String {
|
||||||
|
return "foo.bar.baz.f($x1, $x2, $x3)"
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: file2.kt
|
||||||
|
|
||||||
|
@file:JsExport
|
||||||
|
|
||||||
|
package a.b
|
||||||
|
|
||||||
|
import foo.bar.baz.*
|
||||||
|
import C3
|
||||||
|
|
||||||
|
data class C2(val value: String)
|
||||||
|
fun f(x1: C1, x2: C2, x3: C3): String {
|
||||||
|
return "a.b.f($x1, $x2, $x3)"
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: file3.kt
|
||||||
|
|
||||||
|
@file:JsExport
|
||||||
|
|
||||||
|
import a.b.*
|
||||||
|
import foo.bar.baz.*
|
||||||
|
|
||||||
|
@JsExport
|
||||||
|
data class C3(val value: String)
|
||||||
|
|
||||||
|
@JsExport
|
||||||
|
fun f(x1: C1, x2: C2, x3: C3): String {
|
||||||
|
return "f($x1, $x2, $x3)"
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
"use strict";
|
||||||
|
var C1 = JS_TESTS.foo.bar.baz.C1;
|
||||||
|
var C2 = JS_TESTS.a.b.C2;
|
||||||
|
var C3 = JS_TESTS.C3;
|
||||||
|
function box() {
|
||||||
|
var c1 = new C1("1");
|
||||||
|
var c2 = new C2("2");
|
||||||
|
var c3 = new C3("3");
|
||||||
|
var res1 = JS_TESTS.foo.bar.baz.f(c1, c2, c3);
|
||||||
|
var res2 = JS_TESTS.a.b.f(c1, c2, c3);
|
||||||
|
var res3 = JS_TESTS.f(c1, c2, c3);
|
||||||
|
if (res1 !== "foo.bar.baz.f(C1(value=1), C2(value=2), C3(value=3))")
|
||||||
|
return "Fail 1: " + res1;
|
||||||
|
if (res2 !== "a.b.f(C1(value=1), C2(value=2), C3(value=3))")
|
||||||
|
return "Fail 2: " + res2;
|
||||||
|
if (res3 !== "f(C1(value=1), C2(value=2), C3(value=3))")
|
||||||
|
return "Fail 3: " + res3;
|
||||||
|
return "OK";
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import C1 = JS_TESTS.foo.bar.baz.C1;
|
||||||
|
import C2 = JS_TESTS.a.b.C2;
|
||||||
|
import C3 = JS_TESTS.C3;
|
||||||
|
|
||||||
|
function box(): string {
|
||||||
|
const c1 = new C1("1");
|
||||||
|
const c2 = new C2("2");
|
||||||
|
const c3 = new C3("3");
|
||||||
|
|
||||||
|
const res1 = JS_TESTS.foo.bar.baz.f(c1, c2, c3);
|
||||||
|
const res2 = JS_TESTS.a.b.f(c1, c2, c3);
|
||||||
|
const res3 = JS_TESTS.f(c1, c2, c3);
|
||||||
|
|
||||||
|
if (res1 !== "foo.bar.baz.f(C1(value=1), C2(value=2), C3(value=3))")
|
||||||
|
return "Fail 1: " + res1;
|
||||||
|
|
||||||
|
if (res2 !== "a.b.f(C1(value=1), C2(value=2), C3(value=3))")
|
||||||
|
return "Fail 2: " + res2;
|
||||||
|
|
||||||
|
if (res3 !== "f(C1(value=1), C2(value=2), C3(value=3))")
|
||||||
|
return "Fail 3: " + res3;
|
||||||
|
|
||||||
|
return "OK";
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"include": [ "./*" ],
|
||||||
|
"extends": "../common.tsconfig.json"
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
declare namespace JS_TESTS {
|
||||||
|
type Nullable<T> = T | null | undefined
|
||||||
|
namespace foo {
|
||||||
|
const _any: any;
|
||||||
|
const _unit: void;
|
||||||
|
function _nothing(): never
|
||||||
|
const _throwable: Error;
|
||||||
|
const _string: string;
|
||||||
|
const _boolean: boolean;
|
||||||
|
const _byte: number;
|
||||||
|
const _short: number;
|
||||||
|
const _int: number;
|
||||||
|
const _float: number;
|
||||||
|
const _double: number;
|
||||||
|
const _byte_array: Int8Array;
|
||||||
|
const _short_array: Int16Array;
|
||||||
|
const _int_array: Int32Array;
|
||||||
|
const _float_array: Float32Array;
|
||||||
|
const _double_array: Float64Array;
|
||||||
|
const _array_byte: Array<number>;
|
||||||
|
const _array_short: Array<number>;
|
||||||
|
const _array_int: Array<number>;
|
||||||
|
const _array_float: Array<number>;
|
||||||
|
const _array_double: Array<number>;
|
||||||
|
const _array_string: Array<string>;
|
||||||
|
const _array_boolean: Array<boolean>;
|
||||||
|
const _array_array_string: Array<Array<string>>;
|
||||||
|
const _array_array_int_array: Array<Array<Int32Array>>;
|
||||||
|
const _fun_unit: () => void;
|
||||||
|
const _fun_int_unit: (p0: number) => void;
|
||||||
|
const _fun_boolean_int_string_intarray: (p0: boolean, p1: number, p2: string) => Int32Array;
|
||||||
|
const _curried_fun: (p0: number) => (p0: number) => (p0: number) => (p0: number) => (p0: number) => number;
|
||||||
|
const _higher_order_fun: (p0: (p0: number) => string, p1: (p0: string) => number) => (p0: number) => number;
|
||||||
|
const _n_any: Nullable<any>;
|
||||||
|
const _n_nothing: Nullable<never>;
|
||||||
|
const _n_throwable: Nullable<Error>;
|
||||||
|
const _n_string: Nullable<string>;
|
||||||
|
const _n_boolean: Nullable<boolean>;
|
||||||
|
const _n_byte: Nullable<number>;
|
||||||
|
const _n_short_array: Nullable<Int16Array>;
|
||||||
|
const _n_array_int: Nullable<Array<number>>;
|
||||||
|
const _array_n_int: Array<Nullable<number>>;
|
||||||
|
const _n_array_n_int: Nullable<Array<Nullable<number>>>;
|
||||||
|
const _array_n_array_string: Array<Nullable<Array<string>>>;
|
||||||
|
const _fun_n_int_unit: (p0: Nullable<number>) => void;
|
||||||
|
const _fun_n_boolean_n_int_n_string_n_intarray: (p0: Nullable<boolean>, p1: Nullable<number>, p2: Nullable<string>) => Nullable<Int32Array>;
|
||||||
|
const _n_curried_fun: (p0: Nullable<number>) => (p0: Nullable<number>) => (p0: Nullable<number>) => Nullable<number>;
|
||||||
|
const _n_higher_order_fun: (p0: (p0: Nullable<number>) => Nullable<string>, p1: (p0: Nullable<string>) => Nullable<number>) => (p0: Nullable<number>) => Nullable<number>;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
// TARGET_BACKEND: JS_IR
|
||||||
|
// CHECK_TYPESCRIPT_DECLARATIONS
|
||||||
|
// RUN_PLAIN_BOX_FUNCTION
|
||||||
|
|
||||||
|
@file:JsExport
|
||||||
|
|
||||||
|
package foo
|
||||||
|
|
||||||
|
val _any: Any = Any()
|
||||||
|
|
||||||
|
val _unit: Unit = Unit
|
||||||
|
|
||||||
|
fun _nothing(): Nothing { throw Throwable() }
|
||||||
|
|
||||||
|
val _throwable: Throwable = Throwable()
|
||||||
|
|
||||||
|
val _string: String = "ZZZ"
|
||||||
|
|
||||||
|
val _boolean: Boolean = true
|
||||||
|
|
||||||
|
val _byte: Byte = 1.toByte()
|
||||||
|
val _short: Short = 1.toShort()
|
||||||
|
val _int: Int = 1
|
||||||
|
val _float: Float = 1.0f
|
||||||
|
val _double: Double = 1.0
|
||||||
|
// TODO: Char and Long
|
||||||
|
|
||||||
|
val _byte_array: ByteArray = byteArrayOf()
|
||||||
|
val _short_array: ShortArray = shortArrayOf()
|
||||||
|
val _int_array: IntArray = intArrayOf()
|
||||||
|
val _float_array: FloatArray = floatArrayOf()
|
||||||
|
val _double_array: DoubleArray = doubleArrayOf()
|
||||||
|
|
||||||
|
val _array_byte: Array<Byte> = emptyArray()
|
||||||
|
val _array_short: Array<Short> = emptyArray()
|
||||||
|
val _array_int: Array<Int> = emptyArray()
|
||||||
|
val _array_float: Array<Float> = emptyArray()
|
||||||
|
val _array_double: Array<Double> = emptyArray()
|
||||||
|
val _array_string: Array<String> = emptyArray()
|
||||||
|
val _array_boolean: Array<Boolean> = emptyArray()
|
||||||
|
val _array_array_string: Array<Array<String>> = arrayOf(emptyArray())
|
||||||
|
val _array_array_int_array: Array<Array<IntArray>> = arrayOf(arrayOf(intArrayOf()))
|
||||||
|
|
||||||
|
val _fun_unit: () -> Unit = { }
|
||||||
|
val _fun_int_unit: (Int) -> Unit = { x -> }
|
||||||
|
|
||||||
|
val _fun_boolean_int_string_intarray: (Boolean, Int, String) -> IntArray =
|
||||||
|
{ b, i, s -> intArrayOf(b.toString().length, i, s.length) }
|
||||||
|
|
||||||
|
val _curried_fun: (Int) -> (Int) -> (Int) -> (Int) -> (Int) -> Int =
|
||||||
|
{ x1 -> { x2 -> { x3 -> { x4 -> { x5 -> x1 + x2 + x3 + x4 + x5 } } } } }
|
||||||
|
|
||||||
|
val _higher_order_fun: ((Int) -> String, (String) -> Int) -> ((Int) -> Int) =
|
||||||
|
{ f1, f2 -> { x -> f2(f1(x)) } }
|
||||||
|
|
||||||
|
|
||||||
|
// Nullable types
|
||||||
|
|
||||||
|
val _n_any: Any? = Any()
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
// val _n_unit: Unit? = Unit
|
||||||
|
|
||||||
|
val _n_nothing: Nothing? = null
|
||||||
|
|
||||||
|
val _n_throwable: Throwable? = Throwable()
|
||||||
|
|
||||||
|
val _n_string: String? = "ZZZ"
|
||||||
|
|
||||||
|
val _n_boolean: Boolean? = true
|
||||||
|
|
||||||
|
val _n_byte: Byte? = 1.toByte()
|
||||||
|
|
||||||
|
// TODO: Char and Long
|
||||||
|
|
||||||
|
val _n_short_array: ShortArray? = shortArrayOf()
|
||||||
|
|
||||||
|
val _n_array_int: Array<Int>? = emptyArray()
|
||||||
|
val _array_n_int: Array<Int?> = emptyArray()
|
||||||
|
val _n_array_n_int: Array<Int?>? = emptyArray()
|
||||||
|
|
||||||
|
val _array_n_array_string: Array<Array<String>?> = arrayOf(arrayOf(":)"))
|
||||||
|
|
||||||
|
val _fun_n_int_unit: (Int?) -> Unit = { x -> }
|
||||||
|
|
||||||
|
val _fun_n_boolean_n_int_n_string_n_intarray: (Boolean?, Int?, String?) -> IntArray? =
|
||||||
|
{ b, i, s -> null }
|
||||||
|
|
||||||
|
val _n_curried_fun: (Int?) -> (Int?) -> (Int?) -> Int? =
|
||||||
|
{ x1 -> { x2 -> { x3 -> (x1 ?: 0) + (x2 ?: 0) + (x3 ?: 0) } } }
|
||||||
|
|
||||||
|
val _n_higher_order_fun: ((Int?) -> String?, (String?) -> Int?) -> ((Int?) -> Int?) =
|
||||||
|
{ f1, f2 -> { x -> f2(f1(x)) } }
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
"use strict";
|
||||||
|
var foo = JS_TESTS.foo;
|
||||||
|
function assert(condition) {
|
||||||
|
if (!condition) {
|
||||||
|
throw "Assertion failed";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(typeof foo._any === "object");
|
||||||
|
assert(foo._string === "ZZZ");
|
||||||
|
assert(foo._boolean === true);
|
||||||
|
assert(foo._byte === 1);
|
||||||
|
assert(foo._short === 1);
|
||||||
|
assert(foo._float === 1);
|
||||||
|
assert(foo._double === 1);
|
||||||
|
assert(foo._byte_array instanceof Int8Array);
|
||||||
|
assert(foo._short_array instanceof Int16Array);
|
||||||
|
assert(foo._int_array instanceof Int32Array);
|
||||||
|
assert(foo._float_array instanceof Float32Array);
|
||||||
|
assert(foo._double_array instanceof Float64Array);
|
||||||
|
assert(foo._array_byte instanceof Array);
|
||||||
|
assert(foo._array_short instanceof Array);
|
||||||
|
assert(foo._array_int instanceof Array);
|
||||||
|
assert(foo._array_float instanceof Array);
|
||||||
|
assert(foo._array_double instanceof Array);
|
||||||
|
assert(foo._array_string instanceof Array);
|
||||||
|
assert(foo._array_boolean instanceof Array);
|
||||||
|
assert(foo._array_array_string instanceof Array);
|
||||||
|
assert(foo._array_array_string[0] instanceof Array);
|
||||||
|
assert(foo._array_array_int_array instanceof Array);
|
||||||
|
assert(foo._array_array_int_array[0] instanceof Array);
|
||||||
|
assert(foo._array_array_int_array[0][0] instanceof Int32Array);
|
||||||
|
foo._fun_unit();
|
||||||
|
foo._fun_int_unit(10);
|
||||||
|
assert(foo._fun_boolean_int_string_intarray(true, 20, "A") instanceof Int32Array);
|
||||||
|
assert(foo._curried_fun(1)(2)(3)(4)(5) == 15);
|
||||||
|
assert(foo._higher_order_fun(function (n) { return String(n); }, function (s) { return s.length; })(1000) == 4);
|
||||||
|
assert(foo._n_any != null);
|
||||||
|
assert(foo._n_nothing == null);
|
||||||
|
assert(foo._n_throwable instanceof Error);
|
||||||
|
assert(foo._n_string === "ZZZ");
|
||||||
|
assert(foo._n_boolean === true);
|
||||||
|
assert(foo._n_byte === 1);
|
||||||
|
assert(foo._n_short_array instanceof Int16Array);
|
||||||
|
assert(foo._n_array_int instanceof Array);
|
||||||
|
assert(foo._array_n_int instanceof Array);
|
||||||
|
assert(foo._n_array_n_int instanceof Array);
|
||||||
|
assert(foo._array_n_array_string instanceof Array);
|
||||||
|
var x = foo._array_n_array_string[0];
|
||||||
|
assert(x != null);
|
||||||
|
assert(x instanceof Array);
|
||||||
|
assert(x == null ? false : (x[0] === ":)"));
|
||||||
|
foo._fun_n_int_unit(null);
|
||||||
|
assert(foo._fun_n_boolean_n_int_n_string_n_intarray(false, undefined, "ZZZ") == null);
|
||||||
|
assert(foo._n_curried_fun(10)(null)(30) === 40);
|
||||||
|
assert(foo._n_higher_order_fun(function (n) { return String(n); }, function (s) { return (s == null ? 10 : s.length); })(1000) === 4);
|
||||||
|
function box() {
|
||||||
|
return "OK";
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
import foo = JS_TESTS.foo;
|
||||||
|
|
||||||
|
function assert(condition: boolean) {
|
||||||
|
if (!condition) {
|
||||||
|
throw "Assertion failed";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(typeof foo._any === "object");
|
||||||
|
assert(foo._string === "ZZZ");
|
||||||
|
assert(foo._boolean === true);
|
||||||
|
assert(foo._byte === 1);
|
||||||
|
assert(foo._short === 1);
|
||||||
|
assert(foo._float === 1);
|
||||||
|
assert(foo._double === 1);
|
||||||
|
assert(foo._byte_array instanceof Int8Array);
|
||||||
|
assert(foo._short_array instanceof Int16Array);
|
||||||
|
assert(foo._int_array instanceof Int32Array);
|
||||||
|
assert(foo._float_array instanceof Float32Array);
|
||||||
|
assert(foo._double_array instanceof Float64Array);
|
||||||
|
assert(foo._array_byte instanceof Array);
|
||||||
|
assert(foo._array_short instanceof Array);
|
||||||
|
assert(foo._array_int instanceof Array);
|
||||||
|
assert(foo._array_float instanceof Array);
|
||||||
|
assert(foo._array_double instanceof Array);
|
||||||
|
assert(foo._array_string instanceof Array);
|
||||||
|
assert(foo._array_boolean instanceof Array);
|
||||||
|
|
||||||
|
assert(foo._array_array_string instanceof Array);
|
||||||
|
assert(foo._array_array_string[0] instanceof Array);
|
||||||
|
|
||||||
|
assert(foo._array_array_int_array instanceof Array);
|
||||||
|
assert(foo._array_array_int_array[0] instanceof Array);
|
||||||
|
assert(foo._array_array_int_array[0][0] instanceof Int32Array);
|
||||||
|
|
||||||
|
foo._fun_unit();
|
||||||
|
foo._fun_int_unit(10);
|
||||||
|
assert(foo._fun_boolean_int_string_intarray(true, 20, "A") instanceof Int32Array);
|
||||||
|
assert(foo._curried_fun(1)(2)(3)(4)(5) == 15);
|
||||||
|
assert(foo._higher_order_fun((n) => String(n), (s) => s.length)(1000) == 4);
|
||||||
|
assert(foo._n_any != null);
|
||||||
|
assert(foo._n_nothing == null);
|
||||||
|
assert(foo._n_throwable instanceof Error);
|
||||||
|
assert(foo._n_string === "ZZZ");
|
||||||
|
assert(foo._n_boolean === true);
|
||||||
|
assert(foo._n_byte === 1);
|
||||||
|
assert(foo._n_short_array instanceof Int16Array);
|
||||||
|
assert(foo._n_array_int instanceof Array);
|
||||||
|
assert(foo._array_n_int instanceof Array);
|
||||||
|
assert(foo._n_array_n_int instanceof Array);
|
||||||
|
|
||||||
|
assert(foo._array_n_array_string instanceof Array);
|
||||||
|
let x = foo._array_n_array_string[0];
|
||||||
|
assert(x != null);
|
||||||
|
assert(x instanceof Array);
|
||||||
|
assert(x == null ? false : (x[0] === ":)"));
|
||||||
|
|
||||||
|
foo._fun_n_int_unit(null);
|
||||||
|
|
||||||
|
assert(foo._fun_n_boolean_n_int_n_string_n_intarray(false, undefined, "ZZZ") == null);
|
||||||
|
assert(foo._n_curried_fun(10)(null)(30) === 40);
|
||||||
|
assert(foo._n_higher_order_fun(
|
||||||
|
n => String(n),
|
||||||
|
s => (s == null ? 10 : s.length)
|
||||||
|
)(1000) === 4);
|
||||||
|
|
||||||
|
function box(): string {
|
||||||
|
return "OK";
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"include": [ "./*" ],
|
||||||
|
"extends": "../common.tsconfig.json"
|
||||||
|
}
|
||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
declare namespace JS_TESTS {
|
||||||
|
type Nullable<T> = T | null | undefined
|
||||||
|
namespace foo {
|
||||||
|
interface ExportedInternalInterface {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
namespace foo {
|
||||||
|
interface FileLevelExportedExternalInterface {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
namespace foo {
|
||||||
|
const exportedVal: number;
|
||||||
|
function exportedFun(): number
|
||||||
|
class ExportedClass {
|
||||||
|
constructor()
|
||||||
|
readonly value: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
namespace foo {
|
||||||
|
const fileLevelExportedVal: number;
|
||||||
|
function fileLevelExportedFun(): number
|
||||||
|
class FileLevelExportedClass {
|
||||||
|
constructor()
|
||||||
|
readonly value: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+43
@@ -0,0 +1,43 @@
|
|||||||
|
// TARGET_BACKEND: JS_IR
|
||||||
|
// CHECK_TYPESCRIPT_DECLARATIONS
|
||||||
|
// RUN_PLAIN_BOX_FUNCTION
|
||||||
|
|
||||||
|
// FILE: file1.kt
|
||||||
|
package foo
|
||||||
|
|
||||||
|
@JsExport
|
||||||
|
val exportedVal = 10
|
||||||
|
|
||||||
|
@JsExport
|
||||||
|
fun exportedFun() = 10
|
||||||
|
|
||||||
|
@JsExport
|
||||||
|
class ExportedClass {
|
||||||
|
val value = 10
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsExport
|
||||||
|
external interface ExportedInternalInterface
|
||||||
|
|
||||||
|
val _val = 10
|
||||||
|
|
||||||
|
fun _fun() = 10
|
||||||
|
|
||||||
|
class Class
|
||||||
|
|
||||||
|
external interface ExternalInterface
|
||||||
|
|
||||||
|
// FILE: file2.kt
|
||||||
|
|
||||||
|
@file:JsExport
|
||||||
|
|
||||||
|
package foo
|
||||||
|
|
||||||
|
val fileLevelExportedVal = 10
|
||||||
|
fun fileLevelExportedFun() = 10
|
||||||
|
class FileLevelExportedClass {
|
||||||
|
val value = 10
|
||||||
|
}
|
||||||
|
external interface FileLevelExportedExternalInterface
|
||||||
|
|
||||||
|
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
"use strict";
|
||||||
|
var foo = JS_TESTS.foo;
|
||||||
|
function box() {
|
||||||
|
var tens = [
|
||||||
|
foo.exportedVal,
|
||||||
|
foo.exportedFun(),
|
||||||
|
new foo.ExportedClass().value,
|
||||||
|
foo.fileLevelExportedVal,
|
||||||
|
foo.fileLevelExportedFun(),
|
||||||
|
new foo.FileLevelExportedClass().value
|
||||||
|
];
|
||||||
|
if (tens.every(function (value) { return value === 10; }))
|
||||||
|
return "OK";
|
||||||
|
return "FAIL";
|
||||||
|
}
|
||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
import foo = JS_TESTS.foo;
|
||||||
|
|
||||||
|
function box(): string {
|
||||||
|
const tens: number[] = [
|
||||||
|
foo.exportedVal,
|
||||||
|
foo.exportedFun(),
|
||||||
|
new foo.ExportedClass().value,
|
||||||
|
foo.fileLevelExportedVal,
|
||||||
|
foo.fileLevelExportedFun(),
|
||||||
|
new foo.FileLevelExportedClass().value
|
||||||
|
];
|
||||||
|
|
||||||
|
if (tens.every((value) => value === 10))
|
||||||
|
return "OK";
|
||||||
|
|
||||||
|
return "FAIL";
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"include": [ "./*" ],
|
||||||
|
"extends": "../common.tsconfig.json"
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"include": [ "./*" ],
|
||||||
|
"extends": "../common.tsconfig.json"
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
declare namespace JS_TESTS {
|
||||||
|
type Nullable<T> = T | null | undefined
|
||||||
|
interface publicInterface {
|
||||||
|
}
|
||||||
|
const publicVal: number;
|
||||||
|
function publicFun(): number
|
||||||
|
class publicClass {
|
||||||
|
constructor()
|
||||||
|
}
|
||||||
|
class Class {
|
||||||
|
constructor()
|
||||||
|
readonly publicVal: number;
|
||||||
|
publicFun(): number
|
||||||
|
}
|
||||||
|
namespace Class {
|
||||||
|
class publicClass {
|
||||||
|
constructor()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
// TARGET_BACKEND: JS_IR
|
||||||
|
// CHECK_TYPESCRIPT_DECLARATIONS
|
||||||
|
// RUN_PLAIN_BOX_FUNCTION
|
||||||
|
|
||||||
|
@file:JsExport
|
||||||
|
|
||||||
|
internal val internalVal = 10
|
||||||
|
internal fun internalFun() = 10
|
||||||
|
internal class internalClass
|
||||||
|
internal external interface internalInterface
|
||||||
|
|
||||||
|
private val privateVal = 10
|
||||||
|
private fun privateFun() = 10
|
||||||
|
private class privateClass
|
||||||
|
private external interface privateInterface
|
||||||
|
|
||||||
|
public val publicVal = 10
|
||||||
|
public fun publicFun() = 10
|
||||||
|
public class publicClass
|
||||||
|
public external interface publicInterface
|
||||||
|
|
||||||
|
open class Class {
|
||||||
|
internal val internalVal = 10
|
||||||
|
internal fun internalFun() = 10
|
||||||
|
internal class internalClass
|
||||||
|
|
||||||
|
private val privateVal = 10
|
||||||
|
private fun privateFun() = 10
|
||||||
|
private class privateClass
|
||||||
|
|
||||||
|
protected val protectedVal = 10
|
||||||
|
protected fun protectedFun() = 10
|
||||||
|
protected class protectedClass
|
||||||
|
|
||||||
|
public val publicVal = 10
|
||||||
|
public fun publicFun() = 10
|
||||||
|
public class publicClass
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
"use strict";
|
||||||
|
var Class = JS_TESTS.Class;
|
||||||
|
function box() {
|
||||||
|
var tens = [
|
||||||
|
JS_TESTS.publicVal,
|
||||||
|
JS_TESTS.publicFun(),
|
||||||
|
new JS_TESTS.Class().publicVal,
|
||||||
|
new JS_TESTS.Class().publicFun()
|
||||||
|
];
|
||||||
|
if (!tens.every(function (value) { return value === 10; }))
|
||||||
|
return "Fail 1";
|
||||||
|
if (!(new Class() instanceof Class))
|
||||||
|
return "Fail 2";
|
||||||
|
if (!(new Class.publicClass() instanceof Class.publicClass))
|
||||||
|
return "Fail 3";
|
||||||
|
return "OK";
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import Class = JS_TESTS.Class;
|
||||||
|
|
||||||
|
function box(): string {
|
||||||
|
const tens: number[] = [
|
||||||
|
JS_TESTS.publicVal,
|
||||||
|
JS_TESTS.publicFun(),
|
||||||
|
new JS_TESTS.Class().publicVal,
|
||||||
|
new JS_TESTS.Class().publicFun()
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!tens.every(value => value === 10))
|
||||||
|
return "Fail 1";
|
||||||
|
if (!(new Class() instanceof Class))
|
||||||
|
return "Fail 2";
|
||||||
|
if (!(new Class.publicClass() instanceof Class.publicClass))
|
||||||
|
return "Fail 3";
|
||||||
|
return "OK";
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user