KJS: switch to using Nashorn instead of Rhino for JS backend tests

This commit is contained in:
Zalim Bashorov
2017-04-21 16:39:39 +03:00
parent a39a0abb2a
commit 76fa6ad5c2
18 changed files with 542 additions and 747 deletions
@@ -20,8 +20,7 @@ import com.intellij.openapi.util.io.FileUtil;
import kotlin.collections.CollectionsKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.js.test.rhino.RhinoFunctionResultChecker;
import org.jetbrains.kotlin.js.test.rhino.RhinoUtils;
import org.jetbrains.kotlin.js.test.NashornJsTestChecker;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import java.io.File;
@@ -59,7 +58,7 @@ public class AntTaskJsTest extends AbstractAntTaskTest {
List<String> filePaths = CollectionsKt.map(fileNames, s -> getOutputFileByName(s).getAbsolutePath());
RhinoUtils.runRhinoTest(filePaths, new RhinoFunctionResultChecker("out", "foo", "box", "OK", withModuleSystem));
NashornJsTestChecker.INSTANCE.check(filePaths, "out", "foo", "box", "OK", withModuleSystem);
}
private void doJsAntTestForPostfixPrefix(@Nullable String prefix, @Nullable String postfix) throws Exception {
@@ -39,8 +39,6 @@ import org.jetbrains.kotlin.js.facade.K2JSTranslator
import org.jetbrains.kotlin.js.facade.MainCallParameters
import org.jetbrains.kotlin.js.facade.TranslationResult
import org.jetbrains.kotlin.js.facade.TranslationUnit
import org.jetbrains.kotlin.js.test.rhino.RhinoFunctionResultChecker
import org.jetbrains.kotlin.js.test.rhino.RhinoUtils
import org.jetbrains.kotlin.js.test.utils.DirectiveTestUtils
import org.jetbrains.kotlin.js.test.utils.JsTestUtils
import org.jetbrains.kotlin.js.test.utils.verifyAst
@@ -165,8 +163,7 @@ abstract class BasicBoxTest(
expectedResult: String,
withModuleSystem: Boolean
) {
val checker = RhinoFunctionResultChecker(testModuleName, testPackage, testFunction, expectedResult, withModuleSystem)
RhinoUtils.runRhinoTest(jsFiles, checker)
NashornJsTestChecker.check(jsFiles, testModuleName, testPackage, testFunction, expectedResult, withModuleSystem)
}
protected open fun performAdditionalChecks(generatedJsFiles: List<String>, outputPrefixFile: File?, outputPostfixFile: File?) {}
@@ -0,0 +1,128 @@
/*
* 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
import jdk.nashorn.api.scripting.NashornScriptEngineFactory
import jdk.nashorn.api.scripting.ScriptObjectMirror
import jdk.nashorn.internal.runtime.ScriptRuntime
import org.junit.Assert
import javax.script.Invocable
import javax.script.ScriptEngine
fun createScriptEngine(): ScriptEngine =
// TODO use "-strict"
NashornScriptEngineFactory().getScriptEngine("--language=es5", "--no-java", "--no-syntax-extensions")
private fun ScriptEngine.loadFile(path: String) {
eval("load('$path');")
}
private fun ScriptObjectMirror.toMapWithAllMembers(): Map<String, Any?> = getOwnKeys(true).associate { it to this[it] }
object NashornJsTestChecker {
private val SETUP_KOTLIN_OUTPUT = "kotlin.kotlin.io.output = new kotlin.kotlin.io.BufferedOutput();"
private val GET_KOTLIN_OUTPUT = "kotlin.kotlin.io.output.buffer;"
private val engine = createScriptEngineForTest()
fun check(
files: List<String>,
testModuleName: String,
testPackageName: String?,
testFunctionName: String,
expectedResult: String,
withModuleSystem: Boolean
) {
val actualResult = run(files, testModuleName, testPackageName, testFunctionName, withModuleSystem)
Assert.assertEquals(expectedResult, actualResult)
}
fun checkStdout(files: List<String>, expectedResult: String) {
run(files)
val actualResult = engine.eval(GET_KOTLIN_OUTPUT)
Assert.assertEquals(expectedResult, actualResult)
}
fun run(files: List<String>) {
run(files) { null }
}
private fun run(
files: List<String>,
testModuleName: String,
testPackageName: String?,
testFunctionName: String,
withModuleSystem: Boolean
) = run(files) {
val testModule =
when {
withModuleSystem ->
engine.eval(BasicBoxTest.Companion.KOTLIN_TEST_INTERNAL + ".require('" + testModuleName + "')") as ScriptObjectMirror
else ->
engine.get(testModuleName) as ScriptObjectMirror
}
val testPackage =
when {
testPackageName === null ->
testModule
testPackageName.contains(".") ->
testPackageName.split(".").fold(testModule) { p, part -> p[part] as ScriptObjectMirror }
else ->
testModule[testPackageName]!!
}
(engine as Invocable).invokeMethod(testPackage, testFunctionName)
}
private fun run(
files: List<String>,
f: ScriptEngine.() -> Any?
): Any? {
val globalObject = engine.eval("this") as ScriptObjectMirror
val before = globalObject.toMapWithAllMembers()
engine.eval(SETUP_KOTLIN_OUTPUT)
try {
files.forEach(engine::loadFile)
return engine.f()
}
finally {
val after = globalObject.toMapWithAllMembers()
val diff = after.entries - before.entries
diff.forEach {
globalObject.put(it.key, before[it.key] ?: ScriptRuntime.UNDEFINED)
}
}
}
private fun createScriptEngineForTest(): ScriptEngine {
val engine = createScriptEngine()
listOf(
BasicBoxTest.TEST_DATA_DIR_PATH + "nashorn-polyfills.js",
BasicBoxTest.DIST_DIR_JS_PATH + "kotlin.js",
BasicBoxTest.DIST_DIR_JS_PATH + "kotlin-test.js"
).forEach(engine::loadFile)
engine.eval("this['kotlin-test'].kotlin.test.overrideAsserter_wbnzx$(new this['kotlin-test'].kotlin.test.DefaultAsserter());")
return engine
}
}
@@ -27,11 +27,11 @@ 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.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) {
@@ -48,21 +48,11 @@ abstract class BasicOptimizerTest(private var basePath: String) {
val unoptimizedCode = FileUtil.loadFile(File(unoptimizedName))
val optimizedCode = FileUtil.loadFile(File(optimizedName))
runFiles(unoptimizedName, optimizedName, unoptimizedCode, optimizedCode)
runScript(unoptimizedName, unoptimizedCode)
runScript(optimizedName, 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()), "<js fun>")
val unoptimizedAst = parse(unoptimizedCode, errorReporter, parserScope)
@@ -133,12 +123,12 @@ abstract class BasicOptimizerTest(private var basePath: String) {
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)
private fun runScript(fileName: String, code: String) {
val engine = createScriptEngine()
engine.eval(code)
val result = engine.eval("box()")
Assert.assertEquals("box() function must return 'OK'", "OK", result)
Assert.assertEquals("$fileName: box() function must return 'OK'", "OK", result)
}
private val errorReporter = object : ErrorReporter {
@@ -1,84 +0,0 @@
/*
* 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.rhino;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.js.test.BasicBoxTest;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
import static org.jetbrains.kotlin.js.test.rhino.RhinoUtils.flushSystemOut;
import static org.junit.Assert.assertEquals;
public class RhinoFunctionResultChecker implements RhinoResultChecker {
private final String moduleId;
private final String packageName;
private final String functionName;
private final Object expectedResult;
private final boolean withModuleSystem;
public RhinoFunctionResultChecker(
@NotNull String moduleId,
@Nullable String packageName,
@NotNull String functionName,
@NotNull Object expectedResult,
boolean withModuleSystem
) {
this.moduleId = moduleId;
this.packageName = packageName;
this.functionName = functionName;
this.expectedResult = expectedResult;
this.withModuleSystem = withModuleSystem;
}
@Override
public void runChecks(Context context, Scriptable scope) throws Exception {
Object result = evaluateFunction(context, scope);
flushSystemOut(context, scope);
assertResultValid(result, context);
}
private void assertResultValid(Object result, Context context) {
String ecmaVersion = context.getLanguageVersion() == Context.VERSION_1_8 ? "ecma5" : "ecma3";
assertEquals("Result of " + packageName + "." + functionName + "() is not what expected (" + ecmaVersion + ")!", expectedResult, result);
}
private Object evaluateFunction(Context cx, Scriptable scope) {
return cx.evaluateString(scope, functionCallString(), "function call", 0, null);
}
private String functionCallString() {
StringBuilder sb = new StringBuilder();
if (withModuleSystem) {
sb.append(BasicBoxTest.KOTLIN_TEST_INTERNAL).append(".require('").append(moduleId).append("')");
}
else if (moduleId.contains(".")) {
sb.append("this['").append(moduleId).append("']");
}
else {
sb.append(moduleId);
}
if (packageName != null) {
sb.append('.').append(packageName);
}
return sb.append(".").append(functionName).append("()").toString();
}
}
@@ -1,24 +0,0 @@
/*
* Copyright 2010-2015 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.rhino;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
public interface RhinoResultChecker {
void runChecks(Context context, Scriptable scope) throws Exception;
}
@@ -1,62 +0,0 @@
/*
* Copyright 2010-2015 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.rhino;
import org.jetbrains.annotations.NotNull;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
import static org.jetbrains.kotlin.js.test.rhino.RhinoUtils.GET_KOTLIN_OUTPUT;
import static org.junit.Assert.assertTrue;
public final class RhinoSystemOutputChecker implements RhinoResultChecker {
private final String expectedResult;
public RhinoSystemOutputChecker(@NotNull String expectedResult) {
this.expectedResult = expectedResult;
}
@Override
public void runChecks(@NotNull Context context, @NotNull Scriptable scope)
throws Exception {
String result = getSystemOutput(context, scope);
String trimmedExpected = trimSpace(expectedResult);
String trimmedActual = trimSpace(result);
assertTrue("Returned:\n" + trimmedActual + "END_OF_RETURNED\nExpected:\n" + trimmedExpected
+ "END_OF_EXPECTED\n", trimmedExpected.equals(trimmedActual));
}
@NotNull
private static String getSystemOutput(@NotNull Context context, @NotNull Scriptable scope) {
Object output = context.evaluateString(scope, GET_KOTLIN_OUTPUT, "test", 0, null);
RhinoUtils.flushSystemOut(context, scope);
assertTrue("Output should be a string.", output instanceof String);
return (String) output;
}
@NotNull
private static String trimSpace(@NotNull String s) {
String[] choppedUpString = s.trim().split("\\s");
StringBuilder sb = new StringBuilder();
for (String word : choppedUpString) {
sb.append(word);
}
return sb.toString();
}
}
@@ -1,137 +0,0 @@
/*
* Copyright 2010-2015 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.rhino;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.js.config.EcmaVersion;
import org.jetbrains.kotlin.utils.ExceptionUtilsKt;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import static org.jetbrains.kotlin.js.test.BasicBoxTest.DIST_DIR_JS_PATH;
public final class RhinoUtils {
private static final int OPTIMIZATION_OFF = -1;
private static final String SETUP_KOTLIN_OUTPUT = "kotlin.kotlin.io.output = new kotlin.kotlin.io.BufferedOutput();";
private static final String FLUSH_KOTLIN_OUTPUT = "kotlin.kotlin.io.output.flush();";
public static final String GET_KOTLIN_OUTPUT = "kotlin.kotlin.io.output.buffer;";
@NotNull
private static final Map<EcmaVersion, ScriptableObject> versionToScope = ContainerUtil.newHashMap();
private RhinoUtils() {
}
private static void runFileWithRhino(@NotNull String inputFile,
@NotNull Context context,
@NotNull Scriptable scope) throws Exception {
String result;
try {
result = FileUtil.loadFile(new File(inputFile), CharsetToolkit.UTF8, true);
}
catch (IOException e) {
throw new RuntimeException(e);
}
context.setOptimizationLevel(-1);
context.evaluateString(scope, result, inputFile, 1, null);
}
public static void runRhinoTest(@NotNull List<String> fileNames, @NotNull RhinoResultChecker checker) throws Exception {
EcmaVersion ecmaVersion = EcmaVersion.defaultVersion();
Context context = createContext(ecmaVersion);
context.setOptimizationLevel(OPTIMIZATION_OFF);
try {
Scriptable scope = getScope(ecmaVersion, context);
context.evaluateString(scope, SETUP_KOTLIN_OUTPUT, "setup kotlin output", 0, null);
for (String filename : fileNames) {
runFileWithRhino(filename, context, scope);
}
finishScope(scope);
checker.runChecks(context, scope);
}
finally {
Context.exit();
}
}
@NotNull
private static Scriptable getScope(@NotNull EcmaVersion version, @NotNull Context context) {
Scriptable parentScope = getParentScope(version, context);
Scriptable scope = context.newObject(parentScope);
scope.put("kotlin-test", scope, parentScope.get("kotlin-test", parentScope));
return scope;
}
private static void finishScope(@NotNull Scriptable scope) {
scope.delete("kotlin-test");
}
@NotNull
private static Scriptable getParentScope(@NotNull EcmaVersion version, @NotNull Context context) {
return versionToScope.computeIfAbsent(version, v -> initScope(context));
}
@NotNull
private static ScriptableObject initScope(@NotNull Context context) {
ScriptableObject scope = context.initStandardObjects();
try {
runFileWithRhino(DIST_DIR_JS_PATH + "../../js/js.translator/testData/rhino-polyfills.js", context, scope);
runFileWithRhino(DIST_DIR_JS_PATH + "kotlin.js", context, scope);
runFileWithRhino(DIST_DIR_JS_PATH + "kotlin-test.js", context, scope);
context.evaluateString(scope,
"this['kotlin-test'].kotlin.test.overrideAsserter_wbnzx$(new this['kotlin-test'].kotlin.test.DefaultAsserter());",
"change asserter to DefaultAsserter", 1, null);
}
catch (Exception e) {
throw ExceptionUtilsKt.rethrow(e);
}
return scope;
}
//TODO:
@NotNull
private static Context createContext(@NotNull EcmaVersion ecmaVersion) {
Context context = Context.enter();
if (ecmaVersion == EcmaVersion.v5) {
// actually, currently, doesn't matter because dart doesn't produce js 1.8 code (expression closures)
context.setLanguageVersion(Context.VERSION_1_8);
}
return context;
}
static void flushSystemOut(@NotNull Context context, @NotNull Scriptable scope) {
context.evaluateString(scope, FLUSH_KOTLIN_OUTPUT, "test", 0, null);
}
}
@@ -19,9 +19,9 @@ package org.jetbrains.kotlin.js.test.semantics
import com.google.common.collect.Lists
import org.jetbrains.kotlin.js.facade.MainCallParameters
import org.jetbrains.kotlin.js.test.BasicBoxTest
import org.jetbrains.kotlin.js.test.rhino.RhinoSystemOutputChecker
import org.jetbrains.kotlin.js.test.rhino.RhinoUtils
import org.jetbrains.kotlin.js.test.NashornJsTestChecker
import java.io.File
import javax.script.ScriptException
abstract class AbstractWebDemoExamplesTest(relativePath: String) : BasicBoxTest(
BasicBoxTest.TEST_DATA_DIR_PATH + "/$relativePath/",
@@ -36,9 +36,10 @@ abstract class AbstractWebDemoExamplesTest(relativePath: String) : BasicBoxTest(
expectedResult: String,
withModuleSystem: Boolean
) {
RhinoUtils.runRhinoTest(jsFiles, RhinoSystemOutputChecker(expectedResult))
NashornJsTestChecker.checkStdout(jsFiles, expectedResult)
}
@Throws(ScriptException::class)
protected fun runMainAndCheckOutput(fileName: String, expectedResult: String, vararg args: String) {
doTest(pathToTestDir + fileName, expectedResult, MainCallParameters.mainWithArguments(Lists.newArrayList(*args)))
}
@@ -17,10 +17,9 @@
package org.jetbrains.kotlin.js.test.semantics
import org.jetbrains.kotlin.js.test.BasicBoxTest
import org.jetbrains.kotlin.js.test.rhino.RhinoResultChecker
import org.jetbrains.kotlin.js.test.rhino.RhinoUtils
import org.mozilla.javascript.JavaScriptException
import org.jetbrains.kotlin.js.test.NashornJsTestChecker
import java.io.File
import javax.script.ScriptException
class MultiModuleOrderTest : BasicBoxTest("$TEST_DATA_DIR_PATH/multiModuleOrder/cases/", "$TEST_DATA_DIR_PATH/multiModuleOrder/out/") {
fun testPlain() {
@@ -42,11 +41,9 @@ class MultiModuleOrderTest : BasicBoxTest("$TEST_DATA_DIR_PATH/multiModuleOrder/
val mainJsFile = File(parentDir, "$name-main_v5.js").path
val libJsFile = File(parentDir, "$name-lib_v5.js").path
try {
RhinoUtils.runRhinoTest(listOf(mainJsFile, libJsFile), RhinoResultChecker { _, _ ->
// don't check anything, expect exception from function
})
NashornJsTestChecker.run(listOf(mainJsFile, libJsFile))
}
catch (e: JavaScriptException) {
catch (e: ScriptException) {
val message = e.message!!
assertTrue("Exception message should contain reference to dependency (lib)", "'lib'" in message)
assertTrue("Exception message should contain reference to module that failed to load (main)", "'main'" in message)
@@ -17,7 +17,8 @@
package org.jetbrains.kotlin.js.test.semantics;
import org.jetbrains.annotations.NotNull;
import org.mozilla.javascript.EcmaError;
import javax.script.ScriptException;
/*
* We can't really check that this examples work in non-browser environment, so we just check that examples compile and
@@ -50,8 +51,8 @@ public final class WebDemoCanvasExamplesTest extends AbstractWebDemoExamplesTest
runMainAndCheckOutput(filename, "");
fail();
}
catch (EcmaError e) {
String expectedErrorMessage = "ReferenceError: \"" + firstUnknownSymbolEncountered + "\" is not defined.";
catch (ScriptException e) {
String expectedErrorMessage = "ReferenceError: \"" + firstUnknownSymbolEncountered + "\" is not defined";
assertTrue("Unexpected error when running compiled canvas examples with rhino.\n" +
"Expected: " + expectedErrorMessage + "\n" +
"Actual: " + e.getMessage(),
+6 -6
View File
@@ -1,9 +1,9 @@
var Object = createTestObject("Object", 23);
extend(Object, {
Object: extend(createTestObject("Object.Object", 123), { AnotherClass : createTestClass("Object.Object.Class", 42, 142) }),
Class: createTestClass("Object.Class", 42, 142),
Trait : createTestObject("Object.Trait", 324),
a: createTestObject("Object.a", 34)
var MyObject = createTestObject("MyObject", 23);
extend(MyObject, {
Object: extend(createTestObject("MyObject.Object", 123), { AnotherClass : createTestClass("MyObject.Object.Class", 42, 142) }),
Class: createTestClass("MyObject.Class", 42, 142),
Trait : createTestObject("MyObject.Trait", 324),
a: createTestObject("MyObject.a", 34)
});
var SomeClass = function () {};
+21 -21
View File
@@ -3,29 +3,29 @@ package foo
fun box(): String {
// in object
assertEquals("Object.Object.a", Object.Object.a)
assertEquals("Object.Object.b", Object.Object.b)
assertEquals(123, Object.Object.test())
assertEquals("MyObject.Object.a", MyObject.Object.a)
assertEquals("MyObject.Object.b", MyObject.Object.b)
assertEquals(123, MyObject.Object.test())
assertEquals("Object.Object.Class().a", Object.Object.Class("Object.Object.Class().a").a)
assertEquals("Object.Object.Class().b", Object.Object.Class("something").b)
assertEquals(42, Object.Object.Class("something").test())
assertEquals("Object.Object.Class.a", Object.Object.Class.a)
assertEquals("Object.Object.Class.b", Object.Object.Class.b)
assertEquals(142, Object.Object.Class.test())
assertEquals("MyObject.Object.Class().a", MyObject.Object.Class("MyObject.Object.Class().a").a)
assertEquals("MyObject.Object.Class().b", MyObject.Object.Class("something").b)
assertEquals(42, MyObject.Object.Class("something").test())
assertEquals("MyObject.Object.Class.a", MyObject.Object.Class.a)
assertEquals("MyObject.Object.Class.b", MyObject.Object.Class.b)
assertEquals(142, MyObject.Object.Class.test())
assertEquals("Object.Class().a", Object.Class("Object.Class().a").a)
assertEquals("Object.Class().b", Object.Class("something").b)
assertEquals(42, Object.Class("something").test())
assertEquals("Object.Class.a", Object.Class.a)
assertEquals("Object.Class.b", Object.Class.b)
assertEquals(142, Object.Class.test())
assertEquals("MyObject.Class().a", MyObject.Class("MyObject.Class().a").a)
assertEquals("MyObject.Class().b", MyObject.Class("something").b)
assertEquals(42, MyObject.Class("something").test())
assertEquals("MyObject.Class.a", MyObject.Class.a)
assertEquals("MyObject.Class.b", MyObject.Class.b)
assertEquals(142, MyObject.Class.test())
assertEquals("Object.a.a", Object.a.a)
assertEquals("Object.a.b", Object.a.b)
assertEquals(34, Object.a.test())
assertEquals("Object.b", Object.b)
assertEquals(23, Object.test())
assertEquals("MyObject.a.a", MyObject.a.a)
assertEquals("MyObject.a.b", MyObject.a.b)
assertEquals(34, MyObject.a.test())
assertEquals("MyObject.b", MyObject.b)
assertEquals(23, MyObject.test())
// in class
@@ -49,7 +49,7 @@ fun box(): String {
return "OK";
}
external object Object {
external object MyObject {
object Object {
val a: String = definedExternally
var b: String = definedExternally
@@ -37,16 +37,4 @@
});
}
}
// Patch apply to work with TypedArrays if needed.
try {
(function() {}).apply(null, new Int32Array(0))
} catch (e) {
var apply = Function.prototype.apply;
Object.defineProperty(Function.prototype, 'apply', {
value: function(self, array) {
return apply.call(this, self, [].slice.call(array));
}
});
}
})();
@@ -8,5 +8,3 @@ Take one down, pass it around, no more bottles of beer on the wall.
No more bottles of beer on the wall, no more bottles of beer.
Go to the store and buy some more, 2 bottles of beer on the wall.
+37 -36
View File
@@ -1,37 +1,38 @@
<html>
<head>
<title>
XML encoding with Kotlin
</title>
</head>
<body>
<h1>
XML encoding with Kotlin
</h1>
<p>
this format can be used as an alternative markup to XML
</p>
<a href="http://jetbrains.com/kotlin">
Kotlin
</a>
<p>
This is some
<b>
mixed
</b>
text. For more see the
<a href="http://jetbrains.com/kotlin">
Kotlin
</a>
project
</p>
<p>
some text
</p>
<p>
Command line arguments were:
<ul>
</ul>
</p>
</body>
</html>
<head>
<title>
XML encoding with Kotlin
</title>
</head>
<body>
<h1>
XML encoding with Kotlin
</h1>
<p>
this format can be used as an alternative markup to XML
</p>
<a href="http://jetbrains.com/kotlin">
Kotlin
</a>
<p>
This is some
<b>
mixed
</b>
text. For more see the
<a href="http://jetbrains.com/kotlin">
Kotlin
</a>
project
</p>
<p>
some text
</p>
<p>
Command line arguments were:
<ul>
</ul>
</p>
</body>
</html>
+39 -38
View File
@@ -1,40 +1,41 @@
<html>
<head>
<title>
XML encoding with Kotlin
</title>
</head>
<body>
<h1>
XML encoding with Kotlin
</h1>
<p>
this format can be used as an alternative markup to XML
</p>
<a href="http://jetbrains.com/kotlin">
Kotlin
</a>
<p>
This is some
<b>
mixed
</b>
text. For more see the
<a href="http://jetbrains.com/kotlin">
Kotlin
</a>
project
</p>
<p>
some text
</p>
<p>
Command line arguments were:
<ul>
<li>
over9000
</li>
</ul>
</p>
</body>
<head>
<title>
XML encoding with Kotlin
</title>
</head>
<body>
<h1>
XML encoding with Kotlin
</h1>
<p>
this format can be used as an alternative markup to XML
</p>
<a href="http://jetbrains.com/kotlin">
Kotlin
</a>
<p>
This is some
<b>
mixed
</b>
text. For more see the
<a href="http://jetbrains.com/kotlin">
Kotlin
</a>
project
</p>
<p>
some text
</p>
<p>
Command line arguments were:
<ul>
<li>
over9000
</li>
</ul>
</p>
</body>
</html>
+288 -287
View File
@@ -1,323 +1,324 @@
Step: 1
***
Step: 2
*
*
Step: 3
Step: 1
*
***
*
*
***
*
Step: 2
***
* *
***
***
* *
***
Step: 3
*
* *
* *
* *
*
*
* *
* *
* *
*
Step: 4
*
***
** **
***
*
*
***
** **
***
*
Step: 5
***
* *
* *
* *
***
***
* *
* *
* *
***
Step: 6
***
* * *
*** **
* * *
***
***
* * *
*** **
* * *
***
Step: 7
***
* *
* *
* *
***
***
* *
* *
* *
***
Step: 8
**
* * *
*** **
* * *
**
**
* * *
*** **
* * *
**
Step: 9
***
* * *
* * *
* * *
***
***
* * *
* * *
* * *
***
Step: 10
***
* *
** * *
* *
***
***
* *
** * *
* *
***
Step: 1
*
* *
*
*
* *
*
Step: 2
*
* *
*
*
* *
*
Step: 3
*
* *
*
*
* *
*
Step: 1
**
**
**
**
**
**
Step: 2
**
* *
**
**
* *
**
Step: 3
**
* *
**
**
* *
**
Step: 1
**
**
**
**
**
**
**
**
Step: 2
**
*
*
**
**
*
*
**
Step: 3
**
**
**
**
**
**
**
**
Step: 4
**
*
*
**
**
*
*
**
Step: 5
**
**
**
**
**
**
**
**
Step: 6
**
*
*
**
**
*
*
**
Step: 1
*** ***
* * * *
* * * *
* * * *
*** ***
*** ***
* * * *
* * * *
* * * *
*** ***
*** ***
* * * *
* * * *
* * * *
*** ***
*** ***
* * * *
* * * *
* * * *
*** ***
Step: 2
* *
* *
** **
*** ** ** ***
* * * * * *
** **
** **
* * * * * *
*** ** ** ***
** **
* *
* *
* *
* *
** **
*** ** ** ***
* * * * * *
** **
** **
* * * * * *
*** ** ** ***
** **
* *
* *
Step: 3
** **
** **
* * * * * *
*** ** ** ***
* * * * * *
*** ***
*** ***
* * * * * *
*** ** ** ***
* * * * * *
** **
** **
** **
** **
* * * * * *
*** ** ** ***
* * * * * *
*** ***
*** ***
* * * * * *
*** ** ** ***
* * * * * *
** **
** **
Step: 4
*** ***
* * * *
* * * *
* * * *
*** ***
*** ***
* * * *
* * * *
* * * *
*** ***
*** ***
* * * *
* * * *
* * * *
*** ***
*** ***
* * * *
* * * *
* * * *
*** ***
Step: 5
* *
* *
** **
*** ** ** ***
* * * * * *
** **
** **
* * * * * *
*** ** ** ***
** **
* *
* *
* *
* *
** **
*** ** ** ***
* * * * * *
** **
** **
* * * * * *
*** ** ** ***
** **
* *
* *
Step: 6
** **
** **
* * * * * *
*** ** ** ***
* * * * * *
*** ***
*** ***
* * * * * *
*** ** ** ***
* * * * * *
** **
** **
** **
** **
* * * * * *
*** ** ** ***
* * * * * *
*** ***
*** ***
* * * * * *
*** ** ** ***
* * * * * *
** **
** **
Step: 7
*** ***
* * * *
* * * *
* * * *
*** ***
*** ***
* * * *
* * * *
* * * *
*** ***
*** ***
* * * *
* * * *
* * * *
*** ***
*** ***
* * * *
* * * *
* * * *
*** ***
Step: 8
* *
* *
** **
*** ** ** ***
* * * * * *
** **
** **
* * * * * *
*** ** ** ***
** **
* *
* *
* *
* *
** **
*** ** ** ***
* * * * * *
** **
** **
* * * * * *
*** ** ** ***
** **
* *
* *
Step: 9
** **
** **
* * * * * *
*** ** ** ***
* * * * * *
*** ***
*** ***
* * * * * *
*** ** ** ***
* * * * * *
** **
** **
** **
** **
* * * * * *
*** ** ** ***
* * * * * *
*** ***
*** ***
* * * * * *
*** ** ** ***
* * * * * *
** **
** **
Step: 10
*** ***
* * * *
* * * *
* * * *
*** ***
*** ***
* * * *
* * * *
* * * *
*** ***
*** ***
* * * *
* * * *
* * * *
*** ***
*** ***
* * * *
* * * *
* * * *
*** ***