From af7ddb45724d8a178308fc5421a72f59c188d897 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Tue, 22 Mar 2016 13:30:11 +0300 Subject: [PATCH] Adds test infrastructure for JS optimizer. Adds simple tests --- .../com/google/gwt/dev/js/JsAstMapper.java | 13 ++ .../google/gwt/dev/js/rhino/IRFactory.java | 4 +- .../src/com/google/gwt/dev/js/rhino/Node.java | 1 + .../js/test/optimizer/BasicOptimizerTest.kt | 147 ++++++++++++++++++ .../optimizer/IfStatementReductionTest.kt | 25 +++ .../TemporaryAssignmentEliminationTest.kt | 27 ++++ .../TemporaryVariableEliminationTest.kt | 25 +++ .../if-reduction/assignment.optimized.js | 15 ++ .../if-reduction/assignment.original.js | 21 +++ .../if-reduction/returnStatement.optimized.js | 13 ++ .../if-reduction/returnStatement.original.js | 18 +++ .../assignment.optimized.js | 20 +++ .../assignment.original.js | 23 +++ .../declaration.optimized.js | 20 +++ .../declaration.original.js | 21 +++ .../returnStatement.optimized.js | 18 +++ .../returnStatement.original.js | 21 +++ .../assignment.optimized.js | 10 ++ .../temporary-variable/assignment.original.js | 12 ++ .../declaration.optimized.js | 10 ++ .../declaration.original.js | 11 ++ 21 files changed, 473 insertions(+), 2 deletions(-) create mode 100644 js/js.tests/test/org/jetbrains/kotlin/js/test/optimizer/BasicOptimizerTest.kt create mode 100644 js/js.tests/test/org/jetbrains/kotlin/js/test/optimizer/IfStatementReductionTest.kt create mode 100644 js/js.tests/test/org/jetbrains/kotlin/js/test/optimizer/TemporaryAssignmentEliminationTest.kt create mode 100644 js/js.tests/test/org/jetbrains/kotlin/js/test/optimizer/TemporaryVariableEliminationTest.kt create mode 100644 js/js.translator/testData/js-optimizer/if-reduction/assignment.optimized.js create mode 100644 js/js.translator/testData/js-optimizer/if-reduction/assignment.original.js create mode 100644 js/js.translator/testData/js-optimizer/if-reduction/returnStatement.optimized.js create mode 100644 js/js.translator/testData/js-optimizer/if-reduction/returnStatement.original.js create mode 100644 js/js.translator/testData/js-optimizer/temporary-assignment/assignment.optimized.js create mode 100644 js/js.translator/testData/js-optimizer/temporary-assignment/assignment.original.js create mode 100644 js/js.translator/testData/js-optimizer/temporary-assignment/declaration.optimized.js create mode 100644 js/js.translator/testData/js-optimizer/temporary-assignment/declaration.original.js create mode 100644 js/js.translator/testData/js-optimizer/temporary-assignment/returnStatement.optimized.js create mode 100644 js/js.translator/testData/js-optimizer/temporary-assignment/returnStatement.original.js create mode 100644 js/js.translator/testData/js-optimizer/temporary-variable/assignment.optimized.js create mode 100644 js/js.translator/testData/js-optimizer/temporary-variable/assignment.original.js create mode 100644 js/js.translator/testData/js-optimizer/temporary-variable/declaration.optimized.js create mode 100644 js/js.translator/testData/js-optimizer/temporary-variable/declaration.original.js 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 fb2b010a60d..d05b6c36814 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 @@ -17,6 +17,7 @@ package com.google.gwt.dev.js; import com.google.dart.compiler.backend.js.ast.*; import com.google.dart.compiler.backend.js.ast.JsLiteral.JsBooleanLiteral; +import com.google.dart.compiler.backend.js.ast.metadata.HasMetadata; import com.google.gwt.dev.js.parserExceptions.JsParserException; import com.google.gwt.dev.js.rhino.*; import com.intellij.util.SmartList; @@ -460,6 +461,12 @@ public class JsAstMapper { private JsExpression mapExpression(Node exprNode) throws JsParserException { JsNode unknown = map(exprNode); + + if (unknown instanceof HasMetadata) { + HasMetadata metadataContainer = (HasMetadata) unknown; + metadataContainer.setData("line", exprNode.getLineno()); + } + if (unknown instanceof JsExpression) { return (JsExpression) unknown; } @@ -878,6 +885,12 @@ public class JsAstMapper { private JsStatement mapStatement(Node nodeStmt) throws JsParserException { JsNode unknown = map(nodeStmt); + + if (unknown instanceof HasMetadata) { + HasMetadata metadataContainer = (HasMetadata) unknown; + metadataContainer.setData("line", nodeStmt.getLineno()); + } + if (unknown != null) { if (unknown instanceof JsStatement) { return (JsStatement) unknown; 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 f374fe8ae80..fbd8d556972 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 @@ -328,8 +328,8 @@ public class IRFactory { int lineno) { if (ifFalse == null) - return new Node(TokenStream.IF, (Node)cond, (Node)ifTrue); - return new Node(TokenStream.IF, (Node)cond, (Node)ifTrue, (Node)ifFalse); + return new Node(TokenStream.IF, (Node)cond, (Node)ifTrue, lineno); + return new Node(TokenStream.IF, (Node)cond, (Node)ifTrue, (Node)ifFalse, lineno); } public Object createTernary(Object cond, Object ifTrue, Object ifFalse) { 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 0fc4d32f110..67b448ad447 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 @@ -416,6 +416,7 @@ public class Node implements Cloneable { case TokenStream.BREAK: case TokenStream.CONTINUE: case TokenStream.WITH: + case TokenStream.IF: return true; } return false; diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/optimizer/BasicOptimizerTest.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/optimizer/BasicOptimizerTest.kt new file mode 100644 index 00000000000..4ca4db60ebe --- /dev/null +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/optimizer/BasicOptimizerTest.kt @@ -0,0 +1,147 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.js.test.optimizer + + +import com.google.dart.compiler.backend.js.ast.* +import com.google.dart.compiler.backend.js.ast.metadata.synthetic +import com.google.dart.compiler.util.TextOutputImpl +import com.google.gwt.dev.js.rhino.CodePosition +import com.google.gwt.dev.js.rhino.ErrorReporter +import com.intellij.openapi.util.io.FileUtil +import org.jetbrains.kotlin.js.inline.clean.FunctionPostProcessor +import org.jetbrains.kotlin.js.parser.parse +import org.jetbrains.kotlin.js.sourceMap.JsSourceGenerationVisitor +import org.jetbrains.kotlin.js.test.BasicTest +import org.jetbrains.kotlin.js.translate.utils.JsAstUtils +import org.junit.Assert +import org.junit.Rule +import org.junit.rules.TestName +import org.mozilla.javascript.Context +import java.io.File + +abstract class BasicOptimizerTest(private var basePath: String) { + @Rule + @JvmField + var testName = TestName() + + protected fun box() { + val methodName = testName.methodName + val baseName = "${BasicTest.TEST_DATA_DIR_PATH}/js-optimizer/$basePath" + val unoptimizedName = "$baseName/$methodName.original.js" + val optimizedName = "$baseName/$methodName.optimized.js" + + val unoptimizedCode = FileUtil.loadFile(File(unoptimizedName)) + val optimizedCode = FileUtil.loadFile(File(optimizedName)) + + runFiles(unoptimizedName, optimizedName, unoptimizedCode, optimizedCode) + checkOptimizer(unoptimizedCode, optimizedCode) + } + + private fun runFiles(unoptimizedName: String, optimizedName: String, unoptimizedCode: String, optimizedCode: String) { + try { + val ctx = Context.enter() + runScript(ctx, unoptimizedName, unoptimizedCode) + runScript(ctx, optimizedName, optimizedCode) + } + finally { + Context.exit() + } + } + + private fun checkOptimizer(unoptimizedCode: String, optimizedCode: String) { + val parserScope = JsFunctionScope(JsRootScope(JsProgram("")), "") + val unoptimizedAst = parse(unoptimizedCode, errorReporter, parserScope) + + updateMetadata(unoptimizedCode, unoptimizedAst) + + for (statement in unoptimizedAst) { + object : RecursiveJsVisitor() { + override fun visitFunction(x: JsFunction) { + FunctionPostProcessor(x.body).apply() + super.visitFunction(x) + } + }.accept(statement) + } + + val optimizedAst = parse(optimizedCode, errorReporter, parserScope) + Assert.assertEquals(astToString(optimizedAst), astToString(unoptimizedAst)) + } + + private fun updateMetadata(code: String, ast: List) { + val comments = findSyntheticComments(code) + + for (stmt in ast) { + object : RecursiveJsVisitor() { + override fun visitVars(x: JsVars) { + x.synthetic = x.vars.any { isSyntheticId(it.name.ident) } + super.visitVars(x) + } + + override fun visitExpressionStatement(x: JsExpressionStatement) { + val assignment = JsAstUtils.decomposeAssignmentToVariable(x.expression) + if (assignment != null) { + val name = assignment.first + x.synthetic = isSyntheticId(name.ident) + } + super.visitExpressionStatement(x) + } + + override fun visitIf(x: JsIf) { + val line = x.getData("line") + if (line != null && line in comments.indices && comments[line]) { + x.synthetic = true + } + super.visitIf(x) + } + }.accept(stmt) + } + } + + private fun findSyntheticComments(code: String): List { + val parts = code.lines() + return parts.map { it.contains("/*synthetic*/") } + } + + private fun isSyntheticId(id: String) = id.startsWith("$") + + + private fun astToString(ast: List): String { + val output = TextOutputImpl() + val visitor = JsSourceGenerationVisitor(output, null) + for (stmt in ast) { + stmt.accept(visitor) + } + return output.toString() + } + + private fun runScript(ctx: Context, fileName: String, code: String) { + val scope = ctx.initStandardObjects() + ctx.evaluateString(scope, code, fileName, 1, null) + val result = ctx.evaluateString(scope, "box()", "unit test", 1, null) + + Assert.assertEquals("box() function must return 'OK'", "OK", result) + } + + private val errorReporter = object : ErrorReporter { + override fun warning(message: String, startPosition: CodePosition, endPosition: CodePosition) { } + + override fun error(message: String, startPosition: CodePosition, endPosition: CodePosition) { + Assert.fail("Error parsing JS file: $message at $startPosition") + } + } +} diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/optimizer/IfStatementReductionTest.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/optimizer/IfStatementReductionTest.kt new file mode 100644 index 00000000000..3e4f25700ea --- /dev/null +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/optimizer/IfStatementReductionTest.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.js.test.optimizer + +import org.junit.Test + +class IfStatementReductionTest : BasicOptimizerTest("if-reduction") { + @Test fun assignment() = box() + + @Test fun returnStatement() = box() +} \ No newline at end of file diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/optimizer/TemporaryAssignmentEliminationTest.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/optimizer/TemporaryAssignmentEliminationTest.kt new file mode 100644 index 00000000000..0a1bd233290 --- /dev/null +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/optimizer/TemporaryAssignmentEliminationTest.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.js.test.optimizer + +import org.junit.Test + +class TemporaryAssignmentEliminationTest : BasicOptimizerTest("temporary-assignment") { + @Test fun assignment() = box() + + @Test fun returnStatement() = box() + + @Test fun declaration() = box() +} \ No newline at end of file diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/optimizer/TemporaryVariableEliminationTest.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/optimizer/TemporaryVariableEliminationTest.kt new file mode 100644 index 00000000000..504ea43355f --- /dev/null +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/optimizer/TemporaryVariableEliminationTest.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.js.test.optimizer + +import org.junit.Test + +class TemporaryVariableEliminationTest : BasicOptimizerTest("temporary-variable") { + @Test fun declaration() = box() + + @Test fun assignment() = box() +} \ No newline at end of file diff --git a/js/js.translator/testData/js-optimizer/if-reduction/assignment.optimized.js b/js/js.translator/testData/js-optimizer/if-reduction/assignment.optimized.js new file mode 100644 index 00000000000..749a21056a5 --- /dev/null +++ b/js/js.translator/testData/js-optimizer/if-reduction/assignment.optimized.js @@ -0,0 +1,15 @@ +function test(n) { + var result; + result = n >= 0 ? n : -n; + return result; +} + +function box() { + var result = test(20); + if (result != 20) return "fail1: " + result; + + result = test(-20); + if (result != 20) return "fail2: " + result; + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/js-optimizer/if-reduction/assignment.original.js b/js/js.translator/testData/js-optimizer/if-reduction/assignment.original.js new file mode 100644 index 00000000000..b94388792e6 --- /dev/null +++ b/js/js.translator/testData/js-optimizer/if-reduction/assignment.original.js @@ -0,0 +1,21 @@ +function test(n) { + var result; + /*synthetic*/ if (n >= 0) { + result = n; + } + else { + result = -n; + } + + return result; +} + +function box() { + var result = test(20); + if (result != 20) return "fail1: " + result; + + result = test(-20); + if (result != 20) return "fail2: " + result; + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/js-optimizer/if-reduction/returnStatement.optimized.js b/js/js.translator/testData/js-optimizer/if-reduction/returnStatement.optimized.js new file mode 100644 index 00000000000..f8a7530bb15 --- /dev/null +++ b/js/js.translator/testData/js-optimizer/if-reduction/returnStatement.optimized.js @@ -0,0 +1,13 @@ +function test(n) { + return n >= 0 ? n : -n; +} + +function box() { + var result = test(20); + if (result != 20) return "fail1: " + result; + + result = test(-20); + if (result != 20) return "fail2: " + result; + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/js-optimizer/if-reduction/returnStatement.original.js b/js/js.translator/testData/js-optimizer/if-reduction/returnStatement.original.js new file mode 100644 index 00000000000..a9122931dfd --- /dev/null +++ b/js/js.translator/testData/js-optimizer/if-reduction/returnStatement.original.js @@ -0,0 +1,18 @@ +function test(n) { + /*synthetic*/ if (n >= 0) { + return n; + } + else { + return -n; + } +} + +function box() { + var result = test(20); + if (result != 20) return "fail1: " + result; + + result = test(-20); + if (result != 20) return "fail2: " + result; + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/js-optimizer/temporary-assignment/assignment.optimized.js b/js/js.translator/testData/js-optimizer/temporary-assignment/assignment.optimized.js new file mode 100644 index 00000000000..b86d64e43d8 --- /dev/null +++ b/js/js.translator/testData/js-optimizer/temporary-assignment/assignment.optimized.js @@ -0,0 +1,20 @@ +function test(n) { + var result; + if (n >= 0) { + result = n; + } + else { + result = -n; + } + return result; +} + +function box() { + var result = test(20); + if (result != 20) return "fail1: " + result; + + result = test(-20); + if (result != 20) return "fail2: " + result; + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/js-optimizer/temporary-assignment/assignment.original.js b/js/js.translator/testData/js-optimizer/temporary-assignment/assignment.original.js new file mode 100644 index 00000000000..30d25e75bc4 --- /dev/null +++ b/js/js.translator/testData/js-optimizer/temporary-assignment/assignment.original.js @@ -0,0 +1,23 @@ +function test(n) { + var result; + var $tmp; + if (n >= 0) { + $tmp = n; + } + else { + $tmp = -n; + } + + result = $tmp; + return result; +} + +function box() { + var result = test(20); + if (result != 20) return "fail1: " + result; + + result = test(-20); + if (result != 20) return "fail2: " + result; + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/js-optimizer/temporary-assignment/declaration.optimized.js b/js/js.translator/testData/js-optimizer/temporary-assignment/declaration.optimized.js new file mode 100644 index 00000000000..c6993a1c74c --- /dev/null +++ b/js/js.translator/testData/js-optimizer/temporary-assignment/declaration.optimized.js @@ -0,0 +1,20 @@ +function test(n) { + var result; + if (n >= 0) { + result = n; + } + else { + result = -n; + } + return result; +} + +function box() { + var result = test(20) + if (result != 20) return "fail1: " + result; + + result = test(-20) + if (result != 20) return "fail2: " + result; + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/js-optimizer/temporary-assignment/declaration.original.js b/js/js.translator/testData/js-optimizer/temporary-assignment/declaration.original.js new file mode 100644 index 00000000000..b0150875e66 --- /dev/null +++ b/js/js.translator/testData/js-optimizer/temporary-assignment/declaration.original.js @@ -0,0 +1,21 @@ +function test(n) { + var $tmp; + if (n >= 0) { + $tmp = n; + } + else { + $tmp = -n; + } + var result = $tmp; + return result; +} + +function box() { + var result = test(20); + if (result != 20) return "fail1: " + result; + + result = test(-20); + if (result != 20) return "fail2: " + result; + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/js-optimizer/temporary-assignment/returnStatement.optimized.js b/js/js.translator/testData/js-optimizer/temporary-assignment/returnStatement.optimized.js new file mode 100644 index 00000000000..02c5403a532 --- /dev/null +++ b/js/js.translator/testData/js-optimizer/temporary-assignment/returnStatement.optimized.js @@ -0,0 +1,18 @@ +function test(n) { + if (n >= 0) { + return n; + } + else { + return -n; + } +} + +function box() { + var result = test(20); + if (result != 20) return "fail1: " + result; + + result = test(-20); + if (result != 20) return "fail2: " + result; + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/js-optimizer/temporary-assignment/returnStatement.original.js b/js/js.translator/testData/js-optimizer/temporary-assignment/returnStatement.original.js new file mode 100644 index 00000000000..397d04abd4b --- /dev/null +++ b/js/js.translator/testData/js-optimizer/temporary-assignment/returnStatement.original.js @@ -0,0 +1,21 @@ +function test(n) { + var $tmp; + if (n >= 0) { + $tmp = n; + } + else { + $tmp = -n; + } + + return $tmp; +} + +function box() { + var result = test(20); + if (result != 20) return "fail1: " + result; + + result = test(-20); + if (result != 20) return "fail2: " + result; + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/js-optimizer/temporary-variable/assignment.optimized.js b/js/js.translator/testData/js-optimizer/temporary-variable/assignment.optimized.js new file mode 100644 index 00000000000..036aec95491 --- /dev/null +++ b/js/js.translator/testData/js-optimizer/temporary-variable/assignment.optimized.js @@ -0,0 +1,10 @@ +function test(a, b, c) { + return a + b + c; +} + +function box() { + var result = test(2, 3, 4); + if (result != 9) return "fail: " + result; + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/js-optimizer/temporary-variable/assignment.original.js b/js/js.translator/testData/js-optimizer/temporary-variable/assignment.original.js new file mode 100644 index 00000000000..f41dcf2371e --- /dev/null +++ b/js/js.translator/testData/js-optimizer/temporary-variable/assignment.original.js @@ -0,0 +1,12 @@ +function test(a, b, c) { + var $tmp; + $tmp = a + b; + return $tmp + c; +} + +function box() { + var result = test(2, 3, 4); + if (result != 9) return "fail: " + result; + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/js-optimizer/temporary-variable/declaration.optimized.js b/js/js.translator/testData/js-optimizer/temporary-variable/declaration.optimized.js new file mode 100644 index 00000000000..036aec95491 --- /dev/null +++ b/js/js.translator/testData/js-optimizer/temporary-variable/declaration.optimized.js @@ -0,0 +1,10 @@ +function test(a, b, c) { + return a + b + c; +} + +function box() { + var result = test(2, 3, 4); + if (result != 9) return "fail: " + result; + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/js-optimizer/temporary-variable/declaration.original.js b/js/js.translator/testData/js-optimizer/temporary-variable/declaration.original.js new file mode 100644 index 00000000000..8ff84e8627b --- /dev/null +++ b/js/js.translator/testData/js-optimizer/temporary-variable/declaration.original.js @@ -0,0 +1,11 @@ +function test(a, b, c) { + var $tmp = a + b; + return $tmp + c; +} + +function box() { + var result = test(2, 3, 4); + if (result != 9) return "fail: " + result; + + return "OK" +} \ No newline at end of file