Skip to content

Commit

Permalink
rrr/1.6.20/ilgonmic/kt-51973
Browse files Browse the repository at this point in the history
[JS IR] Add non overridden property and method insode exported class

[JS IR] Add method into exported interface in test

[JS IR] Add interface properties cases to all file export test

[JS IR] Fix usage of isExported inside IrJsUtils


Co-authored-by: Anton Bannykh <[email protected]>

Merge-request: KT-MR-6090
Merged-by: Ilya Goncharov <[email protected]>

^KT-51973 fixed
  • Loading branch information
anton-bannykh authored and Space committed Apr 15, 2022
1 parent 368465e commit a3ed332
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -634,7 +634,7 @@ private fun shouldDeclarationBeExported(declaration: IrDeclarationWithName, cont
}

fun IrOverridableDeclaration<*>.isAllowedFakeOverriddenDeclaration(context: JsIrBackendContext): Boolean {
if (this.resolveFakeOverride(allowAbstract = true)?.parentClassOrNull.isExportedInterface()) {
if (this.resolveFakeOverride(allowAbstract = true)?.parentClassOrNull.isExportedInterface(context)) {
return true
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo

val overriddenSymbols = property.getter?.overriddenSymbols.orEmpty()

val backendContext = context.staticContext.backendContext

// Don't generate `defineProperty` if the property overrides a property from an exported class,
// because we've already generated `defineProperty` for the base class property.
// In other words, we only want to generate `defineProperty` once for each property.
Expand All @@ -142,7 +144,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
// P.S. If the overridden property is owned by an interface - we should generate defineProperty
// for overridden property in the first class which override those properties
val hasOverriddenExportedInterfaceProperties = overriddenSymbols.any { it.owner.isDefinedInsideExportedInterface() }
&& !overriddenSymbols.any { it.owner.parentClassOrNull.isExportedClass() }
&& !overriddenSymbols.any { it.owner.parentClassOrNull.isExportedClass(backendContext) }

val getterOverridesExternal = property.getter?.overridesExternal() == true
val overriddenExportedGetter = !property.getter?.overriddenSymbols.isNullOrEmpty() &&
Expand Down Expand Up @@ -213,7 +215,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
}

private fun IrSimpleFunction.isDefinedInsideExportedInterface(): Boolean {
return (!isFakeOverride && parentClassOrNull.isExportedInterface()) ||
return (!isFakeOverride && parentClassOrNull.isExportedInterface(context.staticContext.backendContext)) ||
overriddenSymbols.any { it.owner.isDefinedInsideExportedInterface() }
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ fun translateCall(
val property = function.correspondingPropertySymbol?.owner
if (
property != null &&
(property.isEffectivelyExternal() || property.isExportedMember())
(property.isEffectivelyExternal() || property.isExportedMember(context.staticContext.backendContext))
) {
val propertyName = context.getNameForProperty(property)
val nameRef = when (jsDispatchReceiver) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,19 @@ package org.jetbrains.kotlin.ir.backend.js.utils

import org.jetbrains.kotlin.descriptors.isClass
import org.jetbrains.kotlin.descriptors.isInterface
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.export.isExported
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithVisibility
import org.jetbrains.kotlin.ir.util.parentClassOrNull

fun IrDeclaration.isExportedMember() =
fun IrDeclaration.isExportedMember(context: JsIrBackendContext) =
(this is IrDeclarationWithVisibility && visibility.isPublicAPI) &&
parentClassOrNull.let { it is IrClass && it.isJsExport() }
parentClassOrNull?.isExported(context) == true

fun IrDeclaration?.isExportedClass() =
this is IrClass && kind.isClass && isJsExport()
fun IrDeclaration?.isExportedClass(context: JsIrBackendContext) =
this is IrClass && kind.isClass && isExported(context)

fun IrDeclaration?.isExportedInterface() =
this is IrClass && kind.isInterface && isJsExport()

fun IrDeclaration.isExportedInterfaceMember() =
parentClassOrNull.isExportedInterface()
fun IrDeclaration?.isExportedInterface(context: JsIrBackendContext) =
this is IrClass && kind.isInterface && isExported(context)
140 changes: 138 additions & 2 deletions js/js.translator/testData/box/export/exportAllFile.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,151 @@

abstract class A {
abstract fun foo(k: String): String

abstract val bar: String

abstract val baz: String

abstract var bay: String

abstract var bat: String
}

class B : A() {
open class B : A() {
override fun foo(k: String): String {
return "O" + k
}

override val bar: String = "bar"

override val baz: String
get() = "baz"

override var bay: String = "bay"

private var _bat: String = "bat"

override var bat: String
get() = _bat
set(value) {
_bat = value
}
}

interface I {
val gap: String

val hap: String

var baz: String

var bay: String

fun foo(): String
}

open class C : I {
override val gap: String = "gap"

override val hap: String
get() = "hap"

override var bay: String = "bay"

private var _baz = "baz"

override var baz: String
get() = _baz
set(value) {
_baz = value
}

val koo: String = "koo"

override fun foo(): String {
return "foo"
}

fun foi() = "foi"
}

fun topFoo(a: A): String {
if (a.bar != "bar3") return "fail"
if (a.baz != "baz3") return "fail"
return "OK"
}

fun topBar(c: C): String {
if (c.bay != "bay3") return "fail"
if (c.baz != "baz3") return "fail"
return "OK"
}

// FILE: test.js

function box() {
return new this["export_all_file"].B().foo("K");
var exportObject = this["export_all_file"]

function H() {
}

H.prototype = Object.create(exportObject.B.prototype);
H.prototype.constructor = H;
Object.defineProperty(H.prototype, "bar", {
get: function() {
return "bar3"
}
})

Object.defineProperty(H.prototype, "baz", {
get: function() {
return "baz3"
}
})

function J() {
}

J.prototype = Object.create(exportObject.C.prototype);
J.prototype.constructor = J;
Object.defineProperty(J.prototype, "bay", {
get: function() {
return "bay3"
}
})

Object.defineProperty(J.prototype, "baz", {
get: function() {
return "baz3"
}
})

var b = new exportObject.B()
if (b.foo("K") != "OK") return "fail 1";
if (b.bar != "bar") return "fail 2"
if (b.baz != "baz") return "fail 3"
if (b.bay != "bay") return "fail 4"
b.bay = "bay2"
if (b.bay != "bay2") return "fail 5"
if (b.bat != "bat") return "fail6"
b.bat = "bat2"
if (b.bat != "bat2") return "fail7"

var c = new exportObject.C()
if (c.gap != "gap") return "fail 8"
if (c.hap != "hap") return "fail 9"
if (c.bay != "bay") return "fail 10"
c.bay = c.bay + "2"
if (c.bay != "bay2") return "fail 11"
if (c.baz != "baz") return "fail 12"
c.baz = c.baz + "2"
if (c.baz != "baz2") return "fail 13"
if (c.foo() != "foo") return "fail 14"
if (c.koo != "koo") return "fail 15"
if (c.foi() != "foi") return "fail 16"

if (exportObject.topFoo(new H()) != "OK") return "fail 17"
if (exportObject.topBar(new J()) != "OK") return "fail 18"

return "OK"
}

0 comments on commit a3ed332

Please sign in to comment.