diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsExpressionTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsExpressionTransformer.kt index 8dfbe988647..44cee71f3cf 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsExpressionTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsExpressionTransformer.kt @@ -113,7 +113,7 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer nameRef - property.setter -> jsAssignment(nameRef, arguments.single()) - else -> error("Function must be an accessor of corresponding property") - } - } - } - - if (isNativeInvoke(expression)) { - return JsInvocation(jsDispatchReceiver!!, arguments) - } - - expression.superQualifierSymbol?.let { superQualifier -> - require(function is IrSimpleFunction) - - val (target, klass) = if (superQualifier.owner.isInterface) { - val impl = function.resolveFakeOverride()!! - Pair(impl, impl.parentAsClass) - } else { - Pair(function, superQualifier.owner) + val lastStatement = statements.last() + if (statements.size == 1) { + if (lastStatement is JsExpressionStatement) return lastStatement.expression } - val qualifierName = context.getNameForClass(klass).makeRef() - val targetName = context.getNameForMemberFunction(target) - val qPrototype = JsNameRef(targetName, prototypeOf(qualifierName)) - val callRef = JsNameRef(Namer.CALL_FUNCTION, qPrototype) - return JsInvocation(callRef, jsDispatchReceiver?.let { receiver -> listOf(receiver) + arguments } ?: arguments) - } + val newStatements = statements.toMutableList() - val varargParameterIndex = function.valueParameters.indexOfFirst { it.varargElementType != null } - val isExternalVararg = function.isEffectivelyExternal() && varargParameterIndex != -1 - - - if (function is IrConstructor) { - // Inline class primary constructor takes a single value of to - // initialize underlying property. - // TODO: Support initialization block - val klass = function.parentAsClass - return if (klass.isInline) { - assert(function.isPrimary) { - "Inline class secondary constructors must be lowered into static methods" + when (lastStatement) { + is JsReturn -> { } - // Argument value constructs unboxed inline class instance - arguments.single() - } else { - val ref = when { - klass.isEffectivelyExternal() -> - context.getRefForExternalClass(klass) - - else -> - context.getNameForClass(klass).makeRef() + is JsExpressionStatement -> { + newStatements[statements.lastIndex] = JsReturn(lastStatement.expression) } - JsNew(ref, arguments) + // TODO: report warning or even error + else -> newStatements += JsReturn(JsPrefixOperation(JsUnaryOperator.VOID, JsIntLiteral(3))) } + + val syntheticFunction = JsFunction(emptyScope, JsBlock(newStatements), "") + return JsInvocation(syntheticFunction) + } - - require(function is IrSimpleFunction) - - val symbolName = when (jsDispatchReceiver) { - null -> context.getNameForStaticFunction(function) - else -> context.getNameForMemberFunction(function) - } - - val ref = when (jsDispatchReceiver) { - null -> JsNameRef(symbolName) - else -> JsNameRef(symbolName, jsDispatchReceiver) - } - - return if (isExternalVararg) { - - // External vararg arguments should be represented in JS as multiple "plain" arguments (opposed to arrays in Kotlin) - // We are using `Function.prototype.apply` function to pass all arguments as a single array. - // For this purpose are concatenating non-vararg arguments with vararg. - // TODO: Don't use `Function.prototype.apply` when number of arguments is known at compile time (e.g. there are no spread operators) - val arrayConcat = JsNameRef("concat", JsArrayLiteral()) - val arraySliceCall = JsNameRef("call", JsNameRef("slice", JsArrayLiteral())) - - val argumentsAsSingleArray = JsInvocation( - arrayConcat, - listOfNotNull(jsExtensionReceiver) + arguments.mapIndexed { index, argument -> - when (index) { - - // Call `Array.prototype.slice` on vararg arguments in order to convert array-like objects into proper arrays - // TODO: Optimize for proper arrays - varargParameterIndex -> JsInvocation(arraySliceCall, argument) - - // TODO: Don't wrap non-array-like arguments with array literal - // TODO: Wrap adjacent non-vararg arguments in a single array literal - else -> JsArrayLiteral(listOf(argument)) - } - } - ) - - if (jsDispatchReceiver != null) { - // TODO: Do not create IIFE when receiver expression is simple or has no side effects - // TODO: Do not create IIFE at all? (Currently there is no reliable way to create temporary variable in current scope) - val receiverName = JsName("\$externalVarargReceiverTmp") - val receiverRef = receiverName.makeRef() - JsInvocation( - // Create scope for temporary variable holding dispatch receiver - // It is used both during method reference and passing `this` value to `apply` function. - JsNameRef( - "call", - JsFunction( - emptyScope, - JsBlock( - JsVars(JsVars.JsVar(receiverName, jsDispatchReceiver)), - JsReturn( - JsInvocation( - JsNameRef("apply", JsNameRef(symbolName, receiverRef)), - listOf( - receiverRef, - argumentsAsSingleArray - ) - ) - ) - ), - "VarargIIFE" - )), - JsThisRef() - ) - } else { - JsInvocation( - JsNameRef("apply", JsNameRef(symbolName)), - listOf(JsNullLiteral(), argumentsAsSingleArray) - ) - } - } else { - JsInvocation(ref, listOfNotNull(jsExtensionReceiver) + arguments) - } + return translateCall(expression, context, this) } override fun visitWhen(expression: IrWhen, context: JsGenerationContext): JsExpression { @@ -320,7 +193,7 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer expression.argument.accept(this, data) - else -> throw IllegalStateException("All type operator calls except IMPLICIT_CAST should be lowered at this point") + else -> error("All type operator calls except IMPLICIT_CAST should be lowered at this point") } } @@ -396,13 +269,4 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer JsEmpty + 1 -> statements.single() + // TODO: use transparent block (e.g. JsCompositeBlock) + else -> JsBlock(statements) + } + } + return translateCall(expression, data, IrElementToJsExpressionTransformer()).makeStmt() + } + override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall, context: JsGenerationContext): JsStatement { // TODO: implement diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIntrinsicTransformers.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIntrinsicTransformers.kt index 3e506f32906..8b9ba2586b3 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIntrinsicTransformers.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIntrinsicTransformers.kt @@ -8,13 +8,14 @@ package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext import org.jetbrains.kotlin.ir.backend.js.utils.Namer -import org.jetbrains.kotlin.ir.backend.js.utils.emptyScope -import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrConstructor +import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.expressions.IrCall -import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression import org.jetbrains.kotlin.ir.expressions.IrFunctionReference import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol -import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.types.classifierOrFail import org.jetbrains.kotlin.ir.util.getInlineClassBackingField @@ -22,7 +23,7 @@ import org.jetbrains.kotlin.ir.util.getInlinedClass import org.jetbrains.kotlin.ir.util.isEffectivelyExternal import org.jetbrains.kotlin.js.backend.ast.* -typealias IrCallTransformer = (IrFunctionAccessExpression, context: JsGenerationContext) -> JsExpression +typealias IrCallTransformer = (IrCall, context: JsGenerationContext) -> JsExpression class JsIntrinsicTransformers(backendContext: JsIrBackendContext) { private val transformers: Map @@ -100,15 +101,7 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) { } } - addIfNotNull(intrinsics.jsCode) { call, context -> - val jsCode = translateJsCode(call as IrCall) - - when (jsCode) { - is JsExpression -> jsCode - // TODO don't generate function for this case - else -> JsInvocation(JsFunction(emptyScope, jsCode as? JsBlock ?: JsBlock(jsCode as JsStatement), "")) - } - } + addIfNotNull(intrinsics.jsCode) { _, _ -> error("Should not be called") } add(intrinsics.jsGetContinuation) { _, context: JsGenerationContext -> context.continuation @@ -181,7 +174,7 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) { add(intrinsics.jsBind) { call, context: JsGenerationContext -> val receiver = call.getValueArgument(0)!! val reference = call.getValueArgument(1) as IrFunctionReference - val superClass = (call as IrCall).superQualifierSymbol!! + val superClass = call.superQualifierSymbol!! val jsReceiver = receiver.accept(IrElementToJsExpressionTransformer(), context) val functionName = context.getNameForMemberFunction(reference.symbol.owner as IrSimpleFunction) @@ -201,11 +194,15 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) { operator fun get(symbol: IrSymbol): IrCallTransformer? = transformers[symbol] } +private fun translateCallArguments(expression: IrCall, context: JsGenerationContext): List { + return translateCallArguments(expression, context, IrElementToJsExpressionTransformer()) +} + private fun MutableMap.add(functionSymbol: IrSymbol, t: IrCallTransformer) { put(functionSymbol, t) } -private fun MutableMap.add(function: IrFunction, t: IrCallTransformer) { +private fun MutableMap.add(function: IrSimpleFunction, t: IrCallTransformer) { put(function.symbol, t) } @@ -214,20 +211,20 @@ private fun MutableMap.addIfNotNull(symbol: IrSymbo put(symbol, t) } -private fun MutableMap.binOp(function: IrFunctionSymbol, op: JsBinaryOperator) { +private fun MutableMap.binOp(function: IrSimpleFunctionSymbol, op: JsBinaryOperator) { withTranslatedArgs(function) { JsBinaryOperation(op, it[0], it[1]) } } -private fun MutableMap.prefixOp(function: IrFunctionSymbol, op: JsUnaryOperator) { +private fun MutableMap.prefixOp(function: IrSimpleFunctionSymbol, op: JsUnaryOperator) { withTranslatedArgs(function) { JsPrefixOperation(op, it[0]) } } -private fun MutableMap.postfixOp(function: IrFunctionSymbol, op: JsUnaryOperator) { +private fun MutableMap.postfixOp(function: IrSimpleFunctionSymbol, op: JsUnaryOperator) { withTranslatedArgs(function) { JsPostfixOperation(op, it[0]) } } private inline fun MutableMap.withTranslatedArgs( - function: IrFunctionSymbol, + function: IrSimpleFunctionSymbol, crossinline t: (List) -> JsExpression ) { put(function) { call, context -> t(translateCallArguments(call, context)) } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/jsAstUtils.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/jsAstUtils.kt index 830d0734987..9dcf225a5d6 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/jsAstUtils.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/jsAstUtils.kt @@ -7,16 +7,13 @@ package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs import org.jetbrains.kotlin.backend.common.descriptors.isSuspend import org.jetbrains.kotlin.backend.common.ir.isElseBranch -import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext -import org.jetbrains.kotlin.ir.backend.js.utils.Namer -import org.jetbrains.kotlin.ir.backend.js.utils.emptyScope +import org.jetbrains.kotlin.ir.backend.js.utils.* import org.jetbrains.kotlin.ir.declarations.IrFunction -import org.jetbrains.kotlin.ir.expressions.IrExpression -import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression -import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression -import org.jetbrains.kotlin.ir.expressions.IrWhen -import org.jetbrains.kotlin.ir.util.isExternalOrInheritedFromExternal +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.js.backend.ast.* +import org.jetbrains.kotlin.util.OperatorNameConventions fun jsVar(name: JsName, initializer: IrExpression?, context: JsGenerationContext): JsVars { val jsInitializer = initializer?.accept(IrElementToJsExpressionTransformer(), context) @@ -64,8 +61,145 @@ fun translateFunction(declaration: IrFunction, name: JsName?, context: JsGenerat return function } -fun translateCallArguments(expression: IrMemberAccessExpression, context: JsGenerationContext): List { - val transformer = IrElementToJsExpressionTransformer() +private fun isNativeInvoke(call: IrCall): Boolean { + val simpleFunction = call.symbol.owner as? IrSimpleFunction ?: return false + val receiverType = simpleFunction.dispatchReceiverParameter?.type ?: return false + + if (simpleFunction.isSuspend) return false + + return simpleFunction.name == OperatorNameConventions.INVOKE && receiverType.isFunctionTypeOrSubtype() +} + +fun translateCall( + expression: IrCall, + context: JsGenerationContext, + transformer: IrElementToJsExpressionTransformer +): JsExpression { + val function = expression.symbol.owner.realOverrideTarget + require(function is IrSimpleFunction) { "Only IrSimpleFunction could be called via IrCall" } // TODO: fix it in IrCall + + val symbol = function.symbol + + context.staticContext.intrinsics[symbol]?.let { + return it(expression, context) + } + + val jsDispatchReceiver = expression.dispatchReceiver?.accept(transformer, context) + val jsExtensionReceiver = expression.extensionReceiver?.accept(transformer, context) + val arguments = translateCallArguments(expression, context, transformer) + + // Transform external property accessor call + // @JsName-annotated external property accessors are translated as function calls + if (function.getJsName() == null) { + val property = function.correspondingPropertySymbol?.owner + if (property != null && property.isEffectivelyExternal()) { + val nameRef = JsNameRef(context.getNameForProperty(property), 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) + } + + expression.superQualifierSymbol?.let { superQualifier -> + val (target, klass) = if (superQualifier.owner.isInterface) { + val impl = function.resolveFakeOverride()!! + Pair(impl, impl.parentAsClass) + } else { + Pair(function, superQualifier.owner) + } + + val qualifierName = context.getNameForClass(klass).makeRef() + val targetName = context.getNameForMemberFunction(target) + val qPrototype = JsNameRef(targetName, prototypeOf(qualifierName)) + val callRef = JsNameRef(Namer.CALL_FUNCTION, qPrototype) + return JsInvocation(callRef, jsDispatchReceiver?.let { receiver -> listOf(receiver) + arguments } ?: arguments) + } + + val varargParameterIndex = function.valueParameters.indexOfFirst { it.varargElementType != null } + val isExternalVararg = function.isEffectivelyExternal() && varargParameterIndex != -1 + + val symbolName = when (jsDispatchReceiver) { + null -> context.getNameForStaticFunction(function) + else -> context.getNameForMemberFunction(function) + } + + val ref = when (jsDispatchReceiver) { + null -> JsNameRef(symbolName) + else -> JsNameRef(symbolName, jsDispatchReceiver) + } + + return if (isExternalVararg) { + + // External vararg arguments should be represented in JS as multiple "plain" arguments (opposed to arrays in Kotlin) + // We are using `Function.prototype.apply` function to pass all arguments as a single array. + // For this purpose are concatenating non-vararg arguments with vararg. + // TODO: Don't use `Function.prototype.apply` when number of arguments is known at compile time (e.g. there are no spread operators) + val arrayConcat = JsNameRef("concat", JsArrayLiteral()) + val arraySliceCall = JsNameRef("call", JsNameRef("slice", JsArrayLiteral())) + + val argumentsAsSingleArray = JsInvocation( + arrayConcat, + listOfNotNull(jsExtensionReceiver) + arguments.mapIndexed { index, argument -> + when (index) { + + // Call `Array.prototype.slice` on vararg arguments in order to convert array-like objects into proper arrays + // TODO: Optimize for proper arrays + varargParameterIndex -> JsInvocation(arraySliceCall, argument) + + // TODO: Don't wrap non-array-like arguments with array literal + // TODO: Wrap adjacent non-vararg arguments in a single array literal + else -> JsArrayLiteral(listOf(argument)) + } + } + ) + + if (jsDispatchReceiver != null) { + // TODO: Do not create IIFE when receiver expression is simple or has no side effects + // TODO: Do not create IIFE at all? (Currently there is no reliable way to create temporary variable in current scope) + val receiverName = JsName("\$externalVarargReceiverTmp") + val receiverRef = receiverName.makeRef() + JsInvocation( + // Create scope for temporary variable holding dispatch receiver + // It is used both during method reference and passing `this` value to `apply` function. + JsNameRef( + "call", + JsFunction( + emptyScope, + JsBlock( + JsVars(JsVars.JsVar(receiverName, jsDispatchReceiver)), + JsReturn( + JsInvocation( + JsNameRef("apply", JsNameRef(symbolName, receiverRef)), + listOf( + receiverRef, + argumentsAsSingleArray + ) + ) + ) + ), + "VarargIIFE" + ) + ), + JsThisRef() + ) + } else { + JsInvocation( + JsNameRef("apply", JsNameRef(symbolName)), + listOf(JsNullLiteral(), argumentsAsSingleArray) + ) + } + } else { + JsInvocation(ref, listOfNotNull(jsExtensionReceiver) + arguments) + } +} + +fun translateCallArguments(expression: IrMemberAccessExpression, context: JsGenerationContext, transformer: IrElementToJsExpressionTransformer): List { val size = expression.valueArgumentsCount val arguments = (0 until size).mapTo(ArrayList(size)) { index -> @@ -90,7 +224,6 @@ fun defineProperty(receiver: JsExpression, name: String, value: () -> JsExpressi return JsInvocation(objectDefineProperty, receiver, JsStringLiteral(name), value()) } - fun defineProperty(receiver: JsExpression, name: String, getter: JsExpression?, setter: JsExpression? = null) = defineProperty(receiver, name) { val literal = JsObjectLiteral(true) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/jsCode.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/jsCode.kt index e361c7210bc..d64d9494239 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/jsCode.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/jsCode.kt @@ -6,8 +6,8 @@ package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs import com.google.gwt.dev.js.ThrowExceptionOnErrorReporter +import com.google.gwt.dev.js.rhino.CodePosition import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrConst import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrStringConcatenation @@ -15,17 +15,21 @@ import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid -import org.jetbrains.kotlin.js.backend.ast.* -import org.jetbrains.kotlin.js.parser.parse +import org.jetbrains.kotlin.js.backend.ast.JsFunctionScope +import org.jetbrains.kotlin.js.backend.ast.JsProgram +import org.jetbrains.kotlin.js.backend.ast.JsRootScope +import org.jetbrains.kotlin.js.backend.ast.JsStatement +import org.jetbrains.kotlin.js.parser.parseExpressionOrStatement - -fun translateJsCode(call: IrCall): JsNode { - //TODO check non simple compile time constants (expressions) +fun translateJsCodeIntoStatementList(code: IrExpression): List { + // TODO: check non simple compile time constants (expressions) + // TODO: support proper symbol linkage and label clash resolution fun foldString(expression: IrExpression): String { val builder = StringBuilder() expression.acceptVoid(object : IrElementVisitorVoid { - override fun visitElement(element: IrElement) = error("Parameter of js function must be compile time String constant, not ${element.render()}") + override fun visitElement(element: IrElement) = + error("Parameter of js function must be compile time String constant, not ${element.render()}") override fun visitConst(expression: IrConst) { builder.append(expression.kind.valueOf(expression)) @@ -37,15 +41,7 @@ fun translateJsCode(call: IrCall): JsNode { return builder.toString() } - val code = call.getValueArgument(0)!! - val statements = parseJsCode(foldString(code)).orEmpty() - val size = statements.size - - return when (size) { - 0 -> JsEmpty - 1 -> statements[0].let { (it as? JsExpressionStatement)?.expression ?: it } - else -> JsBlock(statements) - } + return parseJsCode(foldString(code)) ?: emptyList() } private fun parseJsCode(jsCode: String): List? { @@ -56,7 +52,7 @@ private fun parseJsCode(jsCode: String): List? { val temporaryRootScope = JsRootScope(JsProgram()) val currentScope = JsFunctionScope(temporaryRootScope, "js") - // TODO write debug info, see how it's done in CallExpressionTranslator.parseJsCode + // TODO: write debug info, see how it's done in CallExpressionTranslator.parseJsCode - return parse(jsCode, ThrowExceptionOnErrorReporter, currentScope, "") + return parseExpressionOrStatement(jsCode, ThrowExceptionOnErrorReporter, currentScope, CodePosition(0, 0), "") } \ No newline at end of file diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsGenerationContext.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsGenerationContext.kt index 5efc7f290e9..0ad389fadc9 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsGenerationContext.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsGenerationContext.kt @@ -7,7 +7,11 @@ package org.jetbrains.kotlin.ir.backend.js.utils import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction -import org.jetbrains.kotlin.js.backend.ast.* +import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.js.backend.ast.JsName +import org.jetbrains.kotlin.js.backend.ast.JsNameRef +import org.jetbrains.kotlin.js.backend.ast.JsScope +import org.jetbrains.kotlin.js.backend.ast.JsThisRef val emptyScope: JsScope get() = object : JsScope("nil") { @@ -42,4 +46,6 @@ class JsGenerationContext( val overriddenSymbols = (currentFunction as? IrSimpleFunction)?.overriddenSymbols ?: return false return staticContext.doResumeFunctionSymbol in overriddenSymbols } + + fun checkIfJsCode(symbol: IrFunctionSymbol): Boolean = symbol == staticContext.backendContext.intrinsics.jsCode } \ No newline at end of file diff --git a/js/js.translator/testData/box/jsCode/functionName.kt b/js/js.translator/testData/box/jsCode/functionName.kt index 8bd2c9f897d..e15dc3bcf75 100644 --- a/js/js.translator/testData/box/jsCode/functionName.kt +++ b/js/js.translator/testData/box/jsCode/functionName.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1280 fun box(): String { return js(""" diff --git a/js/js.translator/testData/box/jsCode/labelNestedClashWithKotlin.kt b/js/js.translator/testData/box/jsCode/labelNestedClashWithKotlin.kt index 8ab0e5da866..6ead65f73a9 100644 --- a/js/js.translator/testData/box/jsCode/labelNestedClashWithKotlin.kt +++ b/js/js.translator/testData/box/jsCode/labelNestedClashWithKotlin.kt @@ -1,3 +1,4 @@ +// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1229 package foo diff --git a/js/js.translator/testData/box/jsCode/objectExpression.kt b/js/js.translator/testData/box/jsCode/objectExpression.kt index 28284f534ad..f856ab1d254 100644 --- a/js/js.translator/testData/box/jsCode/objectExpression.kt +++ b/js/js.translator/testData/box/jsCode/objectExpression.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR // EXPECTED_REACHABLE_NODES: 1282 import kotlin.js.*