[K/JS] chore: stop unnecessary defineProperties generating.
This commit is contained in:
+1
-1
@@ -115,7 +115,7 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
|
||||
return expression.receiver!!.accept(this, context).withSource(expression, context)
|
||||
}
|
||||
val fieldName = context.getNameForField(field)
|
||||
return JsNameRef(fieldName, expression.receiver?.accept(this, context)).withSource(expression, context)
|
||||
return jsElementAccess(fieldName, expression.receiver?.accept(this, context)).withSource(expression, context)
|
||||
}
|
||||
|
||||
override fun visitGetValue(expression: IrGetValue, context: JsGenerationContext): JsExpression {
|
||||
|
||||
+1
-1
@@ -101,7 +101,7 @@ class IrElementToJsStatementTransformer : BaseIrElementToJsNodeTransformer<JsSta
|
||||
override fun visitSetField(expression: IrSetField, context: JsGenerationContext): JsStatement {
|
||||
val fieldName = context.getNameForField(expression.symbol.owner)
|
||||
val expressionTransformer = IrElementToJsExpressionTransformer()
|
||||
val dest = JsNameRef(fieldName, expression.receiver?.accept(expressionTransformer, context))
|
||||
val dest = jsElementAccess(fieldName, expression.receiver?.accept(expressionTransformer, context))
|
||||
return expression.value.maybeOptimizeIntoSwitch(context) { jsAssignment(dest, it).withSource(expression, context).makeStmt() }
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -111,7 +111,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
|
||||
if (property.getter?.extensionReceiverParameter != null || property.setter?.extensionReceiverParameter != null)
|
||||
continue
|
||||
|
||||
if (!property.visibility.isPublicAPI)
|
||||
if (!property.visibility.isPublicAPI || property.isSimpleProperty)
|
||||
continue
|
||||
|
||||
if (
|
||||
|
||||
+19
-8
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
||||
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
|
||||
import org.jetbrains.kotlin.ir.util.isSimpleProperty
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.js.backend.ast.*
|
||||
import org.jetbrains.kotlin.utils.DFS
|
||||
@@ -117,7 +118,7 @@ class JsNameLinkingNamer(private val context: JsIrBackendContext, private val mi
|
||||
declaration is IrFunction && declaration.dispatchReceiverParameter != null -> {
|
||||
val property = (declaration as? IrSimpleFunction)?.correspondingPropertySymbol?.owner
|
||||
if (property?.isExported(context) == true || property?.isEffectivelyExternal() == true) {
|
||||
context.minimizedNameGenerator.reserveName(property.name.asString())
|
||||
context.minimizedNameGenerator.reserveName(property.getJsNameOrKotlinName().identifier)
|
||||
}
|
||||
if (declaration.hasStableJsName(context)) {
|
||||
val signature = jsFunctionSignature(declaration, context)
|
||||
@@ -126,7 +127,7 @@ class JsNameLinkingNamer(private val context: JsIrBackendContext, private val mi
|
||||
}
|
||||
declaration is IrProperty -> {
|
||||
if (declaration.isExported(context)) {
|
||||
context.minimizedNameGenerator.reserveName(declaration.name.asString())
|
||||
context.minimizedNameGenerator.reserveName(declaration.getJsNameOrKotlinName().identifier)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -138,12 +139,22 @@ class JsNameLinkingNamer(private val context: JsIrBackendContext, private val mi
|
||||
it.declarations.forEach {
|
||||
when {
|
||||
it is IrField -> {
|
||||
val safeName = if (minimizedMemberNames) {
|
||||
context.minimizedNameGenerator.generateNextName()
|
||||
} else it.safeName()
|
||||
val suffix = nameCnt.getOrDefault(safeName, 0) + 1
|
||||
nameCnt[safeName] = suffix
|
||||
result[it] = safeName + "_$suffix"
|
||||
val correspondingProperty = it.correspondingPropertySymbol?.owner
|
||||
val hasStableName = correspondingProperty != null &&
|
||||
correspondingProperty.visibility.isPublicAPI &&
|
||||
(correspondingProperty.isExported(context) || correspondingProperty.getJsName() != null) &&
|
||||
correspondingProperty.isSimpleProperty
|
||||
val safeName = when {
|
||||
hasStableName -> (correspondingProperty ?: it).getJsNameOrKotlinName().identifier
|
||||
minimizedMemberNames -> context.minimizedNameGenerator.generateNextName()
|
||||
else -> it.safeName()
|
||||
}
|
||||
val resultName = if (!hasStableName) {
|
||||
val suffix = nameCnt.getOrDefault(safeName, 0) + 1
|
||||
nameCnt[safeName] = suffix
|
||||
safeName + "_$suffix"
|
||||
} else safeName
|
||||
result[it] = resultName
|
||||
}
|
||||
it is IrFunction && it.dispatchReceiverParameter != null -> {
|
||||
nameCnt[jsFunctionSignature(it, context)] = 1 // avoid clashes with member functions
|
||||
|
||||
+6
-3
@@ -52,10 +52,13 @@ fun <T : JsNode> IrWhen.toJsNode(
|
||||
}
|
||||
|
||||
fun jsElementAccess(name: String, receiver: JsExpression?): JsExpression =
|
||||
if (receiver == null || name.isValidES5Identifier()) {
|
||||
JsNameRef(JsName(name, false), receiver)
|
||||
jsElementAccess(JsName(name, false), receiver)
|
||||
|
||||
fun jsElementAccess(name: JsName, receiver: JsExpression?): JsExpression =
|
||||
if (receiver == null || name.ident.isValidES5Identifier()) {
|
||||
JsNameRef(name, receiver)
|
||||
} else {
|
||||
JsArrayAccess(receiver, JsStringLiteral(name))
|
||||
JsArrayAccess(receiver, JsStringLiteral(name.ident))
|
||||
}
|
||||
|
||||
fun jsAssignment(left: JsExpression, right: JsExpression) = JsBinaryOperation(JsBinaryOperator.ASG, left, right)
|
||||
|
||||
@@ -192,6 +192,16 @@ fun IrValueParameter.createStubDefaultValue(): IrExpressionBody =
|
||||
IrErrorExpressionImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, "Stub expression for default value of $name")
|
||||
)
|
||||
|
||||
val IrProperty.isSimpleProperty: Boolean
|
||||
get() {
|
||||
val getterFun = getter
|
||||
val setterFun = setter
|
||||
return !isFakeOverride &&
|
||||
modality === Modality.FINAL &&
|
||||
(getterFun == null || getterFun.origin == IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR) &&
|
||||
(setterFun == null || setterFun.origin == IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR)
|
||||
}
|
||||
|
||||
val IrClass.functions: Sequence<IrSimpleFunction>
|
||||
get() = declarations.asSequence().filterIsInstance<IrSimpleFunction>()
|
||||
|
||||
|
||||
@@ -2112,6 +2112,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
||||
runTest("js/js.translator/testData/box/export/exportAllFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportClassPropertiesInDifferentCombinations.kt")
|
||||
public void testExportClassPropertiesInDifferentCombinations() throws Exception {
|
||||
runTest("js/js.translator/testData/box/export/exportClassPropertiesInDifferentCombinations.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportClassWithInternal.kt")
|
||||
public void testExportClassWithInternal() throws Exception {
|
||||
|
||||
+6
@@ -2584,6 +2584,12 @@ public class FirJsTestGenerated extends AbstractFirJsTest {
|
||||
runTest("js/js.translator/testData/box/export/exportAllFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportClassPropertiesInDifferentCombinations.kt")
|
||||
public void testExportClassPropertiesInDifferentCombinations() throws Exception {
|
||||
runTest("js/js.translator/testData/box/export/exportClassPropertiesInDifferentCombinations.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportClassWithInternal.kt")
|
||||
public void testExportClassWithInternal() throws Exception {
|
||||
|
||||
+6
@@ -2584,6 +2584,12 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
||||
runTest("js/js.translator/testData/box/export/exportAllFile.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportClassPropertiesInDifferentCombinations.kt")
|
||||
public void testExportClassPropertiesInDifferentCombinations() throws Exception {
|
||||
runTest("js/js.translator/testData/box/export/exportClassPropertiesInDifferentCombinations.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("exportClassWithInternal.kt")
|
||||
public void testExportClassWithInternal() throws Exception {
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
// FILE: lib.kt
|
||||
|
||||
@JsExport
|
||||
fun `@do something like-this`(): Int = 42
|
||||
fun `@do something like-this`(`test value`: Int = 42): Int = `test value`
|
||||
|
||||
// FILE: test.js
|
||||
function box() {
|
||||
|
||||
+227
@@ -0,0 +1,227 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1252
|
||||
// IGNORE_BACKEND: JS
|
||||
// RUN_PLAIN_BOX_FUNCTION
|
||||
// INFER_MAIN_MODULE
|
||||
|
||||
// MODULE: export_class_properties
|
||||
// FILE: lib.kt
|
||||
|
||||
@JsExport
|
||||
interface IOwner {
|
||||
val interfaceValOpen: String
|
||||
|
||||
val interfaceGetterOnly: String
|
||||
get() = "Interface with Getter"
|
||||
|
||||
var interfaceVarOpen: String
|
||||
}
|
||||
|
||||
@JsExport
|
||||
open class Owner {
|
||||
open val classOpenReadonly: String = "Class Readonly Open"
|
||||
open var classOpenVar: String = "Class Var Open"
|
||||
|
||||
val classFinalReadonly: String = "Class Readonly Final"
|
||||
var classFinalVar: String = "Class Default"
|
||||
|
||||
val classGetterOnly: String
|
||||
get() = "Class with Final Getter"
|
||||
|
||||
open val classOpenGetterOnly: String
|
||||
get() = "Class with Open Getter"
|
||||
|
||||
var classSetterOnly: String = "Class setter only"
|
||||
set(value) { classOpenVar = "Class Changed by class setter only $value" }
|
||||
|
||||
open var classOpenSetterOnly: String = "Class open setter only"
|
||||
set(value) { classOpenVar = "Class Changed by class open setter only $value" }
|
||||
|
||||
var classGetterAndSetter: String = "Class Getter and Setter"
|
||||
get() = field + " by class getter"
|
||||
set(value) { field = value }
|
||||
|
||||
open var classOpenGetterAndSetter: String = "Class Open Getter and Setter"
|
||||
get() = field + " by class open getter"
|
||||
set(value) { field = value }
|
||||
}
|
||||
|
||||
open class HiddenChild : Owner(), IOwner {
|
||||
override val interfaceValOpen: String = "Hidden Child Open Val"
|
||||
override var interfaceVarOpen: String = "Hidden Child Open Var"
|
||||
|
||||
val hiddenDefaultVal: String = "Hidden Default Val"
|
||||
val hiddenDefaultGetter: String get() = "Hidden Default Getter"
|
||||
var hiddenDefaultVar: String = "Hidden Default Var"
|
||||
}
|
||||
|
||||
open class AnotherOneHiddenChild: HiddenChild() {
|
||||
override val interfaceGetterOnly: String
|
||||
get() = "Another One Hidden Child with Getter"
|
||||
}
|
||||
|
||||
@JsExport
|
||||
class ExportedChild: AnotherOneHiddenChild() {
|
||||
override val classOpenReadonly: String = "Exported Child Readonly Open"
|
||||
override var classOpenVar: String = "Exported Child Var Open"
|
||||
|
||||
override val classOpenGetterOnly: String
|
||||
get() = "Exported Child with Open Getter"
|
||||
|
||||
override var classOpenSetterOnly: String = super.classOpenSetterOnly
|
||||
set(value) { classOpenVar = "Exported Child Changed by class open setter only $value" }
|
||||
|
||||
override var classOpenGetterAndSetter: String = super.classOpenGetterAndSetter
|
||||
get() = field + " by exported child open getter"
|
||||
set(value) { field = value }
|
||||
}
|
||||
|
||||
@JsExport
|
||||
fun generateHiddenChild() = HiddenChild()
|
||||
|
||||
@JsExport
|
||||
fun generateAnotherHiddenChild() = AnotherOneHiddenChild()
|
||||
|
||||
// FILE: test.js
|
||||
|
||||
function assertEquals(actualValue, expectedValue) {
|
||||
if (actualValue !== expectedValue) {
|
||||
throw new Error("Expected value is '" + expectedValue + "', but got '" + actualValue + "'")
|
||||
}
|
||||
}
|
||||
|
||||
function testOwner(pkg) {
|
||||
var owner = new pkg.Owner();
|
||||
|
||||
assertEquals(owner.classOpenReadonly, "Class Readonly Open")
|
||||
assertEquals(owner.classOpenVar, "Class Var Open")
|
||||
|
||||
assertEquals(owner.classFinalReadonly, "Class Readonly Final")
|
||||
assertEquals(owner.classFinalVar, "Class Default")
|
||||
|
||||
assertEquals(owner.classGetterOnly, "Class with Final Getter")
|
||||
assertEquals(owner.classOpenGetterOnly, "Class with Open Getter")
|
||||
|
||||
assertEquals(owner.classGetterAndSetter, "Class Getter and Setter by class getter")
|
||||
assertEquals(owner.classOpenGetterAndSetter, "Class Open Getter and Setter by class open getter")
|
||||
|
||||
assertEquals(owner.classSetterOnly, "Class setter only")
|
||||
|
||||
owner.classSetterOnly = "test1"
|
||||
assertEquals(owner.classOpenVar, "Class Changed by class setter only test1")
|
||||
|
||||
assertEquals(owner.classOpenSetterOnly, "Class open setter only")
|
||||
|
||||
owner.classOpenSetterOnly = "test2"
|
||||
assertEquals(owner.classOpenVar, "Class Changed by class open setter only test2")
|
||||
}
|
||||
|
||||
function testHiddenChild(pkg) {
|
||||
var owner = pkg.generateHiddenChild()
|
||||
|
||||
assertEquals(owner.hiddenDefaultVal, undefined)
|
||||
assertEquals(owner.hiddenDefaultGetter, undefined)
|
||||
assertEquals(owner.hiddenDefaultVar, undefined)
|
||||
|
||||
assertEquals(owner.interfaceValOpen, "Hidden Child Open Val")
|
||||
assertEquals(owner.interfaceVarOpen, "Hidden Child Open Var")
|
||||
|
||||
assertEquals(owner.interfaceGetterOnly, "Interface with Getter")
|
||||
|
||||
assertEquals(owner.classOpenReadonly, "Class Readonly Open")
|
||||
assertEquals(owner.classOpenVar, "Class Var Open")
|
||||
|
||||
assertEquals(owner.classFinalReadonly, "Class Readonly Final")
|
||||
assertEquals(owner.classFinalVar, "Class Default")
|
||||
|
||||
assertEquals(owner.classGetterOnly, "Class with Final Getter")
|
||||
assertEquals(owner.classOpenGetterOnly, "Class with Open Getter")
|
||||
|
||||
assertEquals(owner.classGetterAndSetter, "Class Getter and Setter by class getter")
|
||||
assertEquals(owner.classOpenGetterAndSetter, "Class Open Getter and Setter by class open getter")
|
||||
|
||||
assertEquals(owner.classSetterOnly, "Class setter only")
|
||||
|
||||
owner.classSetterOnly = "test1"
|
||||
assertEquals(owner.classOpenVar, "Class Changed by class setter only test1")
|
||||
|
||||
assertEquals(owner.classOpenSetterOnly, "Class open setter only")
|
||||
|
||||
owner.classOpenSetterOnly = "test2"
|
||||
assertEquals(owner.classOpenVar, "Class Changed by class open setter only test2")
|
||||
}
|
||||
|
||||
function testAnotherHiddenChild(pkg) {
|
||||
var owner = pkg.generateAnotherHiddenChild()
|
||||
|
||||
assertEquals(owner.hiddenDefaultVal, undefined)
|
||||
assertEquals(owner.hiddenDefaultGetter, undefined)
|
||||
assertEquals(owner.hiddenDefaultVar, undefined)
|
||||
|
||||
assertEquals(owner.interfaceValOpen, "Hidden Child Open Val")
|
||||
assertEquals(owner.interfaceVarOpen, "Hidden Child Open Var")
|
||||
|
||||
assertEquals(owner.interfaceGetterOnly, "Another One Hidden Child with Getter")
|
||||
|
||||
assertEquals(owner.classOpenReadonly, "Class Readonly Open")
|
||||
assertEquals(owner.classOpenVar, "Class Var Open")
|
||||
|
||||
assertEquals(owner.classFinalReadonly, "Class Readonly Final")
|
||||
assertEquals(owner.classFinalVar, "Class Default")
|
||||
|
||||
assertEquals(owner.classGetterOnly, "Class with Final Getter")
|
||||
assertEquals(owner.classOpenGetterOnly, "Class with Open Getter")
|
||||
|
||||
assertEquals(owner.classGetterAndSetter, "Class Getter and Setter by class getter")
|
||||
assertEquals(owner.classOpenGetterAndSetter, "Class Open Getter and Setter by class open getter")
|
||||
|
||||
owner.classSetterOnly = "test1"
|
||||
assertEquals(owner.classOpenVar, "Class Changed by class setter only test1")
|
||||
|
||||
owner.classOpenSetterOnly = "test2"
|
||||
assertEquals(owner.classOpenVar, "Class Changed by class open setter only test2")
|
||||
}
|
||||
|
||||
function testExportedChild(pkg) {
|
||||
var owner = pkg.generateAnotherHiddenChild()
|
||||
|
||||
assertEquals(owner.hiddenDefaultVal, undefined)
|
||||
assertEquals(owner.hiddenDefaultGetter, undefined)
|
||||
assertEquals(owner.hiddenDefaultVar, undefined)
|
||||
|
||||
assertEquals(owner.interfaceValOpen, "Hidden Child Open Val")
|
||||
assertEquals(owner.interfaceVarOpen, "Hidden Child Open Var")
|
||||
|
||||
assertEquals(owner.interfaceGetterOnly, "Another One Hidden Child with Getter")
|
||||
|
||||
assertEquals(owner.classOpenReadonly, "Exported Child Readonly Open")
|
||||
assertEquals(owner.classOpenVar, "Exported Child Var Open")
|
||||
|
||||
assertEquals(owner.classFinalReadonly, "Class Readonly Final")
|
||||
assertEquals(owner.classFinalVar, "Class Default")
|
||||
|
||||
assertEquals(owner.classGetterOnly, "Class with Final Getter")
|
||||
assertEquals(owner.classOpenGetterOnly, "Exported Child with Open Getter")
|
||||
|
||||
assertEquals(owner.classGetterAndSetter, "Class Getter and Setter by class getter")
|
||||
assertEquals(owner.classOpenGetterAndSetter, "Class Open Getter and Setter by exported child open getter")
|
||||
|
||||
assertEquals(owner.classSetterOnly, "Class setter only")
|
||||
|
||||
owner.classSetterOnly = "test1"
|
||||
assertEquals(owner.classOpenVar, "Class Changed by class setter only test1")
|
||||
|
||||
assertEquals(owner.classOpenSetterOnly, "Class open setter only")
|
||||
|
||||
owner.classOpenSetterOnly = "test2"
|
||||
assertEquals(owner.classOpenVar, "Exported Child Changed by class open setter only test2")
|
||||
}
|
||||
|
||||
function box() {
|
||||
var pkg = this["export_class_properties"]
|
||||
|
||||
testOwner(pkg)
|
||||
testHiddenChild(pkg)
|
||||
testAnotherHiddenChild(pkg)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Reference in New Issue
Block a user