[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) {
ClassKind.OBJECT -> {
val obj = expression.symbol.owner
val className = context.getNameForSymbol(expression.symbol)
val getInstanceName = className.ident + "_getInstance"
JsInvocation(JsNameRef(getInstanceName))
if (obj.isEffectivelyExternal()) {
className.makeRef()
} else {
val getInstanceName = className.ident + "_getInstance"
JsInvocation(JsNameRef(getInstanceName))
}
}
else -> TODO()
}
@@ -131,6 +136,19 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
val jsExtensionReceiver = expression.extensionReceiver?.accept(this, 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)) {
return JsInvocation(jsDispatchReceiver!!, arguments)
}
@@ -403,9 +403,17 @@ fun IrFunction.isFakeOverriddenFromAny(): Boolean {
fun IrCall.isSuperToAny() = superQualifier?.let { this.symbol.owner.isFakeOverriddenFromAny() } ?: false
fun IrDeclaration.isEffectivelyExternal(): Boolean {
fun IrFunction.effectiveParentDeclaration(): IrDeclaration? =
when (this) {
is IrSimpleFunction -> correspondingProperty ?: parent as? IrDeclaration
else -> parent as? IrDeclaration
}
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 IrProperty -> isExternal || parent is IrDeclaration && parent.isEffectivelyExternal()
is IrClass -> isExternal || parent is IrDeclaration && parent.isEffectivelyExternal()
else -> false
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// EXPECTED_REACHABLE_NODES: 1287
// MODULE: lib
// FILE: lib.kt
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// EXPECTED_REACHABLE_NODES: 1203
external interface Foo {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// EXPECTED_REACHABLE_NODES: 1285
// MODULE_KIND: AMD
package foo