KJS: switch to using Nashorn instead of Rhino for JS backend tests
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
+4
-3
@@ -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)
|
||||
|
||||
+4
-3
@@ -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
@@ -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
@@ -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
|
||||
|
||||
Vendored
-12
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
|
||||
*** ***
|
||||
|
||||
* * * *
|
||||
* * * *
|
||||
* * * *
|
||||
*** ***
|
||||
|
||||
*** ***
|
||||
* * * *
|
||||
* * * *
|
||||
* * * *
|
||||
|
||||
*** ***
|
||||
|
||||
|
||||
|
||||
*** ***
|
||||
|
||||
* * * *
|
||||
* * * *
|
||||
* * * *
|
||||
*** ***
|
||||
|
||||
*** ***
|
||||
* * * *
|
||||
* * * *
|
||||
* * * *
|
||||
|
||||
*** ***
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user