[K/JS] Add file-to-file compilation ^KT-6168 Fixed
This commit is contained in:
@@ -210,6 +210,13 @@ public final annotation class ExperimentalJsExport : kotlin.Annotation {
|
||||
public constructor ExperimentalJsExport()
|
||||
}
|
||||
|
||||
@kotlin.RequiresOptIn(level = Level.WARNING)
|
||||
@kotlin.annotation.MustBeDocumented
|
||||
@kotlin.annotation.Retention(value = AnnotationRetention.BINARY)
|
||||
public final annotation class ExperimentalJsFileName : kotlin.Annotation {
|
||||
public constructor ExperimentalJsFileName()
|
||||
}
|
||||
|
||||
public external object JSON {
|
||||
public final fun <T> parse(text: kotlin.String): T
|
||||
|
||||
@@ -266,6 +273,14 @@ public final annotation class JsExternalInheritorsOnly : kotlin.Annotation {
|
||||
public constructor JsExternalInheritorsOnly()
|
||||
}
|
||||
|
||||
@kotlin.annotation.Retention(value = AnnotationRetention.BINARY)
|
||||
@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.FILE})
|
||||
public final annotation class JsFileName : kotlin.Annotation {
|
||||
public constructor JsFileName(name: kotlin.String)
|
||||
|
||||
public final val name: kotlin.String { get; }
|
||||
}
|
||||
|
||||
@kotlin.annotation.Retention(value = AnnotationRetention.BINARY)
|
||||
@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.FILE})
|
||||
public final annotation class JsModule : kotlin.Annotation {
|
||||
@@ -275,7 +290,7 @@ public final annotation class JsModule : kotlin.Annotation {
|
||||
}
|
||||
|
||||
@kotlin.annotation.Retention(value = AnnotationRetention.BINARY)
|
||||
@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER})
|
||||
@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.FILE, AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER})
|
||||
public final annotation class JsName : kotlin.Annotation {
|
||||
public constructor JsName(name: kotlin.String)
|
||||
|
||||
|
||||
@@ -209,6 +209,13 @@ public final annotation class ExperimentalJsExport : kotlin.Annotation {
|
||||
public constructor ExperimentalJsExport()
|
||||
}
|
||||
|
||||
@kotlin.RequiresOptIn(level = Level.WARNING)
|
||||
@kotlin.annotation.MustBeDocumented
|
||||
@kotlin.annotation.Retention(value = AnnotationRetention.BINARY)
|
||||
public final annotation class ExperimentalJsFileName : kotlin.Annotation {
|
||||
public constructor ExperimentalJsFileName()
|
||||
}
|
||||
|
||||
public external object JSON {
|
||||
public final fun <T> parse(text: kotlin.String): T
|
||||
|
||||
@@ -265,6 +272,14 @@ public final annotation class JsExternalInheritorsOnly : kotlin.Annotation {
|
||||
public constructor JsExternalInheritorsOnly()
|
||||
}
|
||||
|
||||
@kotlin.annotation.Retention(value = AnnotationRetention.BINARY)
|
||||
@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.FILE})
|
||||
public final annotation class JsFileName : kotlin.Annotation {
|
||||
public constructor JsFileName(name: kotlin.String)
|
||||
|
||||
public final val name: kotlin.String { get; }
|
||||
}
|
||||
|
||||
@kotlin.annotation.Retention(value = AnnotationRetention.BINARY)
|
||||
@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.FILE})
|
||||
public final annotation class JsModule : kotlin.Annotation {
|
||||
@@ -274,7 +289,7 @@ public final annotation class JsModule : kotlin.Annotation {
|
||||
}
|
||||
|
||||
@kotlin.annotation.Retention(value = AnnotationRetention.BINARY)
|
||||
@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER})
|
||||
@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.FILE, AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER})
|
||||
public final annotation class JsName : kotlin.Annotation {
|
||||
public constructor JsName(name: kotlin.String)
|
||||
|
||||
|
||||
@@ -10,10 +10,34 @@ import kotlin.annotation.AnnotationTarget.*
|
||||
/**
|
||||
* Gives a declaration (a function, a property or a class) specific name in JavaScript.
|
||||
*/
|
||||
@Target(CLASS, FUNCTION, PROPERTY, CONSTRUCTOR, PROPERTY_GETTER, PROPERTY_SETTER)
|
||||
@Target(FILE, CLASS, FUNCTION, PROPERTY, CONSTRUCTOR, PROPERTY_GETTER, PROPERTY_SETTER)
|
||||
@OptionalExpectation
|
||||
public expect annotation class JsName(val name: String)
|
||||
|
||||
/**
|
||||
* Marks experimental [JsFileName] annotation.
|
||||
*
|
||||
* Note that behavior of these annotations will likely be changed in the future.
|
||||
*
|
||||
* Usages of such annotations will be reported as warnings unless an explicit opt-in with
|
||||
* the [OptIn] annotation, e.g. `@OptIn(ExperimentalJsFileName::class)`,
|
||||
* or with the `-opt-in=kotlin.js.ExperimentalJsFileName` compiler option is given.
|
||||
*/
|
||||
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
|
||||
@MustBeDocumented
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
public annotation class ExperimentalJsFileName
|
||||
|
||||
/**
|
||||
* Specifies the name of the compiled file produced from the annotated source file instead of the default one.
|
||||
*
|
||||
* This annotation can be applied only to files and only when the compilation granularity is `PER_FILE`.
|
||||
*/
|
||||
@Target(FILE)
|
||||
@OptionalExpectation
|
||||
@ExperimentalJsFileName
|
||||
public expect annotation class JsFileName(val name: String)
|
||||
|
||||
/**
|
||||
* Marks experimental JS export annotations.
|
||||
*
|
||||
|
||||
@@ -78,7 +78,7 @@ val jsMainSources by task<Sync> {
|
||||
listOf(
|
||||
"libraries/stdlib/js/src/org.w3c/**",
|
||||
"libraries/stdlib/js/src/kotlin/char.kt",
|
||||
"libraries/stdlib/js/src/kotlin/collections.kt",
|
||||
"libraries/stdlib/js/src/kotlin/collectionJs.kt",
|
||||
"libraries/stdlib/js/src/kotlin/collections/**",
|
||||
"libraries/stdlib/js/src/kotlin/time/**",
|
||||
"libraries/stdlib/js/src/kotlin/console.kt",
|
||||
@@ -90,7 +90,7 @@ val jsMainSources by task<Sync> {
|
||||
"libraries/stdlib/js/src/kotlin/json.kt",
|
||||
"libraries/stdlib/js/src/kotlin/promise.kt",
|
||||
"libraries/stdlib/js/src/kotlin/regexp.kt",
|
||||
"libraries/stdlib/js/src/kotlin/sequence.kt",
|
||||
"libraries/stdlib/js/src/kotlin/sequenceJs.kt",
|
||||
"libraries/stdlib/js/src/kotlin/throwableExtensions.kt",
|
||||
"libraries/stdlib/js/src/kotlin/text/**",
|
||||
"libraries/stdlib/js/src/kotlin/reflect/KTypeHelpers.kt",
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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 kotlin.js
|
||||
|
||||
internal fun setMetadataFor(
|
||||
ctor: Ctor,
|
||||
name: String?,
|
||||
metadataConstructor: (name: String?, associatedObjectKey: Number?, associatedObjects: dynamic, suspendArity: Array<Int>?) -> Metadata,
|
||||
parent: Ctor?,
|
||||
interfaces: Array<dynamic>?,
|
||||
associatedObjectKey: Number?,
|
||||
associatedObjects: dynamic,
|
||||
suspendArity: Array<Int>?
|
||||
) {
|
||||
if (parent != null) {
|
||||
js("""
|
||||
ctor.prototype = Object.create(parent.prototype)
|
||||
ctor.prototype.constructor = ctor;
|
||||
""")
|
||||
}
|
||||
|
||||
val metadata = metadataConstructor(name, associatedObjectKey, associatedObjects, suspendArity ?: js("[]"))
|
||||
ctor.`$metadata$` = metadata
|
||||
|
||||
if (interfaces != null) {
|
||||
val receiver = if (metadata.iid != null) ctor else ctor.prototype
|
||||
receiver.`$imask$` = implement(interfaces)
|
||||
}
|
||||
}
|
||||
|
||||
// There was a problem with per-module compilation (KT-55758) when the top-level state (iid) was reinitialized during stdlib module initialization
|
||||
// As a result we miss already incremented iid and had the same iids in two different modules
|
||||
// So, to keep the state consistent it was moved into the variable without initializer and function
|
||||
@Suppress("MUST_BE_INITIALIZED")
|
||||
private var iid: dynamic
|
||||
|
||||
private fun generateInterfaceId(): Int {
|
||||
if (iid === VOID) {
|
||||
iid = 0
|
||||
}
|
||||
iid = iid.unsafeCast<Int>() + 1
|
||||
return iid.unsafeCast<Int>()
|
||||
}
|
||||
|
||||
|
||||
internal fun interfaceMeta(name: String?, associatedObjectKey: Number?, associatedObjects: dynamic, suspendArity: Array<Int>?): Metadata {
|
||||
return createMetadata("interface", name, associatedObjectKey, associatedObjects, suspendArity, generateInterfaceId())
|
||||
}
|
||||
|
||||
internal fun objectMeta(name: String?, associatedObjectKey: Number?, associatedObjects: dynamic, suspendArity: Array<Int>?): Metadata {
|
||||
return createMetadata("object", name, associatedObjectKey, associatedObjects, suspendArity, null)
|
||||
}
|
||||
|
||||
internal fun classMeta(name: String?, associatedObjectKey: Number?, associatedObjects: dynamic, suspendArity: Array<Int>?): Metadata {
|
||||
return createMetadata("class", name, associatedObjectKey, associatedObjects, suspendArity, null)
|
||||
}
|
||||
|
||||
// Seems like we need to disable this check if variables are used inside js annotation
|
||||
@Suppress("UNUSED_PARAMETER", "UNUSED_VARIABLE")
|
||||
private fun createMetadata(
|
||||
kind: String,
|
||||
name: String?,
|
||||
associatedObjectKey: Number?,
|
||||
associatedObjects: dynamic,
|
||||
suspendArity: Array<Int>?,
|
||||
iid: Int?
|
||||
): Metadata {
|
||||
val undef = VOID
|
||||
return js("""({
|
||||
kind: kind,
|
||||
simpleName: name,
|
||||
associatedObjectKey: associatedObjectKey,
|
||||
associatedObjects: associatedObjects,
|
||||
suspendArity: suspendArity,
|
||||
${'$'}kClass$: undef,
|
||||
iid: iid
|
||||
})""")
|
||||
}
|
||||
|
||||
internal external interface Metadata {
|
||||
val kind: String
|
||||
// This field gives fast access to the prototype of metadata owner (Object.getPrototypeOf())
|
||||
// Can be pre-initialized or lazy initialized and then should be immutable
|
||||
val simpleName: String?
|
||||
val associatedObjectKey: Number?
|
||||
val associatedObjects: dynamic
|
||||
val suspendArity: Array<Int>?
|
||||
val iid: Int?
|
||||
|
||||
var `$kClass$`: dynamic
|
||||
|
||||
var errorInfo: Int? // Bits set for overridden properties: "message" => 0x1, "cause" => 0x2
|
||||
}
|
||||
@@ -5,95 +5,6 @@
|
||||
|
||||
package kotlin.js
|
||||
|
||||
internal fun setMetadataFor(
|
||||
ctor: Ctor,
|
||||
name: String?,
|
||||
metadataConstructor: (name: String?, associatedObjectKey: Number?, associatedObjects: dynamic, suspendArity: Array<Int>?) -> Metadata,
|
||||
parent: Ctor?,
|
||||
interfaces: Array<dynamic>?,
|
||||
associatedObjectKey: Number?,
|
||||
associatedObjects: dynamic,
|
||||
suspendArity: Array<Int>?
|
||||
) {
|
||||
if (parent != null) {
|
||||
js("""
|
||||
ctor.prototype = Object.create(parent.prototype)
|
||||
ctor.prototype.constructor = ctor;
|
||||
""")
|
||||
}
|
||||
|
||||
val metadata = metadataConstructor(name, associatedObjectKey, associatedObjects, suspendArity ?: js("[]"))
|
||||
ctor.`$metadata$` = metadata
|
||||
|
||||
if (interfaces != null) {
|
||||
val receiver = if (metadata.iid != null) ctor else ctor.prototype
|
||||
receiver.`$imask$` = implement(interfaces)
|
||||
}
|
||||
}
|
||||
|
||||
// There was a problem with per-module compilation (KT-55758) when the top-level state (iid) was reinitialized during stdlib module initialization
|
||||
// As a result we miss already incremented iid and had the same iids in two different modules
|
||||
// So, to keep the state consistent it was moved into the next lateinit variable and function
|
||||
private lateinit var iid: Any
|
||||
|
||||
private fun generateInterfaceId(): Int {
|
||||
if (!::iid.isInitialized) {
|
||||
iid = 0
|
||||
}
|
||||
iid = iid.unsafeCast<Int>() + 1
|
||||
return iid.unsafeCast<Int>()
|
||||
}
|
||||
|
||||
|
||||
internal fun interfaceMeta(name: String?, associatedObjectKey: Number?, associatedObjects: dynamic, suspendArity: Array<Int>?): Metadata {
|
||||
return createMetadata("interface", name, associatedObjectKey, associatedObjects, suspendArity, generateInterfaceId())
|
||||
}
|
||||
|
||||
internal fun objectMeta(name: String?, associatedObjectKey: Number?, associatedObjects: dynamic, suspendArity: Array<Int>?): Metadata {
|
||||
return createMetadata("object", name, associatedObjectKey, associatedObjects, suspendArity, null)
|
||||
}
|
||||
|
||||
internal fun classMeta(name: String?, associatedObjectKey: Number?, associatedObjects: dynamic, suspendArity: Array<Int>?): Metadata {
|
||||
return createMetadata("class", name, associatedObjectKey, associatedObjects, suspendArity, null)
|
||||
}
|
||||
|
||||
// Seems like we need to disable this check if variables are used inside js annotation
|
||||
@Suppress("UNUSED_PARAMETER", "UNUSED_VARIABLE")
|
||||
private fun createMetadata(
|
||||
kind: String,
|
||||
name: String?,
|
||||
associatedObjectKey: Number?,
|
||||
associatedObjects: dynamic,
|
||||
suspendArity: Array<Int>?,
|
||||
iid: Int?
|
||||
): Metadata {
|
||||
val undef = VOID
|
||||
return js("""({
|
||||
kind: kind,
|
||||
simpleName: name,
|
||||
associatedObjectKey: associatedObjectKey,
|
||||
associatedObjects: associatedObjects,
|
||||
suspendArity: suspendArity,
|
||||
${'$'}kClass$: undef,
|
||||
iid: iid
|
||||
})""")
|
||||
}
|
||||
|
||||
internal external interface Metadata {
|
||||
val kind: String
|
||||
// This field gives fast access to the prototype of metadata owner (Object.getPrototypeOf())
|
||||
// Can be pre-initialized or lazy initialized and then should be immutable
|
||||
val simpleName: String?
|
||||
val associatedObjectKey: Number?
|
||||
val associatedObjects: dynamic
|
||||
val suspendArity: Array<Int>?
|
||||
val iid: Int?
|
||||
|
||||
var `$kClass$`: dynamic
|
||||
|
||||
var errorInfo: Int? // Bits set for overridden properties: "message" => 0x1, "cause" => 0x2
|
||||
}
|
||||
|
||||
internal external interface Ctor {
|
||||
var `$imask$`: BitMask?
|
||||
var `$metadata$`: Metadata
|
||||
@@ -128,22 +39,6 @@ internal fun calculateErrorInfo(proto: dynamic): Int {
|
||||
|
||||
private fun getPrototypeOf(obj: dynamic) = JsObject.getPrototypeOf(obj)
|
||||
|
||||
private fun searchForMetadata(obj: dynamic): Metadata? {
|
||||
if (obj == null) {
|
||||
return null
|
||||
}
|
||||
var metadata: Metadata? = obj.`$metadata$`
|
||||
var currentObject = getPrototypeOf(obj)
|
||||
|
||||
while (metadata == null && currentObject != null) {
|
||||
val currentConstructor = currentObject.constructor
|
||||
metadata = currentConstructor.`$metadata$`
|
||||
currentObject = getPrototypeOf(currentObject)
|
||||
}
|
||||
|
||||
return metadata
|
||||
}
|
||||
|
||||
private fun isInterfaceImpl(obj: dynamic, iface: Int): Boolean {
|
||||
val mask: BitMask = obj.`$imask$`.unsafeCast<BitMask?>() ?: return false
|
||||
return mask.isBitSet(iface)
|
||||
|
||||
@@ -8,7 +8,7 @@ package kotlin.js
|
||||
import kotlin.annotation.AnnotationTarget.*
|
||||
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
@Target(CLASS, FUNCTION, PROPERTY, CONSTRUCTOR, PROPERTY_GETTER, PROPERTY_SETTER)
|
||||
@Target(FILE, CLASS, FUNCTION, PROPERTY, CONSTRUCTOR, PROPERTY_GETTER, PROPERTY_SETTER)
|
||||
internal external annotation class JsName(val name: String)
|
||||
|
||||
internal external annotation class native
|
||||
|
||||
@@ -58,9 +58,18 @@ internal annotation class marker
|
||||
*
|
||||
*/
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
@Target(CLASS, FUNCTION, PROPERTY, CONSTRUCTOR, PROPERTY_GETTER, PROPERTY_SETTER)
|
||||
@Target(FILE, CLASS, FUNCTION, PROPERTY, CONSTRUCTOR, PROPERTY_GETTER, PROPERTY_SETTER)
|
||||
public actual annotation class JsName(actual val name: String)
|
||||
|
||||
/**
|
||||
* Specifies the name of the compiled file produced from the annotated source file instead of the default one.
|
||||
*
|
||||
* This annotation can be applied only to files and only when the compilation granularity is `PER_FILE`.
|
||||
*/
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
@Target(FILE)
|
||||
public actual annotation class JsFileName(actual val name: String)
|
||||
|
||||
/**
|
||||
* Denotes an `external` declaration that must be imported from native JavaScript library.
|
||||
*
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
// TODO: Suppress will be until the next bootstrapping, after the bootstrapping the annotation should be replaced with [kotlin.js.JsFileName]
|
||||
@file:Suppress("ANNOTATION_IS_NOT_APPLICABLE_TO_MULTIFILE_CLASSES")
|
||||
@file:kotlin.js.JsName("CollectionsKt")
|
||||
@file:kotlin.jvm.JvmMultifileClass
|
||||
@file:kotlin.jvm.JvmName("CollectionsKt")
|
||||
@file:OptIn(kotlin.experimental.ExperimentalTypeInference::class)
|
||||
|
||||
@@ -30,6 +30,7 @@ public actual annotation class JsExport {
|
||||
*/
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
@Target(
|
||||
AnnotationTarget.FILE,
|
||||
AnnotationTarget.CLASS,
|
||||
AnnotationTarget.FUNCTION,
|
||||
AnnotationTarget.PROPERTY,
|
||||
|
||||
Reference in New Issue
Block a user