KJS: transform labeled blocks to labeled do-while
It's a workaround for JDK-8177691. Such code can appear during inline.
This commit is contained in:
committed by
Zalim Bashorov
parent
76fa6ad5c2
commit
678d2e7c21
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.inline.clean
|
||||
|
||||
import org.jetbrains.kotlin.js.backend.ast.*
|
||||
|
||||
object LabeledBlockToDoWhileTransformation {
|
||||
fun apply(fragments: List<JsProgramFragment>) {
|
||||
for (fragment in fragments) {
|
||||
apply(fragment.declarationBlock)
|
||||
apply(fragment.initializerBlock)
|
||||
}
|
||||
}
|
||||
|
||||
fun apply(root: JsNode) {
|
||||
object : JsVisitorWithContextImpl() {
|
||||
override fun endVisit(x: JsLabel, ctx: JsContext<JsNode>) {
|
||||
if (x.statement is JsBlock) {
|
||||
x.statement = JsDoWhile(JsLiteral.FALSE, x.statement)
|
||||
}
|
||||
|
||||
super.endVisit(x, ctx)
|
||||
}
|
||||
}.accept(root)
|
||||
}
|
||||
}
|
||||
@@ -17,18 +17,18 @@
|
||||
package org.jetbrains.kotlin.js.test.optimizer
|
||||
|
||||
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.synthetic
|
||||
import org.jetbrains.kotlin.js.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.backend.ast.*
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.synthetic
|
||||
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.BasicBoxTest
|
||||
import org.jetbrains.kotlin.js.test.createScriptEngine
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||
import org.jetbrains.kotlin.js.util.TextOutputImpl
|
||||
import org.junit.Assert
|
||||
import org.junit.Rule
|
||||
import org.junit.rules.TestName
|
||||
@@ -60,18 +60,22 @@ abstract class BasicOptimizerTest(private var basePath: String) {
|
||||
updateMetadata(unoptimizedCode, unoptimizedAst)
|
||||
|
||||
for (statement in unoptimizedAst) {
|
||||
object : RecursiveJsVisitor() {
|
||||
override fun visitFunction(x: JsFunction) {
|
||||
FunctionPostProcessor(x).apply()
|
||||
super.visitFunction(x)
|
||||
}
|
||||
}.accept(statement)
|
||||
process(statement)
|
||||
}
|
||||
|
||||
val optimizedAst = parse(optimizedCode, errorReporter, parserScope)
|
||||
Assert.assertEquals(astToString(optimizedAst), astToString(unoptimizedAst))
|
||||
}
|
||||
|
||||
protected open fun process(statement: JsStatement) {
|
||||
object : RecursiveJsVisitor() {
|
||||
override fun visitFunction(x: JsFunction) {
|
||||
FunctionPostProcessor(x).apply()
|
||||
super.visitFunction(x)
|
||||
}
|
||||
}.accept(statement)
|
||||
}
|
||||
|
||||
private fun updateMetadata(code: String, ast: List<JsStatement>) {
|
||||
val comments = findSyntheticComments(code)
|
||||
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2010-2017 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.jetbrains.kotlin.js.backend.ast.JsStatement
|
||||
import org.jetbrains.kotlin.js.inline.clean.LabeledBlockToDoWhileTransformation
|
||||
import org.junit.Test
|
||||
|
||||
class LabeledBlockToDoWhileTransformationTest : BasicOptimizerTest("labeled-block-to-do-while") {
|
||||
@Test fun simple() = box()
|
||||
|
||||
override fun process(statement: JsStatement) {
|
||||
LabeledBlockToDoWhileTransformation.apply(statement)
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.js.config.JsConfig;
|
||||
import org.jetbrains.kotlin.js.coroutine.CoroutineTransformer;
|
||||
import org.jetbrains.kotlin.js.facade.exceptions.TranslationException;
|
||||
import org.jetbrains.kotlin.js.inline.JsInliner;
|
||||
import org.jetbrains.kotlin.js.inline.clean.LabeledBlockToDoWhileTransformation;
|
||||
import org.jetbrains.kotlin.js.inline.clean.RemoveUnusedImportsKt;
|
||||
import org.jetbrains.kotlin.js.inline.clean.ResolveTemporaryNamesKt;
|
||||
import org.jetbrains.kotlin.js.translate.general.AstGenerationResult;
|
||||
@@ -124,6 +125,8 @@ public final class K2JSTranslator {
|
||||
|
||||
JsInliner.process(config, analysisResult.getBindingTrace(), translationResult.getInnerModuleName(), allFragments, newFragments);
|
||||
|
||||
LabeledBlockToDoWhileTransformation.INSTANCE.apply(newFragments);
|
||||
|
||||
CoroutineTransformer coroutineTransformer = new CoroutineTransformer(translationResult.getProgram());
|
||||
for (JsProgramFragment fragment : newFragments) {
|
||||
coroutineTransformer.accept(fragment.getDeclarationBlock());
|
||||
@@ -174,6 +177,7 @@ public final class K2JSTranslator {
|
||||
for (JsImportedModule module : translationResult.getImportedModuleList()) {
|
||||
importedModules.add(module.getExternalName());
|
||||
}
|
||||
|
||||
return new TranslationResult.Success(config, files, translationResult.getProgram(), diagnostics, importedModules,
|
||||
moduleDescriptor, bindingTrace.getBindingContext(), metadataHeader, fileMap);
|
||||
}
|
||||
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
var a = eval("true");
|
||||
|
||||
function box() {
|
||||
var functions = [box1, box2, box3];
|
||||
|
||||
for (i in functions) {
|
||||
var f = functions[i];
|
||||
var result = f();
|
||||
|
||||
if (f.toString().indexOf("label: do {") < 0) {
|
||||
// http://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8177691
|
||||
if (result === "OK") return "Looks like JDK-8177691 fixed for " + f;
|
||||
if (result !== void 0) return "Result of function changed: " + f;
|
||||
}
|
||||
else if (result !== "OK") {
|
||||
return "fail on " + f
|
||||
}
|
||||
}
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
function box1() {
|
||||
label: do {
|
||||
try {
|
||||
if (a) throw 1;
|
||||
}
|
||||
catch (e) {
|
||||
break label;
|
||||
}
|
||||
throw 2;
|
||||
} while (false);
|
||||
|
||||
return "OK";
|
||||
}
|
||||
|
||||
function box2() {
|
||||
label: do {
|
||||
try {
|
||||
if (a) throw 1;
|
||||
}
|
||||
finally {
|
||||
break label;
|
||||
}
|
||||
throw 2;
|
||||
} while (false);
|
||||
|
||||
return 'OK';
|
||||
}
|
||||
|
||||
function box3() {
|
||||
label: do {
|
||||
try {
|
||||
throw 1;
|
||||
}
|
||||
finally {
|
||||
break label;
|
||||
}
|
||||
} while (false);
|
||||
|
||||
return 'OK';
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
var a = eval("true");
|
||||
|
||||
function box() {
|
||||
var functions = [box1, box2, box3];
|
||||
|
||||
for (i in functions) {
|
||||
var f = functions[i];
|
||||
var result = f();
|
||||
|
||||
if (f.toString().indexOf("label: do {") < 0) {
|
||||
// See http://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8177691
|
||||
if (result === "OK") return "Looks like JDK-8177691 fixed for " + f;
|
||||
if (result !== void 0) return "Result of function changed: " + f;
|
||||
}
|
||||
else if (result !== "OK") {
|
||||
return "fail on " + f
|
||||
}
|
||||
}
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
function box1() {
|
||||
label: {
|
||||
try {
|
||||
if (a) throw 1;
|
||||
}
|
||||
catch (e) {
|
||||
break label;
|
||||
}
|
||||
throw 2;
|
||||
}
|
||||
|
||||
return 'OK';
|
||||
};
|
||||
|
||||
function box2() {
|
||||
label: {
|
||||
try {
|
||||
if (a) throw 1;
|
||||
}
|
||||
finally {
|
||||
break label;
|
||||
}
|
||||
throw 2;
|
||||
}
|
||||
|
||||
return 'OK';
|
||||
}
|
||||
|
||||
function box3() {
|
||||
label: {
|
||||
try {
|
||||
throw 1;
|
||||
}
|
||||
finally {
|
||||
break label;
|
||||
}
|
||||
}
|
||||
|
||||
return 'OK';
|
||||
}
|
||||
Reference in New Issue
Block a user