[JS IR BE] Support codegen for external objects and properties

This commit is contained in:
Svyatoslav Kuzmich
2019-02-06 14:27:43 +03:00
parent 53d15ea27c
commit d8b1d09566
5 changed files with 29 additions and 6 deletions
@@ -79,9 +79,14 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
override fun visitGetObjectValue(expression: IrGetObjectValue, context: JsGenerationContext) = when (expression.symbol.owner.kind) { override fun visitGetObjectValue(expression: IrGetObjectValue, context: JsGenerationContext) = when (expression.symbol.owner.kind) {
ClassKind.OBJECT -> { ClassKind.OBJECT -> {
val obj = expression.symbol.owner
val className = context.getNameForSymbol(expression.symbol) val className = context.getNameForSymbol(expression.symbol)
val getInstanceName = className.ident + "_getInstance" if (obj.isEffectivelyExternal()) {
JsInvocation(JsNameRef(getInstanceName)) className.makeRef()
} else {
val getInstanceName = className.ident + "_getInstance"
JsInvocation(JsNameRef(getInstanceName))
}
} }
else -> TODO() else -> TODO()
} }
@@ -131,6 +136,19 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
val jsExtensionReceiver = expression.extensionReceiver?.accept(this, context) val jsExtensionReceiver = expression.extensionReceiver?.accept(this, context)
val arguments = translateCallArguments(expression, context) val arguments = translateCallArguments(expression, context)
// Transform external property accessor call
if (function is IrSimpleFunction) {
val property = function.correspondingProperty
if (property != null && property.isEffectivelyExternal()) {
val nameRef = JsNameRef(property.name.identifier, jsDispatchReceiver)
return when (function) {
property.getter -> nameRef
property.setter -> jsAssignment(nameRef, arguments.single())
else -> error("Function must be an accessor of corresponding property")
}
}
}
if (isNativeInvoke(expression)) { if (isNativeInvoke(expression)) {
return JsInvocation(jsDispatchReceiver!!, arguments) return JsInvocation(jsDispatchReceiver!!, arguments)
} }
@@ -403,9 +403,17 @@ fun IrFunction.isFakeOverriddenFromAny(): Boolean {
fun IrCall.isSuperToAny() = superQualifier?.let { this.symbol.owner.isFakeOverriddenFromAny() } ?: false fun IrCall.isSuperToAny() = superQualifier?.let { this.symbol.owner.isFakeOverriddenFromAny() } ?: false
fun IrDeclaration.isEffectivelyExternal(): Boolean { fun IrDeclaration.isEffectivelyExternal(): Boolean {
fun IrFunction.effectiveParentDeclaration(): IrDeclaration? =
when (this) {
is IrSimpleFunction -> correspondingProperty ?: parent as? IrDeclaration
else -> parent as? IrDeclaration
}
return when (this) { return when (this) {
is IrFunction -> isExternal || parent is IrDeclaration && parent.isEffectivelyExternal() is IrFunction -> isExternal || (effectiveParentDeclaration()?.isEffectivelyExternal() ?: false)
is IrField -> isExternal || parent is IrDeclaration && parent.isEffectivelyExternal() is IrField -> isExternal || parent is IrDeclaration && parent.isEffectivelyExternal()
is IrProperty -> isExternal || parent is IrDeclaration && parent.isEffectivelyExternal()
is IrClass -> isExternal || parent is IrDeclaration && parent.isEffectivelyExternal() is IrClass -> isExternal || parent is IrDeclaration && parent.isEffectivelyExternal()
else -> false else -> false
} }
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// EXPECTED_REACHABLE_NODES: 1287 // EXPECTED_REACHABLE_NODES: 1287
// MODULE: lib // MODULE: lib
// FILE: lib.kt // FILE: lib.kt
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// EXPECTED_REACHABLE_NODES: 1203 // EXPECTED_REACHABLE_NODES: 1203
external interface Foo { external interface Foo {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// EXPECTED_REACHABLE_NODES: 1285 // EXPECTED_REACHABLE_NODES: 1285
// MODULE_KIND: AMD // MODULE_KIND: AMD
package foo package foo