[K/JS] feat: add logic under the flag for strict implicit export generating inside d.ts files.
This commit is contained in:
+7
@@ -207,6 +207,13 @@ class K2JSCompilerArguments : CommonCompilerArguments() {
|
||||
)
|
||||
var generateDts: Boolean by FreezableVar(false)
|
||||
|
||||
|
||||
@Argument(
|
||||
value = "-Xstrict-implicit-export-types",
|
||||
description = "Generate strict types for implicitly exported entities inside d.ts files. Available in IR backend only."
|
||||
)
|
||||
var strictImplicitExportType: Boolean by FreezableVar(false)
|
||||
|
||||
@GradleOption(DefaultValues.BooleanTrueDefault::class)
|
||||
@Argument(value = "-Xtyped-arrays", description = "Translate primitive arrays to JS typed arrays")
|
||||
var typedArrays: Boolean by FreezableVar(true)
|
||||
|
||||
@@ -503,6 +503,9 @@ class K2JsIrCompiler : CLICompiler<K2JSCompilerArguments>() {
|
||||
|
||||
configuration.put(JSConfigurationKeys.FRIEND_PATHS_DISABLED, arguments.friendModulesDisabled)
|
||||
|
||||
configuration.put(JSConfigurationKeys.GENERATE_STRICT_IMPLICIT_EXPORT, arguments.strictImplicitExportType)
|
||||
|
||||
|
||||
val friendModules = arguments.friendModules
|
||||
if (!arguments.friendModulesDisabled && friendModules != null) {
|
||||
val friendPaths = friendModules
|
||||
|
||||
@@ -311,6 +311,8 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC
|
||||
val doNotIntrinsifyAnnotationSymbol = context.symbolTable.referenceClass(context.getJsInternalClass("DoNotIntrinsify"))
|
||||
val jsFunAnnotationSymbol = context.symbolTable.referenceClass(context.getJsInternalClass("JsFun"))
|
||||
|
||||
val jsImplicitExportAnnotationSymbol = context.symbolTable.referenceClass(context.getJsInternalClass("JsImplicitExport"))
|
||||
|
||||
// TODO move CharSequence-related stiff to IntrinsifyCallsLowering
|
||||
val charSequenceClassSymbol = context.symbolTable.referenceClass(context.getClass(FqName("kotlin.CharSequence")))
|
||||
val charSequenceLengthPropertyGetterSymbol by context.lazy2 {
|
||||
|
||||
@@ -798,6 +798,12 @@ private val escapedIdentifiersLowering = makeBodyLoweringPhase(
|
||||
description = "Convert global variables with invalid names access to globalThis member expression"
|
||||
)
|
||||
|
||||
private val implicitlyExportedDeclarationsMarkingLowering = makeDeclarationTransformerPhase(
|
||||
::ImplicitlyExportedDeclarationsMarkingLowering,
|
||||
name = "ImplicitlyExportedDeclarationsMarkingLowering",
|
||||
description = "Add @JsImplicitExport annotation to declarations which are not exported but are used inside other exported declarations as a type"
|
||||
)
|
||||
|
||||
private val cleanupLoweringPhase = makeBodyLoweringPhase(
|
||||
{ CleanupLowering() },
|
||||
name = "CleanupLowering",
|
||||
@@ -920,6 +926,7 @@ val loweringList = listOf<Lowering>(
|
||||
captureStackTraceInThrowablesPhase,
|
||||
callsLoweringPhase,
|
||||
escapedIdentifiersLowering,
|
||||
implicitlyExportedDeclarationsMarkingLowering,
|
||||
cleanupLoweringPhase,
|
||||
// Currently broken due to static members lowering making single-open-class
|
||||
// files non-recognizable as single-class files
|
||||
|
||||
@@ -61,7 +61,6 @@ class ExportedProperty(
|
||||
val irSetter: IrFunction? = null,
|
||||
) : ExportedDeclaration()
|
||||
|
||||
|
||||
// TODO: Cover all cases with frontend and disable error declarations
|
||||
class ErrorDeclaration(val message: String) : ExportedDeclaration()
|
||||
|
||||
|
||||
+72
-19
@@ -22,6 +22,8 @@ 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.js.config.JSConfigurationKeys
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.serialization.js.ModuleKind
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
||||
@@ -53,7 +55,7 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
|
||||
|
||||
private fun exportDeclaration(declaration: IrDeclaration): ExportedDeclaration? {
|
||||
val candidate = getExportCandidate(declaration) ?: return null
|
||||
if (!shouldDeclarationBeExported(candidate, context)) return null
|
||||
if (!shouldDeclarationBeExportedImplicitlyOrExplicitly(candidate, context)) return null
|
||||
|
||||
return when (candidate) {
|
||||
is IrSimpleFunction -> exportFunction(candidate)
|
||||
@@ -74,9 +76,10 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun exportFunction(function: IrSimpleFunction): ExportedDeclaration? {
|
||||
return when (val exportability = functionExportability(function)) {
|
||||
is Exportability.NotNeeded -> null
|
||||
is Exportability.NotNeeded, is Exportability.Implicit -> null
|
||||
is Exportability.Prohibited -> ErrorDeclaration(exportability.reason)
|
||||
is Exportability.Allowed -> {
|
||||
val parent = function.parent
|
||||
@@ -201,18 +204,44 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
|
||||
}
|
||||
}
|
||||
|
||||
if (klass.isJsImplicitExport()) {
|
||||
return Exportability.Implicit
|
||||
}
|
||||
|
||||
if (klass.isSingleFieldValueClass)
|
||||
return Exportability.Prohibited("Inline class ${klass.fqNameWhenAvailable}")
|
||||
|
||||
return Exportability.Allowed
|
||||
}
|
||||
|
||||
private fun exportDeclarationImplicitly(klass: IrClass, superTypes: Iterable<IrType>): ExportedDeclaration {
|
||||
val typeParameters = klass.typeParameters.map(::exportTypeParameter)
|
||||
val superInterfaces = superTypes
|
||||
.filter { (it.classifierOrFail.owner as? IrDeclaration)?.isExportedImplicitlyOrExplicitly(context) ?: false }
|
||||
.map { exportType(it) }
|
||||
.filter { it !is ExportedType.ErrorType }
|
||||
|
||||
val name = klass.getExportedIdentifier()
|
||||
val (members, nestedClasses) = exportClassDeclarations(klass, superTypes)
|
||||
return ExportedRegularClass(
|
||||
name = name,
|
||||
isInterface = true,
|
||||
isAbstract = false,
|
||||
superClasses = emptyList(),
|
||||
superInterfaces = superInterfaces,
|
||||
typeParameters = typeParameters,
|
||||
members = members,
|
||||
nestedClasses = nestedClasses,
|
||||
ir = klass
|
||||
)
|
||||
}
|
||||
|
||||
private fun exportOrdinaryClass(klass: IrClass, superTypes: Iterable<IrType>): ExportedDeclaration? {
|
||||
when (val exportability = classExportability(klass)) {
|
||||
is Exportability.Prohibited -> error(exportability.reason)
|
||||
is Exportability.NotNeeded -> return null
|
||||
Exportability.Allowed -> {
|
||||
}
|
||||
Exportability.NotNeeded -> return null
|
||||
Exportability.Implicit -> return exportDeclarationImplicitly(klass, superTypes)
|
||||
Exportability.Allowed -> {}
|
||||
}
|
||||
|
||||
val (members, nestedClasses) = exportClassDeclarations(klass, superTypes)
|
||||
@@ -228,9 +257,9 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
|
||||
private fun exportEnumClass(klass: IrClass, superTypes: Iterable<IrType>): ExportedDeclaration? {
|
||||
when (val exportability = classExportability(klass)) {
|
||||
is Exportability.Prohibited -> error(exportability.reason)
|
||||
is Exportability.NotNeeded -> return null
|
||||
Exportability.Allowed -> {
|
||||
}
|
||||
Exportability.NotNeeded -> return null
|
||||
Exportability.Implicit -> return exportDeclarationImplicitly(klass, superTypes)
|
||||
Exportability.Allowed -> {}
|
||||
}
|
||||
|
||||
val enumEntries = klass
|
||||
@@ -267,10 +296,12 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
|
||||
): ExportedClassDeclarationsInfo {
|
||||
val members = mutableListOf<ExportedDeclaration>()
|
||||
val nestedClasses = mutableListOf<ExportedClass>()
|
||||
val isImplicitlyExportedClass = klass.isJsImplicitExport()
|
||||
|
||||
for (declaration in klass.declarations) {
|
||||
val candidate = getExportCandidate(declaration) ?: continue
|
||||
if (!shouldDeclarationBeExported(candidate, context)) continue
|
||||
if (isImplicitlyExportedClass && candidate !is IrClass) continue
|
||||
if (!shouldDeclarationBeExportedImplicitlyOrExplicitly(candidate, context)) continue
|
||||
|
||||
val processingResult = specialProcessing(candidate)
|
||||
if (processingResult != null) {
|
||||
@@ -324,13 +355,13 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
|
||||
}
|
||||
|
||||
private fun IrClass.shouldNotBeImplemented(): Boolean {
|
||||
return isInterface && !isExternal
|
||||
return isInterface && !isExternal || isJsImplicitExport()
|
||||
}
|
||||
|
||||
private fun IrClass.shouldContainImplementationOfMagicProperty(superTypes: Iterable<IrType>): Boolean {
|
||||
return !isExternal && superTypes.any {
|
||||
val superClass = it.classOrNull?.owner ?: return@any false
|
||||
superClass.isInterface && superClass.isExported(context)
|
||||
superClass.isInterface && superClass.isExported(context) || superClass.isJsImplicitExport()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,11 +370,13 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
|
||||
}
|
||||
|
||||
private fun MutableList<ExportedDeclaration>.addMagicPropertyForInterfaceImplementation(klass: IrClass, superTypes: Iterable<IrType>) {
|
||||
val superTypesToInheritanceMagicProperty = superTypes.filter { it.shouldAddMagicPropertyOfSuper() }
|
||||
val allSuperTypesWithMagicProperty = superTypes.filter { it.shouldAddMagicPropertyOfSuper() }
|
||||
|
||||
if (superTypesToInheritanceMagicProperty.isEmpty()) return
|
||||
if (allSuperTypesWithMagicProperty.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
val intersectionOfTypes = superTypesToInheritanceMagicProperty
|
||||
val intersectionOfTypes = allSuperTypesWithMagicProperty
|
||||
.map { ExportedType.PropertyType(exportType(it), ExportedType.LiteralType.StringLiteralType(magicPropertyName)) }
|
||||
.reduce(ExportedType::IntersectionType)
|
||||
.let { if (klass.shouldNotBeImplemented()) ExportedType.IntersectionType(klass.generateTagType(), it) else it }
|
||||
@@ -356,8 +389,11 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
|
||||
}
|
||||
|
||||
private fun IrClass.isOwnMagicPropertyAdded(): Boolean {
|
||||
if (isJsImplicitExport()) return true
|
||||
if (!isExported(context)) return false
|
||||
return isInterface && !isExternal || superTypes.any { it.classOrNull?.owner?.isOwnMagicPropertyAdded() ?: false }
|
||||
return isInterface && !isExternal || superTypes.any {
|
||||
it.classOrNull?.owner?.isOwnMagicPropertyAdded() == true
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrClass.generateTagType(): ExportedType {
|
||||
@@ -388,7 +424,7 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
|
||||
.filter { it !is ExportedType.ErrorType }
|
||||
|
||||
val superInterfaces = superTypes
|
||||
.filter { it.classifierOrFail.isInterface }
|
||||
.filter { it.shouldPresentInsideImplementsClause() }
|
||||
.map { exportType(it, false) }
|
||||
.filter { it !is ExportedType.ErrorType }
|
||||
|
||||
@@ -419,9 +455,14 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrSimpleType.collectSuperTransitiveHierarchy() =
|
||||
private fun IrSimpleType.collectSuperTransitiveHierarchy(): Set<IrType> =
|
||||
transitiveExportCollector.collectSuperTypesTransitiveHierarchyFor(this)
|
||||
|
||||
private fun IrType.shouldPresentInsideImplementsClause(): Boolean {
|
||||
val classifier = classifierOrFail
|
||||
return classifier.isInterface || (classifier.owner as? IrDeclaration)?.isJsImplicitExport() == true
|
||||
}
|
||||
|
||||
private fun exportAsEnumMember(
|
||||
candidate: IrDeclarationWithName,
|
||||
enumEntriesToOrdinal: Map<IrEnumEntry, Int>
|
||||
@@ -460,7 +501,9 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
|
||||
}
|
||||
|
||||
private fun IrType.canBeUsedAsSuperTypeOfExportedClasses(): Boolean =
|
||||
!this.isAny() && classifierOrNull != context.irBuiltIns.enumClass
|
||||
!isAny() &&
|
||||
classifierOrNull != context.irBuiltIns.enumClass &&
|
||||
(classifierOrNull?.owner as? IrDeclaration)?.isJsImplicitExport() != true
|
||||
|
||||
private fun exportTypeArgument(type: IrTypeArgument): ExportedType {
|
||||
if (type is IrTypeProjection)
|
||||
@@ -541,7 +584,7 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
|
||||
|
||||
classifier is IrClassSymbol -> {
|
||||
val klass = classifier.owner
|
||||
val isExported = klass.isExported(context)
|
||||
val isExported = klass.isExportedImplicitlyOrExplicitly(context)
|
||||
val isImplicitlyExported = !isExported && !klass.isExternal
|
||||
val isNonExportedExternal = klass.isExternal && !isExported
|
||||
val name = klass.getFqNameWithJsNameWhenAvailable(!isNonExportedExternal && generateNamespacesForPackages).asString()
|
||||
@@ -630,6 +673,7 @@ class ExportModelGenerator(val context: JsIrBackendContext, val generateNamespac
|
||||
sealed class Exportability {
|
||||
object Allowed : Exportability()
|
||||
object NotNeeded : Exportability()
|
||||
object Implicit : Exportability()
|
||||
class Prohibited(val reason: String) : Exportability()
|
||||
}
|
||||
|
||||
@@ -670,6 +714,10 @@ private fun getExportCandidate(declaration: IrDeclaration): IrDeclarationWithNam
|
||||
return declaration
|
||||
}
|
||||
|
||||
private fun shouldDeclarationBeExportedImplicitlyOrExplicitly(declaration: IrDeclarationWithName, context: JsIrBackendContext): Boolean {
|
||||
return declaration.isJsImplicitExport() || shouldDeclarationBeExported(declaration, context)
|
||||
}
|
||||
|
||||
private fun shouldDeclarationBeExported(declaration: IrDeclarationWithName, context: JsIrBackendContext): Boolean {
|
||||
if (context.additionalExportedDeclarationNames.contains(declaration.fqNameWhenAvailable))
|
||||
return true
|
||||
@@ -727,6 +775,11 @@ fun IrDeclaration.isExported(context: JsIrBackendContext): Boolean {
|
||||
return shouldDeclarationBeExported(candidate, context)
|
||||
}
|
||||
|
||||
fun IrDeclaration.isExportedImplicitlyOrExplicitly(context: JsIrBackendContext): Boolean {
|
||||
val candidate = getExportCandidate(this) ?: return false
|
||||
return shouldDeclarationBeExportedImplicitlyOrExplicitly(candidate, context)
|
||||
}
|
||||
|
||||
private fun DescriptorVisibility.toExportedVisibility() =
|
||||
when (this) {
|
||||
DescriptorVisibilities.PROTECTED -> ExportedVisibility.PROTECTED
|
||||
|
||||
+19
-2
@@ -12,6 +12,10 @@ import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.isJsImplicitExport
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.superTypes
|
||||
|
||||
private typealias SubstitutionMap = Map<IrTypeParameterSymbol, IrType>
|
||||
|
||||
@@ -34,13 +38,26 @@ class TransitiveExportCollector(val context: JsIrBackendContext) {
|
||||
.toSet()
|
||||
}
|
||||
|
||||
private fun IrSimpleType.findNearestExportedClass(typeSubstitutionMap: SubstitutionMap): IrSimpleType? {
|
||||
val classifier = classifier as? IrClassSymbol ?: return null
|
||||
if (classifier.owner.isExported(context)) return substitute(typeSubstitutionMap) as IrSimpleType
|
||||
|
||||
return classifier.superTypes()
|
||||
.firstNotNullOfOrNull { (it as? IrSimpleType)?.findNearestExportedClass(typeSubstitutionMap) }
|
||||
}
|
||||
|
||||
private fun IrSimpleType.collectTransitiveHierarchy(typeSubstitutionMap: SubstitutionMap): Set<IrType> {
|
||||
val owner = classifier.owner as? IrClass ?: return emptySet()
|
||||
val substitutionMap = calculateTypeSubstitutionMap(typeSubstitutionMap)
|
||||
|
||||
return when {
|
||||
isBuiltInClass(owner) || isStdLibClass(owner) -> emptySet()
|
||||
owner.isExported(context) -> setOf(substitute(typeSubstitutionMap))
|
||||
owner.isExported(context) -> setOf(substitute(substitutionMap))
|
||||
owner.isJsImplicitExport() -> setOfNotNull(
|
||||
substitute(typeSubstitutionMap),
|
||||
takeIf { !owner.isInterface }?.findNearestExportedClass(substitutionMap)
|
||||
)
|
||||
|
||||
else -> collectSuperTypesTransitiveHierarchy(substitutionMap)
|
||||
}
|
||||
}
|
||||
@@ -62,4 +79,4 @@ class TransitiveExportCollector(val context: JsIrBackendContext) {
|
||||
}
|
||||
|
||||
private data class ClassWithAppliedArguments(val classSymbol: IrClassSymbol, val appliedArguments: List<IrTypeArgument>)
|
||||
}
|
||||
}
|
||||
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2010-2021 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.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.DeclarationTransformer
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.export.isExported
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.isJsImplicitExport
|
||||
import org.jetbrains.kotlin.ir.builders.irCall
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.constructors
|
||||
import org.jetbrains.kotlin.ir.util.isPrimitiveArray
|
||||
import org.jetbrains.kotlin.ir.util.parentClassOrNull
|
||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||
|
||||
class ImplicitlyExportedDeclarationsMarkingLowering(private val context: JsIrBackendContext) : DeclarationTransformer {
|
||||
private val strictImplicitExport = context.configuration.getBoolean(JSConfigurationKeys.GENERATE_STRICT_IMPLICIT_EXPORT)
|
||||
|
||||
override fun transformFlat(declaration: IrDeclaration): List<IrDeclaration>? {
|
||||
if (!strictImplicitExport || !declaration.isExported(context)) return null
|
||||
|
||||
val implicitlyExportedDeclarations = when (declaration) {
|
||||
is IrFunction -> declaration.collectImplicitlyExportedDeclarations()
|
||||
is IrClass -> declaration.collectImplicitlyExportedDeclarations()
|
||||
is IrProperty -> declaration.collectImplicitlyExportedDeclarations()
|
||||
else -> emptySet()
|
||||
}
|
||||
|
||||
implicitlyExportedDeclarations.forEach { it.markWithJsImplicitExport() }
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private fun IrClass.collectImplicitlyExportedDeclarations(): Set<IrDeclaration> {
|
||||
return typeParameters
|
||||
.flatMap { it.superTypes }.toSet()
|
||||
.flatMap { it.collectImplicitlyExportedDeclarations() }.toSet()
|
||||
}
|
||||
|
||||
|
||||
private fun IrFunction.collectImplicitlyExportedDeclarations(): Set<IrDeclaration> {
|
||||
val types = buildSet {
|
||||
add(returnType)
|
||||
addAll(valueParameters.map { it.type })
|
||||
addAll(typeParameters.flatMap { it.superTypes })
|
||||
}
|
||||
|
||||
return types.flatMap { it.collectImplicitlyExportedDeclarations() }.toSet()
|
||||
}
|
||||
|
||||
private fun IrProperty.collectImplicitlyExportedDeclarations(): Set<IrDeclaration> {
|
||||
val getterImplicitlyExportedDeclarations = getter?.collectImplicitlyExportedDeclarations() ?: emptySet()
|
||||
val setterImplicitlyExportedDeclarations = setter?.collectImplicitlyExportedDeclarations() ?: emptySet()
|
||||
val fieldImplicitlyExportedDeclarations = backingField?.type?.collectImplicitlyExportedDeclarations() ?: emptySet()
|
||||
|
||||
return getterImplicitlyExportedDeclarations + setterImplicitlyExportedDeclarations + fieldImplicitlyExportedDeclarations
|
||||
}
|
||||
|
||||
private fun IrType.collectImplicitlyExportedDeclarations(): Set<IrDeclaration> {
|
||||
if (this is IrDynamicType || this !is IrSimpleType)
|
||||
return emptySet()
|
||||
|
||||
val nonNullType = makeNotNull() as IrSimpleType
|
||||
val classifier = nonNullType.classifier
|
||||
|
||||
return when {
|
||||
nonNullType.isPrimitiveType() || nonNullType.isPrimitiveArray() || nonNullType.isAny() || nonNullType.isUnit() -> emptySet()
|
||||
classifier is IrTypeParameterSymbol -> classifier.owner.superTypes.flatMap { it.collectImplicitlyExportedDeclarations() }
|
||||
.toSet()
|
||||
|
||||
classifier is IrClassSymbol -> setOfNotNull(classifier.owner.takeIf { it.shouldBeMarkedWithImplicitExport() })
|
||||
else -> emptySet()
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrDeclaration.shouldBeMarkedWithImplicitExport(): Boolean {
|
||||
return this is IrClass && !isExternal && !isExported(context) && !isJsImplicitExport()
|
||||
}
|
||||
|
||||
private fun IrDeclaration.markWithJsImplicitExport() {
|
||||
val jsImplicitExportCtor = context.intrinsics.jsImplicitExportAnnotationSymbol.constructors.single()
|
||||
annotations += context.createIrBuilder(symbol).irCall(jsImplicitExportCtor)
|
||||
|
||||
parentClassOrNull?.takeIf { it.shouldBeMarkedWithImplicitExport() }?.markWithJsImplicitExport()
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ object JsAnnotations {
|
||||
val jsNameFqn = FqName("kotlin.js.JsName")
|
||||
val jsQualifierFqn = FqName("kotlin.js.JsQualifier")
|
||||
val jsExportFqn = FqName("kotlin.js.JsExport")
|
||||
val jsImplicitExportFqn = FqName("kotlin.js.JsImplicitExport")
|
||||
val jsNativeGetter = FqName("kotlin.js.nativeGetter")
|
||||
val jsNativeSetter = FqName("kotlin.js.nativeSetter")
|
||||
val jsNativeInvoke = FqName("kotlin.js.nativeInvoke")
|
||||
@@ -34,6 +35,10 @@ object JsAnnotations {
|
||||
fun IrConstructorCall.getSingleConstStringArgument() =
|
||||
(getValueArgument(0) as IrConst<String>).value
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun IrConstructorCall.getSingleConstBooleanArgument() =
|
||||
(getValueArgument(0) as IrConst<Boolean>).value
|
||||
|
||||
fun IrAnnotationContainer.getJsModule(): String? =
|
||||
getAnnotation(JsAnnotations.jsModuleFqn)?.getSingleConstStringArgument()
|
||||
|
||||
@@ -58,6 +63,9 @@ fun IrAnnotationContainer.getJsFunAnnotation(): String? =
|
||||
fun IrAnnotationContainer.isJsExport(): Boolean =
|
||||
hasAnnotation(JsAnnotations.jsExportFqn)
|
||||
|
||||
fun IrAnnotationContainer.isJsImplicitExport(): Boolean =
|
||||
hasAnnotation(JsAnnotations.jsImplicitExportFqn)
|
||||
|
||||
fun IrAnnotationContainer.isJsNativeGetter(): Boolean = hasAnnotation(JsAnnotations.jsNativeGetter)
|
||||
|
||||
fun IrAnnotationContainer.isJsNativeSetter(): Boolean = hasAnnotation(JsAnnotations.jsNativeSetter)
|
||||
|
||||
+1
@@ -38,6 +38,7 @@ where advanced options include:
|
||||
-Xmetadata-only Generate *.meta.js and *.kjsm files only
|
||||
-Xpartial-linkage Allow unlinked symbols
|
||||
-Xrepositories=<path> Paths to additional places where libraries could be found
|
||||
-Xstrict-implicit-export-types Generate strict types for implicitly exported entities inside d.ts files. Available in IR backend only.
|
||||
-Xtyped-arrays Translate primitive arrays to JS typed arrays
|
||||
-Xwasm Use experimental WebAssembly compiler backend
|
||||
-Xwasm-debug-info Add debug info to WebAssembly compiled module
|
||||
|
||||
+5
@@ -117,6 +117,11 @@ object JsEnvironmentConfigurationDirectives : SimpleDirectivesContainer() {
|
||||
applicability = DirectiveApplicability.Global
|
||||
)
|
||||
|
||||
val GENERATE_STRICT_IMPLICIT_EXPORT by directive(
|
||||
description = "enable strict implicitly exported entities types inside d.ts files",
|
||||
applicability = DirectiveApplicability.Global
|
||||
)
|
||||
|
||||
val SAFE_EXTERNAL_BOOLEAN by directive(
|
||||
description = "",
|
||||
applicability = DirectiveApplicability.Global
|
||||
|
||||
+5
@@ -125,6 +125,11 @@ fun TargetPlatform.platformToEnvironmentConfigFiles() = when {
|
||||
fun createCompilerConfiguration(module: TestModule, configurators: List<AbstractEnvironmentConfigurator>): CompilerConfiguration {
|
||||
val configuration = CompilerConfiguration()
|
||||
configuration[CommonConfigurationKeys.MODULE_NAME] = module.name
|
||||
|
||||
if (JsEnvironmentConfigurationDirectives.GENERATE_STRICT_IMPLICIT_EXPORT in module.directives) {
|
||||
configuration.put(JSConfigurationKeys.GENERATE_STRICT_IMPLICIT_EXPORT, true)
|
||||
}
|
||||
|
||||
if (module.frontendKind == FrontendKinds.FIR) {
|
||||
configuration[CommonConfigurationKeys.USE_FIR] = true
|
||||
}
|
||||
|
||||
@@ -103,6 +103,9 @@ public class JSConfigurationKeys {
|
||||
public static final CompilerConfigurationKey<Boolean> GENERATE_INLINE_ANONYMOUS_FUNCTIONS =
|
||||
CompilerConfigurationKey.create("translate lambdas into in-line anonymous functions");
|
||||
|
||||
public static final CompilerConfigurationKey<Boolean> GENERATE_STRICT_IMPLICIT_EXPORT =
|
||||
CompilerConfigurationKey.create("enable strict implicitly exported entities types inside d.ts files");
|
||||
|
||||
public static final CompilerConfigurationKey<Boolean> WASM_ENABLE_ARRAY_RANGE_CHECKS =
|
||||
CompilerConfigurationKey.create("enable array range checks");
|
||||
|
||||
|
||||
Generated
+16
@@ -373,6 +373,22 @@ public class IrJsTypeScriptExportTestGenerated extends AbstractIrJsTypeScriptExp
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("js/js.translator/testData/typescript-export/strictImplicitExport")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class StrictImplicitExport {
|
||||
@Test
|
||||
public void testAllFilesPresentInStrictImplicitExport() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/typescript-export/strictImplicitExport"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("declarations.kt")
|
||||
public void testDeclarations() throws Exception {
|
||||
runTest("js/js.translator/testData/typescript-export/strictImplicitExport/declarations.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("js/js.translator/testData/typescript-export/visibility")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+1
@@ -41,5 +41,6 @@ declare namespace JS_TESTS {
|
||||
function bar(): Error;
|
||||
const console: Console;
|
||||
const error: WebAssembly.CompileError;
|
||||
function functionWithTypeAliasInside(x: any/* foo.NonExportedGenericInterface<foo.NonExportedType> */): any/* foo.NonExportedGenericInterface<foo.NonExportedType> */;
|
||||
}
|
||||
}
|
||||
|
||||
+8
-1
@@ -85,4 +85,11 @@ val console: Console
|
||||
|
||||
@JsExport
|
||||
val error: CompileError
|
||||
get() = js("{}")
|
||||
get() = js("{}")
|
||||
|
||||
typealias NotExportedTypeAlias = NonExportedGenericInterface<NonExportedType>
|
||||
|
||||
@JsExport
|
||||
fun functionWithTypeAliasInside(x: NotExportedTypeAlias): NotExportedTypeAlias {
|
||||
return x
|
||||
}
|
||||
@@ -18,4 +18,4 @@ declare namespace JS_TESTS {
|
||||
inlineFun(x: number, callback: (p0: number) => void): void;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
declare namespace JS_TESTS {
|
||||
type Nullable<T> = T | null | undefined
|
||||
namespace foo {
|
||||
const forth: foo.Forth;
|
||||
interface ExportedInterface {
|
||||
readonly __doNotUseOrImplementIt: {
|
||||
readonly "foo.ExportedInterface": unique symbol;
|
||||
};
|
||||
}
|
||||
function producer(value: number): foo.NonExportedType;
|
||||
function consumer(value: foo.NonExportedType): number;
|
||||
function childProducer(value: number): foo.NotExportedChildClass;
|
||||
function childConsumer(value: foo.NotExportedChildClass): number;
|
||||
function genericChildProducer<T extends foo.NonExportedGenericType<number>>(value: T): foo.NotExportedChildGenericClass<T>;
|
||||
function genericChildConsumer<T extends foo.NonExportedGenericType<number>>(value: foo.NotExportedChildGenericClass<T>): T;
|
||||
class A implements foo.NonExportedParent.NonExportedSecond.NonExportedUsedChild {
|
||||
constructor(value: foo.NonExportedType);
|
||||
get value(): foo.NonExportedType;
|
||||
set value(value: foo.NonExportedType);
|
||||
increment<T extends foo.NonExportedType>(t: T): foo.NonExportedType;
|
||||
getNonExportedUserChild(): foo.NonExportedParent.NonExportedSecond.NonExportedUsedChild;
|
||||
readonly __doNotUseOrImplementIt: foo.NonExportedParent.NonExportedSecond.NonExportedUsedChild["__doNotUseOrImplementIt"];
|
||||
}
|
||||
class B implements foo.NonExportedType {
|
||||
constructor(v: number);
|
||||
readonly __doNotUseOrImplementIt: foo.NonExportedType["__doNotUseOrImplementIt"];
|
||||
}
|
||||
class C implements foo.NonExportedInterface {
|
||||
constructor();
|
||||
readonly __doNotUseOrImplementIt: foo.NonExportedInterface["__doNotUseOrImplementIt"];
|
||||
}
|
||||
class D implements foo.NonExportedInterface, foo.ExportedInterface {
|
||||
constructor();
|
||||
readonly __doNotUseOrImplementIt: foo.NonExportedInterface["__doNotUseOrImplementIt"] & foo.ExportedInterface["__doNotUseOrImplementIt"];
|
||||
}
|
||||
class E implements foo.NonExportedType, foo.ExportedInterface {
|
||||
constructor();
|
||||
readonly __doNotUseOrImplementIt: foo.NonExportedType["__doNotUseOrImplementIt"] & foo.ExportedInterface["__doNotUseOrImplementIt"];
|
||||
}
|
||||
class F extends foo.A implements foo.NonExportedInterface {
|
||||
constructor();
|
||||
readonly __doNotUseOrImplementIt: foo.A["__doNotUseOrImplementIt"] & foo.NonExportedInterface["__doNotUseOrImplementIt"];
|
||||
}
|
||||
class G implements foo.NonExportedGenericInterface<foo.NonExportedType> {
|
||||
constructor();
|
||||
readonly __doNotUseOrImplementIt: foo.NonExportedGenericInterface<foo.NonExportedType>["__doNotUseOrImplementIt"];
|
||||
}
|
||||
class H implements foo.NonExportedGenericType<foo.NonExportedType> {
|
||||
constructor();
|
||||
readonly __doNotUseOrImplementIt: foo.NonExportedGenericType<foo.NonExportedType>["__doNotUseOrImplementIt"];
|
||||
}
|
||||
class I implements foo.NotExportedChildClass {
|
||||
constructor();
|
||||
readonly __doNotUseOrImplementIt: foo.NotExportedChildClass["__doNotUseOrImplementIt"];
|
||||
}
|
||||
class J implements foo.NotExportedChildGenericClass<foo.NonExportedType> {
|
||||
constructor();
|
||||
readonly __doNotUseOrImplementIt: foo.NotExportedChildGenericClass<foo.NonExportedType>["__doNotUseOrImplementIt"];
|
||||
}
|
||||
function baz(a: number): Promise<number>;
|
||||
function bar(): Error;
|
||||
function pep<T extends foo.NonExportedInterface & foo.NonExportedGenericInterface<number>>(x: T): void;
|
||||
const console: Console;
|
||||
const error: WebAssembly.CompileError;
|
||||
interface IA {
|
||||
readonly __doNotUseOrImplementIt: {
|
||||
readonly "foo.IA": unique symbol;
|
||||
};
|
||||
}
|
||||
class Third extends /* foo.Second */ foo.First {
|
||||
constructor();
|
||||
}
|
||||
class Sixth extends /* foo.Fifth */ foo.Third implements foo.Forth, foo.IC {
|
||||
constructor();
|
||||
readonly __doNotUseOrImplementIt: foo.Forth["__doNotUseOrImplementIt"] & foo.IC["__doNotUseOrImplementIt"];
|
||||
}
|
||||
class First {
|
||||
constructor();
|
||||
}
|
||||
function acceptForthLike<T extends foo.Forth>(forth: T): void;
|
||||
function acceptMoreGenericForthLike<T extends foo.IB & foo.IC & foo.Third>(forth: T): void;
|
||||
interface NonExportedParent {
|
||||
readonly __doNotUseOrImplementIt: {
|
||||
readonly "foo.NonExportedParent": unique symbol;
|
||||
};
|
||||
}
|
||||
namespace NonExportedParent {
|
||||
interface NonExportedSecond {
|
||||
readonly __doNotUseOrImplementIt: {
|
||||
readonly "foo.NonExportedParent.NonExportedSecond": unique symbol;
|
||||
};
|
||||
}
|
||||
namespace NonExportedSecond {
|
||||
interface NonExportedUsedChild {
|
||||
readonly __doNotUseOrImplementIt: {
|
||||
readonly "foo.NonExportedParent.NonExportedSecond.NonExportedUsedChild": unique symbol;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
interface NonExportedInterface {
|
||||
readonly __doNotUseOrImplementIt: {
|
||||
readonly "foo.NonExportedInterface": unique symbol;
|
||||
};
|
||||
}
|
||||
interface NonExportedGenericInterface<T> {
|
||||
readonly __doNotUseOrImplementIt: {
|
||||
readonly "foo.NonExportedGenericInterface": unique symbol;
|
||||
};
|
||||
}
|
||||
interface NonExportedType {
|
||||
readonly __doNotUseOrImplementIt: {
|
||||
readonly "foo.NonExportedType": unique symbol;
|
||||
};
|
||||
}
|
||||
interface NonExportedGenericType<T> {
|
||||
readonly __doNotUseOrImplementIt: {
|
||||
readonly "foo.NonExportedGenericType": unique symbol;
|
||||
};
|
||||
}
|
||||
interface NotExportedChildClass extends foo.NonExportedInterface, foo.NonExportedType {
|
||||
readonly __doNotUseOrImplementIt: {
|
||||
readonly "foo.NotExportedChildClass": unique symbol;
|
||||
} & foo.NonExportedInterface["__doNotUseOrImplementIt"] & foo.NonExportedType["__doNotUseOrImplementIt"];
|
||||
}
|
||||
interface NotExportedChildGenericClass<T> extends foo.NonExportedInterface, foo.NonExportedGenericInterface<T>, foo.NonExportedGenericType<T> {
|
||||
readonly __doNotUseOrImplementIt: {
|
||||
readonly "foo.NotExportedChildGenericClass": unique symbol;
|
||||
} & foo.NonExportedInterface["__doNotUseOrImplementIt"] & foo.NonExportedGenericInterface<T>["__doNotUseOrImplementIt"] & foo.NonExportedGenericType<T>["__doNotUseOrImplementIt"];
|
||||
}
|
||||
interface IB extends foo.IA {
|
||||
readonly __doNotUseOrImplementIt: {
|
||||
readonly "foo.IB": unique symbol;
|
||||
} & foo.IA["__doNotUseOrImplementIt"];
|
||||
}
|
||||
interface IC extends foo.IB {
|
||||
readonly __doNotUseOrImplementIt: {
|
||||
readonly "foo.IC": unique symbol;
|
||||
} & foo.IB["__doNotUseOrImplementIt"];
|
||||
}
|
||||
interface Forth extends foo.Third, foo.IB, foo.IC {
|
||||
readonly __doNotUseOrImplementIt: {
|
||||
readonly "foo.Forth": unique symbol;
|
||||
} & foo.IB["__doNotUseOrImplementIt"] & foo.IC["__doNotUseOrImplementIt"];
|
||||
}
|
||||
}
|
||||
}
|
||||
+169
@@ -0,0 +1,169 @@
|
||||
// CHECK_TYPESCRIPT_DECLARATIONS
|
||||
// RUN_PLAIN_BOX_FUNCTION
|
||||
// SKIP_MINIFICATION
|
||||
// SKIP_NODE_JS
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
// INFER_MAIN_MODULE
|
||||
// GENERATE_STRICT_IMPLICIT_EXPORT
|
||||
// MODULE: JS_TESTS
|
||||
// FILE: qualified.kt
|
||||
@file:JsQualifier("WebAssembly")
|
||||
package qualified
|
||||
|
||||
external interface CompileError
|
||||
|
||||
// FILE: notQualified.kt
|
||||
package notQualified
|
||||
|
||||
external interface Console
|
||||
|
||||
// FILE: declarations.kt
|
||||
|
||||
package foo
|
||||
|
||||
import notQualified.Console
|
||||
import qualified.CompileError
|
||||
|
||||
interface NeverUsedInsideExportedDeclarationsType
|
||||
|
||||
open class NonExportedParent {
|
||||
open class NonExportedSecond {
|
||||
open class NonExportedUsedChild
|
||||
open class NonExportedUnusedChild
|
||||
}
|
||||
}
|
||||
|
||||
interface NonExportedInterface
|
||||
interface NonExportedGenericInterface<T>
|
||||
open class NonExportedType(val value: Int)
|
||||
open class NonExportedGenericType<T>(val value: T)
|
||||
|
||||
open class NotExportedChildClass : NonExportedInterface, NeverUsedInsideExportedDeclarationsType, NonExportedType(322)
|
||||
open class NotExportedChildGenericClass<T>(value: T) : NonExportedInterface, NeverUsedInsideExportedDeclarationsType, NonExportedGenericInterface<T>, NonExportedGenericType<T>(value)
|
||||
|
||||
|
||||
@JsExport
|
||||
interface ExportedInterface
|
||||
|
||||
@JsExport
|
||||
fun producer(value: Int): NonExportedType {
|
||||
return NonExportedType(value)
|
||||
}
|
||||
|
||||
@JsExport
|
||||
fun consumer(value: NonExportedType): Int {
|
||||
return value.value
|
||||
}
|
||||
|
||||
@JsExport
|
||||
fun childProducer(value: Int): NotExportedChildClass {
|
||||
return NotExportedChildClass()
|
||||
}
|
||||
|
||||
@JsExport
|
||||
fun childConsumer(value: NotExportedChildClass): Int {
|
||||
return value.value
|
||||
}
|
||||
|
||||
@JsExport
|
||||
fun <T: NonExportedGenericType<Int>> genericChildProducer(value: T): NotExportedChildGenericClass<T> {
|
||||
return NotExportedChildGenericClass<T>(value)
|
||||
}
|
||||
|
||||
@JsExport
|
||||
fun <T: NonExportedGenericType<Int>> genericChildConsumer(value: NotExportedChildGenericClass<T>): T {
|
||||
return value.value
|
||||
}
|
||||
|
||||
@JsExport
|
||||
open class A(var value: NonExportedType): NonExportedParent.NonExportedSecond.NonExportedUsedChild() {
|
||||
fun <T: NonExportedType> increment(t: T): NonExportedType {
|
||||
return NonExportedType(value = t.value + 1)
|
||||
}
|
||||
|
||||
fun getNonExportedUserChild(): NonExportedParent.NonExportedSecond.NonExportedUsedChild {
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
||||
@JsExport
|
||||
class B(v: Int) : NonExportedType(v)
|
||||
|
||||
@JsExport
|
||||
class C : NonExportedInterface
|
||||
|
||||
@JsExport
|
||||
class D : NonExportedInterface, ExportedInterface
|
||||
|
||||
@JsExport
|
||||
class E : NonExportedType(42), ExportedInterface
|
||||
|
||||
@JsExport
|
||||
class F : A(NonExportedType(42)), NonExportedInterface
|
||||
|
||||
@JsExport
|
||||
class G : NonExportedGenericInterface<NonExportedType>
|
||||
|
||||
@JsExport
|
||||
class H : NonExportedGenericType<NonExportedType>(NonExportedType(42))
|
||||
|
||||
@JsExport
|
||||
class I : NotExportedChildClass()
|
||||
|
||||
@JsExport
|
||||
class J : NotExportedChildGenericClass<NonExportedType>(NonExportedType(322))
|
||||
|
||||
@JsExport
|
||||
fun baz(a: Int): kotlin.js.Promise<Int> {
|
||||
return kotlin.js.Promise<Int> { res, rej -> res(a) }
|
||||
}
|
||||
|
||||
@JsExport
|
||||
fun bar(): Throwable {
|
||||
return Throwable("Test Error")
|
||||
}
|
||||
|
||||
@JsExport
|
||||
fun <T> pep(x: T) where T: NonExportedInterface,
|
||||
T: NonExportedGenericInterface<Int>
|
||||
{}
|
||||
|
||||
@JsExport
|
||||
val console: Console
|
||||
get() = js("console")
|
||||
|
||||
@JsExport
|
||||
val error: CompileError
|
||||
get() = js("{}")
|
||||
|
||||
// Save hierarhy
|
||||
|
||||
@JsExport
|
||||
interface IA
|
||||
|
||||
interface IB : IA
|
||||
|
||||
interface IC : IB
|
||||
|
||||
@JsExport
|
||||
open class Third: Second()
|
||||
|
||||
open class Forth: Third(), IB, IC
|
||||
|
||||
open class Fifth: Forth()
|
||||
|
||||
@JsExport
|
||||
class Sixth: Fifth(), IC
|
||||
@JsExport
|
||||
open class First
|
||||
|
||||
open class Second: First()
|
||||
|
||||
@JsExport
|
||||
fun <T : Forth> acceptForthLike(forth: T) {}
|
||||
|
||||
@JsExport
|
||||
fun <T> acceptMoreGenericForthLike(forth: T) where T: IB, T: IC, T: Third {}
|
||||
|
||||
@JsExport
|
||||
val forth = Forth()
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
"use strict";
|
||||
var producer = JS_TESTS.foo.producer;
|
||||
var consumer = JS_TESTS.foo.consumer;
|
||||
var A = JS_TESTS.foo.A;
|
||||
var B = JS_TESTS.foo.B;
|
||||
var childProducer = JS_TESTS.foo.childProducer;
|
||||
var childConsumer = JS_TESTS.foo.childConsumer;
|
||||
var genericChildProducer = JS_TESTS.foo.genericChildProducer;
|
||||
var genericChildConsumer = JS_TESTS.foo.genericChildConsumer;
|
||||
function assert(condition) {
|
||||
if (!condition) {
|
||||
throw "Assertion failed";
|
||||
}
|
||||
}
|
||||
function box() {
|
||||
var nonExportedType = producer(42);
|
||||
var a = new A(nonExportedType);
|
||||
var b = new B(43);
|
||||
assert(consumer(nonExportedType) == 42);
|
||||
a.value = producer(24);
|
||||
assert(consumer(b) == 43);
|
||||
assert(consumer(a.value) == 24);
|
||||
assert(consumer(a.increment(nonExportedType)) == 43);
|
||||
var oneMoreNonExportedType = childProducer(322);
|
||||
assert(consumer(oneMoreNonExportedType) == 322);
|
||||
assert(childConsumer(oneMoreNonExportedType) == 322);
|
||||
return "OK";
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
import producer = JS_TESTS.foo.producer;
|
||||
import consumer = JS_TESTS.foo.consumer;
|
||||
import A = JS_TESTS.foo.A;
|
||||
import B = JS_TESTS.foo.B;
|
||||
import childProducer = JS_TESTS.foo.childProducer;
|
||||
import childConsumer = JS_TESTS.foo.childConsumer;
|
||||
import genericChildProducer = JS_TESTS.foo.genericChildProducer;
|
||||
import genericChildConsumer = JS_TESTS.foo.genericChildConsumer;
|
||||
|
||||
function assert(condition: boolean) {
|
||||
if (!condition) {
|
||||
throw "Assertion failed";
|
||||
}
|
||||
}
|
||||
|
||||
function box(): string {
|
||||
const nonExportedType = producer(42)
|
||||
const a = new A(nonExportedType)
|
||||
const b = new B(43)
|
||||
|
||||
assert(consumer(nonExportedType) == 42)
|
||||
|
||||
a.value = producer(24)
|
||||
assert(consumer(b) == 43)
|
||||
assert(consumer(a.value) == 24)
|
||||
assert(consumer(a.increment(nonExportedType)) == 43)
|
||||
|
||||
const oneMoreNonExportedType = childProducer(322)
|
||||
assert(consumer(oneMoreNonExportedType) == 322)
|
||||
assert(childConsumer(oneMoreNonExportedType) == 322)
|
||||
|
||||
return "OK";
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"include": [ "./*" ],
|
||||
"extends": "../common.tsconfig.json"
|
||||
}
|
||||
@@ -42,4 +42,12 @@ internal fun safePropertySet(self: dynamic, setterName: String, propName: String
|
||||
* Code gets inserted as is without syntax verification.
|
||||
*/
|
||||
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
|
||||
internal annotation class JsFun(val code: String)
|
||||
internal annotation class JsFun(val code: String)
|
||||
|
||||
/**
|
||||
* The annotation is needed for annotating class declarations and type alias which are used inside exported declarations, but
|
||||
* doesn't contain @JsExport annotation
|
||||
* This information is used for generating special tagged types inside d.ts files, for more strict usage of implicitly exported entities
|
||||
*/
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class JsImplicitExport()
|
||||
|
||||
Reference in New Issue
Block a user