chore: fix current state of comments in js call.
diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsCodeOutliningLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsCodeOutliningLowering.kt
index c1dd2ae..a4e0ab3 100644
--- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsCodeOutliningLowering.kt
+++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsCodeOutliningLowering.kt
@@ -11,7 +11,7 @@
 import org.jetbrains.kotlin.ir.IrStatement
 import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
 import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
-import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.translateJsCodeIntoStatementList
+import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.translateJsCodeIntoJsScript
 import org.jetbrains.kotlin.ir.backend.js.utils.emptyScope
 import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
 import org.jetbrains.kotlin.ir.builders.declarations.buildFun
@@ -132,7 +132,8 @@
             return null
 
         val jsCodeArg = expression.getValueArgument(0) ?: compilationException("Expected js code string", expression)
-        val jsStatements = translateJsCodeIntoStatementList(jsCodeArg, backendContext) ?: return null
+        val jsScript = translateJsCodeIntoJsScript(jsCodeArg, backendContext) ?: return null
+        val jsStatements = jsScript.statements
 
         // Collect used Kotlin local variables and parameters.
         val scope = JsScopesCollector().apply { acceptList(jsStatements) }
@@ -175,7 +176,13 @@
                 newStatements += JsReturn(JsPrefixOperation(JsUnaryOperator.VOID, JsIntLiteral(3)))
             }
         }
-        val newFun = JsFunction(emptyScope, JsBlock(newStatements), "")
+
+        val newFun = JsFunction(
+            emptyScope,
+            JsBlock(JsScript(newStatements, jsScript.comments)),
+            ""
+        )
+
         kotlinLocalsUsedInJs.forEach { irParameter ->
             newFun.parameters.add(JsParameter(JsName(irParameter.name.identifier, false)))
         }
diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/FunctionWithJsFuncAnnotationInliner.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/FunctionWithJsFuncAnnotationInliner.kt
index 4874a43..11d5817 100644
--- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/FunctionWithJsFuncAnnotationInliner.kt
+++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/FunctionWithJsFuncAnnotationInliner.kt
@@ -12,24 +12,33 @@
 import org.jetbrains.kotlin.js.backend.ast.*
 
 class FunctionWithJsFuncAnnotationInliner(private val jsFuncCall: IrCall, private val context: JsGenerationContext) {
+    private val script = getJsScript()
     private val function = getJsFunctionImplementation()
     private val replacements = collectReplacementsForCall()
 
-    fun generateResultStatement(): List<JsStatement> {
+    fun generateResultJsScript(): JsScript {
         return function.body.statements
             .run {
                 SimpleJsCodeInliner(replacements)
                     .apply { acceptList(this@run) }
                     .withTemporaryVariablesForExpressions(this)
             }
+            .run {
+                JsScript(this, script.comments)
+            }
     }
 
     private fun getJsFunctionImplementation(): JsFunction {
+        return (script.statements.firstOrNull() as? JsExpressionStatement)
+            ?.let { it.expression as? JsFunction } ?: compilationException("Provided js code is not a js function", jsFuncCall.symbol.owner)
+    }
+
+    private fun getJsScript(): JsScript {
         val code = jsFuncCall.symbol.owner.getJsFunAnnotation() ?: compilationException("JsFun annotation is expected", jsFuncCall)
         val statements = parseJsCode(code) ?: compilationException("Cannot compute js code", jsFuncCall)
         return statements.singleOrNull()
             ?.let { it as? JsExpressionStatement }
-            ?.let { it.expression as? JsFunction } ?: compilationException("Provided js code is not a js function", jsFuncCall.symbol.owner)
+            ?.let { it.expression as? JsScript } ?: compilationException("Provided js code has wrong structure", jsFuncCall.symbol.owner)
     }
 
     private fun collectReplacementsForCall(): Map<JsName, JsExpression> {
@@ -42,7 +51,7 @@
     }
 }
 
-private class SimpleJsCodeInliner(private val replacements: Map<JsName, JsExpression>): RecursiveJsVisitor() {
+private class SimpleJsCodeInliner(private val replacements: Map<JsName, JsExpression>) : RecursiveJsVisitor() {
     private val temporaryNamesForExpressions = mutableMapOf<JsName, JsExpression>()
 
     fun withTemporaryVariablesForExpressions(statements: List<JsStatement>): List<JsStatement> {
diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsCallTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsCallTransformer.kt
index 920ff1d..2cb9e93 100644
--- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsCallTransformer.kt
+++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsCallTransformer.kt
@@ -12,13 +12,13 @@
 import org.jetbrains.kotlin.js.backend.ast.*
 
 class JsCallTransformer(private val jsOrJsFuncCall: IrCall, private val context: JsGenerationContext) {
-    private val statements = getJsStatements()
+    private val script = getJsScript()
 
     fun generateStatement(): JsStatement {
-        if (statements.isEmpty()) return JsEmpty
+        if (script.statements.isEmpty()) return JsEmpty
 
-        val newStatements = statements.toMutableList().apply {
-            val expression = (last() as? JsReturn)?.expression ?: return@apply
+        val newStatements = script.statements.toMutableList().apply {
+            val expression = (script.statements.last() as? JsReturn)?.expression ?: return@apply
 
             if (expression is JsPrefixOperation && expression.operator == JsUnaryOperator.VOID) {
                 removeLastOrNull()
@@ -27,47 +27,56 @@
             }
         }
 
-        return when (newStatements.size) {
-            0 -> JsEmpty
-            1 -> newStatements.single().withSource(jsOrJsFuncCall, context)
+        val statements = when (newStatements.size) {
+            0 -> return JsEmpty
+            1 -> newStatements.map { it.withSource(jsOrJsFuncCall, context) }
             // TODO: use transparent block (e.g. JsCompositeBlock)
-            else -> JsBlock(newStatements)
+            else -> newStatements
         }
+
+        return JsScript(statements, script.comments)
     }
 
     fun generateExpression(): JsExpression {
-        if (statements.isEmpty()) return JsPrefixOperation(JsUnaryOperator.VOID, JsIntLiteral(3)) // TODO: report warning or even error
+        if (script.statements.isEmpty()) return JsPrefixOperation(JsUnaryOperator.VOID, JsIntLiteral(3)) // TODO: report warning or even error
 
-        val lastStatement = statements.last()
+        val lastStatement = script.statements.last()
         val lastExpression = when (lastStatement) {
             is JsReturn -> lastStatement.expression
             is JsExpressionStatement -> lastStatement.expression
             else -> null
         }
-        if (statements.size == 1 && lastExpression != null) {
-            return lastExpression.withSource(jsOrJsFuncCall, context)
+        if (script.statements.size == 1 && lastExpression != null) {
+            return JsScript(
+                listOf(lastExpression.withSource(jsOrJsFuncCall, context).makeStmt()),
+                script.comments
+            )
         }
 
-        val newStatements = statements.toMutableList()
+        val newStatements = script.statements.toMutableList()
 
         when (lastStatement) {
             is JsReturn -> {
             }
             is JsExpressionStatement -> {
-                newStatements[statements.lastIndex] = JsReturn(lastStatement.expression)
+                newStatements[script.statements.lastIndex] = JsReturn(lastStatement.expression)
             }
             // TODO: report warning or even error
             else -> newStatements += JsReturn(JsPrefixOperation(JsUnaryOperator.VOID, JsIntLiteral(3)))
         }
 
-        val syntheticFunction = JsFunction(emptyScope, JsBlock(newStatements), "")
+        val syntheticFunction = JsFunction(
+            emptyScope,
+            JsBlock(JsScript(newStatements, script.comments)),
+            ""
+        )
         return JsInvocation(syntheticFunction).withSource(jsOrJsFuncCall, context)
     }
 
-    private fun getJsStatements(): List<JsStatement> {
+    private fun getJsScript(): JsScript {
         return when {
             context.checkIfJsCode(jsOrJsFuncCall.symbol) -> {
-                translateJsCodeIntoStatementList(
+                translateJsCodeIntoJsScript(
                     jsOrJsFuncCall.getValueArgument(0) ?: compilationException("JsCode is expected", jsOrJsFuncCall),
                     context.staticContext.backendContext
                 )
@@ -75,7 +84,7 @@
             }
 
             context.checkIfAnnotatedWithJsFunc(jsOrJsFuncCall.symbol) ->
-                FunctionWithJsFuncAnnotationInliner(jsOrJsFuncCall, context).generateResultStatement()
+                FunctionWithJsFuncAnnotationInliner(jsOrJsFuncCall, context).generateResultJsScript()
 
             else -> compilationException("`js` function call or function with @JsFunc annotation expected", jsOrJsFuncCall)
         }
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 e3ffbfc..ad88ae5 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
@@ -15,17 +15,16 @@
 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.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.backend.ast.*
 import org.jetbrains.kotlin.js.parser.parseExpressionOrStatement
 
 // Returns null if constant expression could not be parsed
-fun translateJsCodeIntoStatementList(code: IrExpression, context: JsIrBackendContext): List<JsStatement>? {
+fun translateJsCodeIntoJsScript(code: IrExpression, context: JsIrBackendContext): JsScript? {
     // TODO: support proper symbol linkage and label clash resolution
 
     return parseJsCode(foldString(code, context) ?: return null)
+        ?.let { it.firstOrNull() as? JsExpressionStatement }
+        ?.let { it.expression as? JsScript }
 }
 
 fun parseJsCode(jsCode: String): List<JsStatement>? {
diff --git a/js/js.ast/src/org/jetbrains/kotlin/js/backend/JsPrecedenceVisitor.java b/js/js.ast/src/org/jetbrains/kotlin/js/backend/JsPrecedenceVisitor.java
index 358d2f8..eb78cf6 100644
--- a/js/js.ast/src/org/jetbrains/kotlin/js/backend/JsPrecedenceVisitor.java
+++ b/js/js.ast/src/org/jetbrains/kotlin/js/backend/JsPrecedenceVisitor.java
@@ -46,6 +46,12 @@
     }
 
     @Override
+    public void visitScript(@NotNull JsScript x) {
+        JsExpressionStatement statement = (JsExpressionStatement) x.getStatements().get(0);
+        statement.getExpression().accept(this);
+    }
+
+    @Override
     public void visitArrayAccess(@NotNull JsArrayAccess x) {
         answer = 16;
     }
diff --git a/js/js.ast/src/org/jetbrains/kotlin/js/backend/JsToStringGenerationVisitor.java b/js/js.ast/src/org/jetbrains/kotlin/js/backend/JsToStringGenerationVisitor.java
index 6836b37..1630472 100644
--- a/js/js.ast/src/org/jetbrains/kotlin/js/backend/JsToStringGenerationVisitor.java
+++ b/js/js.ast/src/org/jetbrains/kotlin/js/backend/JsToStringGenerationVisitor.java
@@ -54,6 +54,9 @@
     @NotNull
     private final List<Object> sourceInfoStack = new ArrayList<>();
 
+    @NotNull
+    private final Queue<JsComment> commentsQueue = new LinkedList<>();
+
     public static CharSequence javaScriptString(String value) {
         return javaScriptString(value, false);
     }
@@ -194,7 +197,16 @@
     }
 
     @Override
+    protected void visitElement(@NotNull JsNode node) {
+        if (node instanceof SourceInfoAwareJsNode) {
+            maybePrintComment((SourceInfoAwareJsNode) node);
+        }
+    }
+
+    @Override
     public void visitArrayAccess(@NotNull JsArrayAccess x) {
+        super.visitArrayAccess(x);
+
         pushSourceInfo(x.getSource());
 
         printPair(x, x.getArrayExpression());
@@ -207,6 +219,8 @@
 
     @Override
     public void visitArray(@NotNull JsArrayLiteral x) {
+        super.visitArray(x);
+
         pushSourceInfo(x.getSource());
 
         leftSquare();
@@ -230,6 +244,8 @@
 
     @Override
     public void visitBinaryExpression(@NotNull JsBinaryOperation binaryOperation) {
+        super.visitBinaryExpression(binaryOperation);
+
         pushSourceInfo(binaryOperation.getSource());
 
         JsBinaryOperator operator = binaryOperation.getOperator();
@@ -279,11 +295,13 @@
 
     @Override
     public void visitBlock(@NotNull JsBlock x) {
+        super.visitBlock(x);
         printJsBlock(x, true, null);
     }
 
     @Override
     public void visitBoolean(@NotNull JsBooleanLiteral x) {
+        super.visitBoolean(x);
         pushSourceInfo(x.getSource());
 
         if (x.getValue()) {
@@ -298,6 +316,7 @@
 
     @Override
     public void visitBreak(@NotNull JsBreak x) {
+        super.visitBreak(x);
         pushSourceInfo(x.getSource());
 
         p.print(CHARS_BREAK);
@@ -308,6 +327,7 @@
 
     @Override
     public void visitContinue(@NotNull JsContinue x) {
+        super.visitContinue(x);
         pushSourceInfo(x.getSource());
 
         p.print(CHARS_CONTINUE);
@@ -326,6 +346,7 @@
 
     @Override
     public void visitCase(@NotNull JsCase x) {
+        super.visitCase(x);
         pushSourceInfo(x.getSource());
 
         p.print(CHARS_CASE);
@@ -358,6 +379,7 @@
 
     @Override
     public void visitCatch(@NotNull JsCatch x) {
+        super.visitCatch(x);
         pushSourceInfo(x.getSource());
 
         spaceOpt();
@@ -388,6 +410,7 @@
 
     @Override
     public void visitConditional(@NotNull JsConditional x) {
+        super.visitConditional(x);
         pushSourceInfo(x.getSource());
 
         // Associativity: for the then and else branches, it is safe to insert
@@ -424,6 +447,7 @@
 
     @Override
     public void visitDebugger(@NotNull JsDebugger x) {
+        super.visitDebugger(x);
         pushSourceInfo(x.getSource());
 
         p.print(CHARS_DEBUGGER);
@@ -433,6 +457,7 @@
 
     @Override
     public void visitDefault(@NotNull JsDefault x) {
+        super.visitDefault(x);
         pushSourceInfo(x.getSource());
 
         p.print(CHARS_DEFAULT);
@@ -448,6 +473,7 @@
 
     @Override
     public void visitWhile(@NotNull JsWhile x) {
+        super.visitWhile(x);
         pushSourceInfo(x.getSource());
 
         _while();
@@ -467,6 +493,7 @@
 
     @Override
     public void visitDoWhile(@NotNull JsDoWhile x) {
+        super.visitDoWhile(x);
         sourceLocationConsumer.pushSourceInfo(null);
 
         p.print(CHARS_DO);
@@ -495,11 +522,8 @@
     }
 
     @Override
-    public void visitEmpty(@NotNull JsEmpty x) {
-    }
-
-    @Override
     public void visitExpressionStatement(@NotNull JsExpressionStatement x) {
+        super.visitExpressionStatement(x);
         Object source = x.getSource();
         if (source == null && !(x.getExpression() instanceof JsFunction)) {
             source = x.getExpression().getSource();
@@ -520,6 +544,7 @@
 
     @Override
     public void visitFor(@NotNull JsFor x) {
+        super.visitFor(x);
         pushSourceInfo(x.getSource());
 
         _for();
@@ -568,6 +593,7 @@
 
     @Override
     public void visitForIn(@NotNull JsForIn x) {
+        super.visitForIn(x);
         pushSourceInfo(x.getSource());
 
         _for();
@@ -610,6 +636,7 @@
 
     @Override
     public void visitFunction(@NotNull JsFunction x) {
+        super.visitFunction(x);
         pushSourceInfo(x.getSource());
 
         p.print(CHARS_FUNCTION);
@@ -647,6 +674,7 @@
 
     @Override
     public void visitClass(@NotNull JsClass x) {
+        super.visitClass(x);
         pushSourceInfo(x.getSource());
 
         p.print(CHARS_CLASS);
@@ -693,6 +721,7 @@
 
     @Override
     public void visitIf(@NotNull JsIf x) {
+        super.visitIf(x);
         pushSourceInfo(x.getSource());
 
         _if();
@@ -759,6 +788,7 @@
 
     @Override
     public void visitInvocation(@NotNull JsInvocation invocation) {
+        super.visitInvocation(invocation);
         pushSourceInfo(invocation.getSource());
 
         printPair(invocation, invocation.getQualifier());
@@ -772,6 +802,7 @@
 
     @Override
     public void visitLabel(@NotNull JsLabel x) {
+        super.visitLabel(x);
         nameOf(x);
         _colon();
         spaceOpt();
@@ -783,6 +814,7 @@
 
     @Override
     public void visitNameRef(@NotNull JsNameRef nameRef) {
+        super.visitNameRef(nameRef);
         pushSourceInfo(nameRef.getSource());
 
         JsExpression qualifier = nameRef.getQualifier();
@@ -814,6 +846,7 @@
 
     @Override
     public void visitNew(@NotNull JsNew x) {
+        super.visitNew(x);
         pushSourceInfo(x.getSource());
 
         p.print(CHARS_NEW);
@@ -838,6 +871,7 @@
 
     @Override
     public void visitNull(@NotNull JsNullLiteral x) {
+        super.visitNull(x);
         pushSourceInfo(x.getSource());
 
         p.print(CHARS_NULL);
@@ -847,6 +881,7 @@
 
     @Override
     public void visitInt(@NotNull JsIntLiteral x) {
+        super.visitInt(x);
         pushSourceInfo(x.getSource());
 
         p.print(x.value);
@@ -856,6 +891,7 @@
 
     @Override
     public void visitDouble(@NotNull JsDoubleLiteral x) {
+        super.visitDouble(x);
         pushSourceInfo(x.getSource());
 
         p.print(x.value);
@@ -865,6 +901,7 @@
 
     @Override
     public void visitObjectLiteral(@NotNull JsObjectLiteral objectLiteral) {
+        super.visitObjectLiteral(objectLiteral);
         pushSourceInfo(objectLiteral.getSource());
 
         p.print('{');
@@ -937,11 +974,13 @@
 
     @Override
     public void visitParameter(@NotNull JsParameter x) {
+        super.visitParameter(x);
         nameOf(x);
     }
 
     @Override
     public void visitPostfixOperation(@NotNull JsPostfixOperation x) {
+        super.visitPostfixOperation(x);
         pushSourceInfo(x.getSource());
 
         JsUnaryOperator op = x.getOperator();
@@ -955,6 +994,7 @@
 
     @Override
     public void visitPrefixOperation(@NotNull JsPrefixOperation x) {
+        super.visitPrefixOperation(x);
         pushSourceInfo(x.getSource());
 
         JsUnaryOperator op = x.getOperator();
@@ -971,11 +1011,13 @@
 
     @Override
     public void visitProgram(@NotNull JsProgram x) {
+        super.visitProgram(x);
         x.acceptChildren(this);
     }
 
     @Override
     public void visitRegExp(@NotNull JsRegExp x) {
+        super.visitRegExp(x);
         pushSourceInfo(x.getSource());
 
         slash();
@@ -991,6 +1033,7 @@
 
     @Override
     public void visitReturn(@NotNull JsReturn x) {
+        super.visitReturn(x);
         pushSourceInfo(x.getSource());
 
         p.print(CHARS_RETURN);
@@ -1005,6 +1048,7 @@
 
     @Override
     public void visitString(@NotNull JsStringLiteral x) {
+        super.visitString(x);
         pushSourceInfo(x.getSource());
 
         p.print(javaScriptString(x.getValue()));
@@ -1014,6 +1058,7 @@
 
     @Override
     public void visit(@NotNull JsSwitch x) {
+        super.visit(x);
         pushSourceInfo(x.getSource());
 
         p.print(CHARS_SWITCH);
@@ -1035,6 +1080,7 @@
 
     @Override
     public void visitThis(@NotNull JsThisRef x) {
+        super.visitThis(x);
         pushSourceInfo(x.getSource());
 
         p.print(CHARS_THIS);
@@ -1044,6 +1090,7 @@
 
     @Override
     public void visitThrow(@NotNull JsThrow x) {
+        super.visitThrow(x);
         pushSourceInfo(x.getSource());
 
         p.print(CHARS_THROW);
@@ -1055,6 +1102,7 @@
 
     @Override
     public void visitTry(@NotNull JsTry x) {
+        super.visitTry(x);
         p.print(CHARS_TRY);
         spaceOpt();
         lineBreakAfterBlock = false;
@@ -1072,6 +1120,7 @@
 
     @Override
     public void visit(@NotNull JsVar var) {
+        super.visit(var);
         pushSourceInfo(var.getSource());
 
         nameOf(var);
@@ -1092,6 +1141,7 @@
 
     @Override
     public void visitVars(@NotNull JsVars vars) {
+        super.visitVars(vars);
         pushSourceInfo(vars.getSource());
 
         var();
@@ -1124,6 +1174,18 @@
     }
 
     @Override
+    public void visitMultiLineComment(@NotNull JsMultiLineComment comment) {
+        p.print("/*");
+        p.print(comment.getText());
+        p.print("*/");
+        needSemi = false;
+
+        if (comment.getText().contains("\n")) {
+            newline();
+        }
+    }
+
+    @Override
     public void visitDocComment(@NotNull JsDocComment comment) {
         boolean asSingleLine = comment.getTags().size() == 1;
         if (!asSingleLine) {
@@ -1188,6 +1250,7 @@
 
     @Override
     public void visitExport(@NotNull JsExport export) {
+        super.visitExport(export);
         p.print("export");
         space();
         JsExport.Subject subject = export.getSubject();
@@ -1220,6 +1283,7 @@
 
     @Override
     public void visitImport(@NotNull JsImport jsImport) {
+        super.visitImport(jsImport);
         p.print("import {");
         boolean isMultiline = jsImport.getElements().size() > 1;
         p.indentIn();
@@ -1248,6 +1312,44 @@
         p.print(javaScriptString(jsImport.getModule()));
     }
 
+    @Override
+    public void visitScript(@NotNull JsScript script) {
+        commentsQueue.addAll(script.getComments());
+        acceptList(script.getStatements());
+
+        while (!commentsQueue.isEmpty()) {
+            JsComment comment = commentsQueue.poll();
+            printComment(comment);
+        }
+
+        newline();
+    }
+
+    private void maybePrintComment(SourceInfoAwareJsNode node) {
+        if (commentsQueue.isEmpty()) return;
+        JsComment comment = commentsQueue.peek();
+        JsLocation nodeLocation = (JsLocation) node.getSource();
+        JsLocation commentLocation = (JsLocation) comment.getSource();
+
+        if (nodeLocation == null || commentLocation == null) return;
+
+        if (nodeLocation.compareTo(commentLocation) >= 0) {
+            printComment(commentsQueue.poll());
+            maybePrintComment(comment);
+        }
+
+    }
+
+    private void printComment(JsComment comment) {
+        if (comment instanceof JsSingleLineComment) {
+            visitSingleLineComment((JsSingleLineComment) comment);
+        }
+
+        if (comment instanceof JsMultiLineComment) {
+            visitMultiLineComment((JsMultiLineComment) comment);
+        }
+    }
+
     private void newline() {
         p.newline();
         sourceLocationConsumer.newLine();
diff --git a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsComment.kt b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsComment.kt
new file mode 100644
index 0000000..f6075ad
--- /dev/null
+++ b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsComment.kt
@@ -0,0 +1,12 @@
+/*
+ * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin.js.backend.ast
+
+abstract class JsComment(val text: String) : SourceInfoAwareJsNode(), JsStatement {
+    override fun acceptChildren(visitor: JsVisitor) {}
+
+    override fun deepCopy() = this
+}
\ No newline at end of file
diff --git a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsLocation.kt b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsLocation.kt
index 4519d9a..6ce6e8d 100644
--- a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsLocation.kt
+++ b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsLocation.kt
@@ -22,11 +22,18 @@
         override val file: String,
         override val startLine: Int,
         override val startChar: Int
-) : JsLocationWithSource {
+) : JsLocationWithSource, Comparable<JsLocation> {
     override val identityObject: Any? = null
     override val sourceProvider: () -> Reader? = { null }
 
     override fun asSimpleLocation(): JsLocation = this
+
+    override fun compareTo(other: JsLocation): Int {
+        val linesDiff = startLine - other.startLine
+        if (linesDiff != 0) return linesDiff
+
+        return startChar - other.startChar
+    }
 }
 
 interface JsLocationWithSource {
diff --git a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsMultiLineComment.kt b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsMultiLineComment.kt
new file mode 100644
index 0000000..856ae15
--- /dev/null
+++ b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsMultiLineComment.kt
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin.js.backend.ast
+
+class JsMultiLineComment(text: String) : JsComment(text) {
+    override fun accept(visitor: JsVisitor) {
+        visitor.visitMultiLineComment(this)
+    }
+
+    override fun traverse(visitor: JsVisitorWithContext, ctx: JsContext<*>) {
+        visitor.visit(this, ctx)
+        visitor.endVisit(this, ctx)
+    }
+}
\ No newline at end of file
diff --git a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsScript.kt b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsScript.kt
new file mode 100644
index 0000000..bded8a6
--- /dev/null
+++ b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsScript.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin.js.backend.ast
+
+import org.jetbrains.kotlin.js.util.AstUtil
+
+class JsScript(val statements: List<JsStatement>, val comments: List<JsComment>) : JsStatement, JsExpression() {
+    constructor(comments: List<JsComment>) : this(mutableListOf(), comments)
+
+    override fun deepCopy(): JsScript {
+        return JsScript(AstUtil.deepCopy(statements), comments).withMetadataFrom(this);
+    }
+
+    override fun accept(v: JsVisitor) {
+        v.visitScript(this)
+    }
+
+    override fun acceptChildren(visitor: JsVisitor) {
+        visitor.acceptList(statements)
+    }
+
+    override fun traverse(v: JsVisitorWithContext, ctx: JsContext<*>) {
+        if (v.visit(this, ctx)) {
+            v.acceptStatementList(statements)
+        }
+        v.endVisit(this, ctx)
+    }
+}
\ No newline at end of file
diff --git a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsSingleLineComment.kt b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsSingleLineComment.kt
index b299b92..ec7fac9 100644
--- a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsSingleLineComment.kt
+++ b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsSingleLineComment.kt
@@ -5,18 +5,13 @@
 
 package org.jetbrains.kotlin.js.backend.ast
 
-class JsSingleLineComment(val text: String) : SourceInfoAwareJsNode(), JsStatement {
+class JsSingleLineComment(text: String) : JsComment(text) {
     override fun accept(visitor: JsVisitor) {
         visitor.visitSingleLineComment(this)
     }
 
-    override fun acceptChildren(visitor: JsVisitor) {
-    }
-
     override fun traverse(visitor: JsVisitorWithContext, ctx: JsContext<*>) {
         visitor.visit(this, ctx)
         visitor.endVisit(this, ctx)
     }
-
-    override fun deepCopy() = this
 }
\ No newline at end of file
diff --git a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsVisitor.kt b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsVisitor.kt
index 8561755..8dfd510 100644
--- a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsVisitor.kt
+++ b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsVisitor.kt
@@ -39,6 +39,9 @@
     open fun visitBlock(x: JsBlock): Unit =
             visitElement(x)
 
+    open fun visitScript(x: JsScript): Unit =
+            visitElement(x)
+
     open fun visitBoolean(x: JsBooleanLiteral): Unit =
             visitElement(x)
 
@@ -165,6 +168,9 @@
     open fun visitSingleLineComment(comment: JsSingleLineComment): Unit =
             visitElement(comment)
 
+    open fun visitMultiLineComment(comment: JsMultiLineComment): Unit =
+        visitElement(comment)
+
     open fun visitExport(export: JsExport): Unit =
             visitElement(export)
 
diff --git a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsVisitorWithContext.java b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsVisitorWithContext.java
index 955c38e..106fa25 100644
--- a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsVisitorWithContext.java
+++ b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsVisitorWithContext.java
@@ -77,6 +77,9 @@
     public void endVisit(@NotNull JsBlock x, @NotNull JsContext ctx) {
     }
 
+    public void endVisit(@NotNull JsScript x, @NotNull JsContext ctx) {
+    }
+
     public void endVisit(@NotNull JsBooleanLiteral x, @NotNull JsContext ctx) {
         endVisit((JsExpression) x, ctx);
     }
@@ -214,6 +217,9 @@
     public void endVisit(@NotNull JsSingleLineComment x, @NotNull JsContext ctx) {
     }
 
+    public void endVisit(@NotNull JsMultiLineComment x, @NotNull JsContext ctx) {
+    }
+
     public void endVisit(@NotNull JsExport x, @NotNull JsContext ctx) {
     }
 
@@ -240,6 +246,10 @@
         return true;
     }
 
+    public boolean visit(@NotNull JsScript x, @NotNull JsContext ctx) {
+        return true;
+    }
+
     public boolean visit(@NotNull JsBooleanLiteral x, @NotNull JsContext ctx) {
         return true;
     }
@@ -404,6 +414,10 @@
         return true;
     }
 
+    public boolean visit(@NotNull JsMultiLineComment x, @NotNull JsContext ctx) {
+        return true;
+    }
+
     public boolean visit(@NotNull JsExport x, @NotNull JsContext ctx) {
         return true;
     }
diff --git a/js/js.parser/src/com/google/gwt/dev/js/JsAstMapper.java b/js/js.parser/src/com/google/gwt/dev/js/JsAstMapper.java
index fac1ca8..5c7b55f 100644
--- a/js/js.parser/src/com/google/gwt/dev/js/JsAstMapper.java
+++ b/js/js.parser/src/com/google/gwt/dev/js/JsAstMapper.java
@@ -16,15 +16,14 @@
 package com.google.gwt.dev.js;
 
 import com.google.gwt.dev.js.parserExceptions.JsParserException;
-import com.google.gwt.dev.js.rhino.CodePosition;
-import com.google.gwt.dev.js.rhino.Node;
-import com.google.gwt.dev.js.rhino.TokenStream;
+import com.google.gwt.dev.js.rhino.*;
 import com.intellij.util.SmartList;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.kotlin.js.backend.ast.*;
 
 import java.util.ArrayList;
+import java.util.LinkedList;
 import java.util.List;
 
 public class JsAstMapper {
@@ -50,9 +49,7 @@
     private JsNode mapWithoutLocation(Node node) throws JsParserException {
         switch (node.getType()) {
             case TokenStream.SCRIPT: {
-                JsBlock block = new JsBlock();
-                mapStatements(block.getStatements(), node);
-                return block;
+                return mapScriptStatement(node);
             }
 
             case TokenStream.DEBUGGER:
@@ -892,6 +889,12 @@
             return JsEmpty.INSTANCE;
         }
     }
+    public JsScript mapScriptStatement(Node node) {
+        List<JsComment> comments = mapComments(((Node.ScriptNode) node).getFirstComment());
+        JsScript result = new JsScript(comments);
+        mapStatements(result.getStatements(), node);
+        return result;
+    }
 
     private void mapStatements(List<JsStatement> stmts, Node nodeStmts)
             throws JsParserException {
@@ -1107,7 +1110,31 @@
                                     withNode);
     }
 
-    private <T extends JsNode> T withLocation(T astNode, Node node) {
+    private List<JsComment> mapComments(Comment comment) {
+        List<JsComment> comments = new LinkedList<>();
+
+        while (comment != null) {
+            comments.add(mapComment(comment));
+            comment = comment.getNext();
+        }
+
+        return comments;
+    }
+
+    private JsComment mapComment(Comment comment) {
+        JsComment jsComment = comment.isMultiLine() ? mapMultiLineComment(comment) : mapSingleLineComment(comment);
+        return withLocation(jsComment, comment);
+    }
+
+    private JsSingleLineComment mapSingleLineComment(Comment comment) {
+        return new JsSingleLineComment(comment.getContent());
+    }
+
+    private JsMultiLineComment mapMultiLineComment(Comment comment) {
+        return new JsMultiLineComment(comment.getContent());
+    }
+
+    public <T extends JsNode> T withLocation(T astNode, WithCodePosition node) {
         if (astNode == null) return null;
 
         CodePosition location = node.getPosition();
diff --git a/js/js.parser/src/com/google/gwt/dev/js/rhino/Comment.kt b/js/js.parser/src/com/google/gwt/dev/js/rhino/Comment.kt
new file mode 100644
index 0000000..63442dd
--- /dev/null
+++ b/js/js.parser/src/com/google/gwt/dev/js/rhino/Comment.kt
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package com.google.gwt.dev.js.rhino
+
+class Comment(
+    val content: String,
+    override val position: CodePosition,
+    val isMultiLine: Boolean,
+) : WithCodePosition {
+    var next: Comment? = null
+}
\ No newline at end of file
diff --git a/js/js.parser/src/com/google/gwt/dev/js/rhino/IRFactory.java b/js/js.parser/src/com/google/gwt/dev/js/rhino/IRFactory.java
index 1ab1de0..3d72efa 100644
--- a/js/js.parser/src/com/google/gwt/dev/js/rhino/IRFactory.java
+++ b/js/js.parser/src/com/google/gwt/dev/js/rhino/IRFactory.java
@@ -35,6 +35,8 @@
 
 package com.google.gwt.dev.js.rhino;
 
+import jdk.nashorn.internal.parser.Token;
+
 /**
  * This class allows the creation of nodes, and follows the Factory pattern.
  *
@@ -48,9 +50,8 @@
     /**
      * Script (for associating file/url names with toplevel scripts.)
      */
-    public Node createScript(Node body)
-    {
-        Node result = new Node(TokenStream.SCRIPT);
+    public Node.ScriptNode createScript(Node body, Comment firstComment) {
+        Node.ScriptNode result = Node.newScript(firstComment);
         Node children = body.getFirstChild();
         if (children != null)
             result.addChildrenToBack(children);
diff --git a/js/js.parser/src/com/google/gwt/dev/js/rhino/Node.java b/js/js.parser/src/com/google/gwt/dev/js/rhino/Node.java
index faeb0c6..296a5a6 100644
--- a/js/js.parser/src/com/google/gwt/dev/js/rhino/Node.java
+++ b/js/js.parser/src/com/google/gwt/dev/js/rhino/Node.java
@@ -42,7 +42,7 @@
  * This class implements the root of the intermediate representation.
  */
 
-public class Node implements Cloneable {
+public class Node implements Cloneable, WithCodePosition {
 
     private static class NumberNode extends Node {
         NumberNode(int type, double number, CodePosition position) {
@@ -90,6 +90,17 @@
         private String str;
     }
 
+    public static class ScriptNode extends Node {
+        ScriptNode(Comment firstComment, CodePosition position) {
+            super(TokenStream.SCRIPT, position);
+            this.firstComment = firstComment;
+        }
+
+        private Comment firstComment;
+
+        public Comment getFirstComment() { return firstComment; }
+    }
+
     public Node(int nodeType) {
         type = nodeType;
     }
@@ -187,6 +198,10 @@
         return new StringNode(TokenStream.STRING, str, position);
     }
 
+    public static ScriptNode newScript(Comment firstComment) {
+        return new ScriptNode(firstComment, null);
+    }
+
     public static Node newString(int type, String str, CodePosition position) {
         return new StringNode(type, str, position);
     }
@@ -342,6 +357,7 @@
         return operation;
     }
 
+    @Override
     public CodePosition getPosition() {
         return position;
     }
diff --git a/js/js.parser/src/com/google/gwt/dev/js/rhino/Parser.java b/js/js.parser/src/com/google/gwt/dev/js/rhino/Parser.java
index 0cd62bb..af3d13c 100644
--- a/js/js.parser/src/com/google/gwt/dev/js/rhino/Parser.java
+++ b/js/js.parser/src/com/google/gwt/dev/js/rhino/Parser.java
@@ -37,6 +37,7 @@
 
 package com.google.gwt.dev.js.rhino;
 
+import jdk.nashorn.internal.parser.Token;
 import org.jetbrains.annotations.NotNull;
 
 import java.io.IOException;
@@ -137,7 +138,7 @@
             return null;
         }
 
-        return nf.createScript(tempBlock);
+        return nf.createScript(tempBlock, ts.getFirstComment());
     }
 
     /*
@@ -735,6 +736,13 @@
         return pn;
     }
 
+    public Node scriptExpr(TokenStream ts, boolean inForInit) throws IOException, JavaScriptException {
+        Node expression = expr(ts, inForInit);
+        Node tempBlock = nf.createLeaf(TokenStream.BLOCK, ts.tokenPosition);
+        tempBlock.addChildToBack(expression);
+        return nf.createScript(tempBlock, ts.getFirstComment());
+    }
+
     private Node assignExpr(TokenStream ts, boolean inForInit) throws IOException, JavaScriptException {
         Node pn = condExpr(ts, inForInit);
 
diff --git a/js/js.parser/src/com/google/gwt/dev/js/rhino/TokenStream.java b/js/js.parser/src/com/google/gwt/dev/js/rhino/TokenStream.java
index 017f05b..b419260 100644
--- a/js/js.parser/src/com/google/gwt/dev/js/rhino/TokenStream.java
+++ b/js/js.parser/src/com/google/gwt/dev/js/rhino/TokenStream.java
@@ -253,7 +253,7 @@
 
         LAST_TOKEN  = 147,
         NUMBER_INT  = 148,
-    
+
         // This value is only used as a return value for getTokenHelper,
         // which is only called from getToken and exists to avoid an excessive
         // recursion problem if a number of lines in a row are comments.
@@ -412,7 +412,7 @@
                 case JSR:             return "jsr";
                 case NEWLOCAL:        return "newlocal";
                 case USELOCAL:        return "uselocal";
-                case SCRIPT:          return "script";
+                case SCRIPT:        return "script";
             }
             return "<unknown="+token+">";
         }
@@ -1059,19 +1059,29 @@
         case '/':
             // is it a // comment?
             if (in.match('/')) {
-                skipLine();
+                CodePosition commentPosition = tokenPosition;
+                stringBufferTop = 0;
+                while ((c = in.read()) != -1 && c != '\n') {
+                    addToString(c);
+                }
+                this.addSingleLineComment(new String(stringBuffer, 0, stringBufferTop), commentPosition);
                 return RETRY_TOKEN;
             }
             if (in.match('*')) {
+                CodePosition commentPosition = tokenPosition;
+                stringBufferTop = 0;
                 while ((c = in.read()) != -1 &&
                        !(c == '*' && in.match('/'))) {
+                    addToString(c);
                     ; // empty loop body
                 }
                 if (c == EOF_CHAR) {
                     reportTokenError("msg.unterminated.comment", null);
                     return ERROR;
                 }
-                return RETRY_TOKEN;  // `goto retry'
+
+                this.addMultiLineComment(new String(stringBuffer, 0, stringBufferTop), commentPosition);
+                return RETRY_TOKEN;
             }
 
             // is it a regexp?
@@ -1454,7 +1464,26 @@
         }
     }
 
+    private void addComment(Comment comment) {
+        if (firstComment == null) {
+            firstComment = comment;
+            currentComment = comment;
+        } else {
+            currentComment.setNext(comment);
+            currentComment = comment;
+        }
+    }
+
+    private void addSingleLineComment(String content, CodePosition position) {
+        addComment(new Comment(content, position, false));
+    }
+
+    private void addMultiLineComment(String content, CodePosition position) {
+        addComment(new Comment(content, position, true));
+    }
+
     public String getSourceName() { return sourceName; }
+    public Comment getFirstComment() { return firstComment; }
     public int getLineno() { return in.getLineno(); }
     public int getOp() { return op; }
     public String getString() { return string; }
@@ -1496,4 +1525,7 @@
 
     private char[] stringBuffer = new char[128];
     private int stringBufferTop;
+
+    private Comment firstComment;
+    private Comment currentComment;
 }
diff --git a/js/js.parser/src/com/google/gwt/dev/js/rhino/WithCodePosition.kt b/js/js.parser/src/com/google/gwt/dev/js/rhino/WithCodePosition.kt
new file mode 100644
index 0000000..cc1708c
--- /dev/null
+++ b/js/js.parser/src/com/google/gwt/dev/js/rhino/WithCodePosition.kt
@@ -0,0 +1,10 @@
+/*
+ * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package com.google.gwt.dev.js.rhino
+
+interface WithCodePosition {
+    val position: CodePosition
+}
\ No newline at end of file
diff --git a/js/js.parser/src/org/jetbrains/kotlin/js/parser/parserUtils.kt b/js/js.parser/src/org/jetbrains/kotlin/js/parser/parserUtils.kt
index f76615c..69915d0 100644
--- a/js/js.parser/src/org/jetbrains/kotlin/js/parser/parserUtils.kt
+++ b/js/js.parser/src/org/jetbrains/kotlin/js/parser/parserUtils.kt
@@ -38,7 +38,7 @@
     val accumulatingReporter = AccumulatingReporter()
     val exprNode = try {
         parse(code, startPosition, 0, accumulatingReporter, true) {
-            val result = expr(it, false)
+            val result = scriptExpr(it, false)
             if (it.token != TokenStream.EOF) {
                 accumulatingReporter.hasErrors = true
             }
@@ -61,7 +61,7 @@
     else {
         val node = parse(code, startPosition, 0, reporter, true, Parser::parse)
         node?.toJsAst(scope, fileName) {
-            mapStatements(it)
+            listOf(JsExpressionStatement(mapScriptStatement(it)))
         }
     }
 }
@@ -71,7 +71,9 @@
         addListener(FunctionParsingObserver())
         primaryExpr(it)
     }
-    return rootNode?.toJsAst(scope, fileName, JsAstMapper::mapFunction)
+    return rootNode?.toJsAst(scope, fileName) {
+        mapFunction(it)
+    }
 }
 
 private class FunctionParsingObserver : ParserListener {
diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/BoxJsTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/BoxJsTestGenerated.java
index ee99ae0..22ad11b3 100644
--- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/BoxJsTestGenerated.java
+++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/BoxJsTestGenerated.java
@@ -6109,6 +6109,12 @@
         }
 
         @Test
+        @TestMetadata("comments.kt")
+        public void testComments() throws Exception {
+            runTest("js/js.translator/testData/box/jsCode/comments.kt");
+        }
+
+        @Test
         @TestMetadata("constantExpression.kt")
         public void testConstantExpression() throws Exception {
             runTest("js/js.translator/testData/box/jsCode/constantExpression.kt");
diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java
index 497afc6..15062e3 100644
--- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java
+++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java
@@ -6487,6 +6487,12 @@
         }
 
         @Test
+        @TestMetadata("comments.kt")
+        public void testComments() throws Exception {
+            runTest("js/js.translator/testData/box/jsCode/comments.kt");
+        }
+
+        @Test
         @TestMetadata("constantExpression.kt")
         public void testConstantExpression() throws Exception {
             runTest("js/js.translator/testData/box/jsCode/constantExpression.kt");
diff --git a/js/js.translator/testData/box/inline/jsCode.kt b/js/js.translator/testData/box/inline/jsCode.kt
index 3934fab..d0459bb 100644
--- a/js/js.translator/testData/box/inline/jsCode.kt
+++ b/js/js.translator/testData/box/inline/jsCode.kt
@@ -5,7 +5,7 @@
 // CHECK_CONTAINS_NO_CALLS: test TARGET_BACKENDS=JS
 // CHECK_NOT_CALLED_IN_SCOPE: function=sum scope=test
 
-internal inline fun sum(x: Int, y: Int): Int = js("x + y")
+fun sum(x: Int, y: Int): Int = js("/*before x*/ x /*before +*/ + /*after +*/ y /*after y*/")
 
 internal fun test(x: Int, y: Int): Int = sum(sum(x, x), sum(y, y))
 
diff --git a/js/js.translator/testData/box/jsCode/comments.kt b/js/js.translator/testData/box/jsCode/comments.kt
new file mode 100644
index 0000000..361dd30
--- /dev/null
+++ b/js/js.translator/testData/box/jsCode/comments.kt
@@ -0,0 +1,33 @@
+// EXPECTED_REACHABLE_NODES: 1282
+package foo
+
+fun simpleSingleLineComment() {
+    js("""
+       // This is 'simpleSingleLineComment' comment  
+       console.log('simpleSingleLineComment');
+    """)
+}
+
+fun simpleMultilineComment() {
+    js("""
+       /* 
+        This is 'simpleMultilineComment' comment 
+        */
+       console.log('simpleSingleLineComment');
+    """)
+}
+
+fun complexMultilineComment() {
+    js("""
+       function mul(a/*: float*/, b/*: float*/)/*: int*/ {
+          return /*int(*/a/*)*/ * /*int(*/b/*)*/;
+       }
+    """)
+}
+
+fun box(): String {
+    simpleSingleLineComment()
+    simpleMultilineComment()
+    complexMultilineComment()
+    return "OK"
+}
\ No newline at end of file