From d4d300d0e9206fb8b9e97ddbb6a7e22a20c55f2f Mon Sep 17 00:00:00 2001 From: develar Date: Mon, 4 Jun 2012 18:12:38 +0400 Subject: [PATCH] Requested only one commit pull request (was: https://github.com/JetBrains/kotlin/pull/59/files). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Note: all tests passed, but I haven't tested this build in real life (opposite to my master branch). Don't remember about critical issue — http://youtrack.jetbrains.com/issue/KT-2154 Fix for this issue is not included in this patch (because unrelated). Fix for it and for all other unrelated changes will be opened as separated pull-requests. --- .../org/jetbrains/k2js/test/BasicTest.java | 35 +- .../test/MultipleFilesTranslationTest.java | 3 +- .../k2js/test/SingleFileTranslationTest.java | 5 +- .../rhino/RhinoFunctionResultChecker.java | 3 +- .../jetbrains/k2js/test/rhino/RhinoUtils.java | 12 +- .../k2js/test/semantics/ExamplesTest.java | 5 +- .../test/semantics/ExtensionPropertyTest.java | 8 +- .../k2js/test/semantics/KotlinLibTest.java | 5 +- .../k2js/test/semantics/MiscTest.java | 14 +- .../test/semantics/NativeInteropTest.java | 4 +- .../semantics/OperatorOverloadingTest.java | 4 +- .../test/semantics/PropertyAccessTest.java | 13 +- .../k2js/test/semantics/RangeTest.java | 6 +- .../test/semantics/StandardClassesTest.java | 8 +- .../k2js/test/semantics/StdLibTest.java | 5 +- .../semantics/WebDemoCanvasExamplesTest.java | 1 + .../test/semantics/WebDemoExamples2Test.java | 8 +- .../k2js/test/utils/JsTestUtils.java | 1 - .../k2js/test/utils/TranslationUtils.java | 1 - .../k2js/translate/context/Namer.java | 49 +- .../k2js/translate/context/StaticContext.java | 18 +- .../ClassDeclarationTranslator.java | 2 +- .../declaration/ClassTranslator.java | 72 ++- .../declaration/DeclarationBodyVisitor.java | 16 +- .../NamespaceDeclarationTranslator.java | 19 +- .../declaration/NamespaceTranslator.java | 26 +- .../declaration/PropertyTranslator.java | 33 +- .../expression/FunctionTranslator.java | 6 + .../expression/PatternTranslator.java | 19 +- .../foreach/IteratorForTranslator.java | 28 +- .../k2js/translate/general/Translation.java | 18 +- .../ClassInitializerTranslator.java | 52 +- .../initializer/Ecma3InitializerVisitor.java | 37 -- .../initializer/Ecma5InitializerVisitor.java | 54 -- .../initializer/InitializerUtils.java | 18 +- .../initializer/InitializerVisitor.java | 31 +- .../NamespaceInitializerTranslator.java | 7 +- .../primitive/PrimitiveRangeToIntrinsic.java | 10 +- .../translate/reference/CallTranslator.java | 15 +- .../reference/ReferenceTranslator.java | 23 +- .../k2js/translate/utils/JsAstUtils.java | 59 +- .../translate/utils/JsDescriptorUtils.java | 10 + .../translate/utils/TranslationUtils.java | 18 + .../cases/propertyWithGetterAndSetter.kt | 3 + .../testFiles/kotlinLib/cases/hashMap.js | 4 +- .../kotlinLib/cases/isAncestorType.js | 6 +- .../kotlinLib/cases/isComplexTest.js | 10 +- .../kotlinLib/cases/isNotOtherType.js | 8 +- .../testFiles/kotlinLib/cases/isSameType.js | 6 +- .../testFiles/kotlinLib/cases/namespace.js | 2 +- .../kotlinLib/cases/namespaceWithClasses.js | 8 +- .../testFiles/kotlinLib/cases/trait.js | 4 +- js/js.translator/testFiles/kotlin_lib.js | 510 ++++-------------- .../testFiles/kotlin_lib_ecma3.js | 262 +++++++++ .../testFiles/kotlin_lib_ecma5.js | 171 ++++++ .../cases/initInstanceProperties.kt | 12 + js/js.translator/testFiles/test.html | 13 + 57 files changed, 1006 insertions(+), 794 deletions(-) delete mode 100644 js/js.translator/src/org/jetbrains/k2js/translate/initializer/Ecma3InitializerVisitor.java delete mode 100644 js/js.translator/src/org/jetbrains/k2js/translate/initializer/Ecma5InitializerVisitor.java create mode 100644 js/js.translator/testFiles/kotlin_lib_ecma3.js create mode 100644 js/js.translator/testFiles/kotlin_lib_ecma5.js create mode 100644 js/js.translator/testFiles/propertyAccess/cases/initInstanceProperties.kt create mode 100644 js/js.translator/testFiles/test.html diff --git a/js/js.tests/test/org/jetbrains/k2js/test/BasicTest.java b/js/js.tests/test/org/jetbrains/k2js/test/BasicTest.java index 408014b2c3d..f31f7ccb663 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/BasicTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/BasicTest.java @@ -26,8 +26,8 @@ import org.jetbrains.k2js.test.rhino.RhinoResultChecker; import org.jetbrains.k2js.test.utils.TranslationUtils; import java.io.File; +import java.util.ArrayList; import java.util.Collections; -import java.util.EnumSet; import java.util.List; import java.util.Map; @@ -44,6 +44,8 @@ public abstract class BasicTest extends TestWithEnvironment { private static final String CASES = "cases/"; private static final String OUT = "out/"; private static final String KOTLIN_JS_LIB = pathToTestFilesRoot() + "kotlin_lib.js"; + private static final String KOTLIN_JS_LIB_ECMA_3 = pathToTestFilesRoot() + "kotlin_lib_ecma3.js"; + private static final String KOTLIN_JS_LIB_ECMA_5 = pathToTestFilesRoot() + "kotlin_lib_ecma5.js"; private static final String EXPECTED = "expected/"; @NotNull @@ -87,28 +89,32 @@ public abstract class BasicTest extends TestWithEnvironment { assert success; } - protected List additionalJSFiles() { - return Collections.singletonList(KOTLIN_JS_LIB); + protected List additionalJSFiles(EcmaVersion ecmaVersion) { + List list = new ArrayList(2); + list.add(ecmaVersion == EcmaVersion.v5 ? KOTLIN_JS_LIB_ECMA_5 : KOTLIN_JS_LIB_ECMA_3); + list.add(KOTLIN_JS_LIB); + return list; } protected void generateJavaScriptFiles(@NotNull String kotlinFilename, @NotNull MainCallParameters mainCallParameters, - @NotNull EnumSet ecmaVersions) throws Exception { + @NotNull Iterable ecmaVersions) throws Exception { generateJavaScriptFiles(Collections.singletonList(getInputFilePath(kotlinFilename)), kotlinFilename, mainCallParameters, ecmaVersions); } protected void generateJavaScriptFiles(@NotNull List files, @NotNull String testName, - @NotNull MainCallParameters mainCallParameters, @NotNull EnumSet ecmaVersions) + @NotNull MainCallParameters mainCallParameters, @NotNull Iterable ecmaVersions) throws Exception { for (EcmaVersion version : ecmaVersions) { TranslationUtils.translateFiles(getProject(), files, getOutputFilePath(testName, version), mainCallParameters, version); } } - protected void runRhinoTests(@NotNull List outputFilePaths, @NotNull RhinoResultChecker checker) throws Exception { - for (String outputFilePath : outputFilePaths) { - runRhinoTest(withAdditionalFiles(outputFilePath), checker, getRhinoTestVariables()); + protected void runRhinoTests(@NotNull String filename, @NotNull Iterable ecmaVersions, @NotNull RhinoResultChecker checker) throws Exception { + for (EcmaVersion ecmaVersion : ecmaVersions) { + runRhinoTest(withAdditionalFiles(getOutputFilePath(filename, ecmaVersion), ecmaVersion), checker, getRhinoTestVariables(), + ecmaVersion); } } @@ -155,21 +161,12 @@ public abstract class BasicTest extends TestWithEnvironment { } @NotNull - protected List withAdditionalFiles(@NotNull String inputFile) { - List allFiles = Lists.newArrayList(additionalJSFiles()); + protected List withAdditionalFiles(@NotNull String inputFile, EcmaVersion ecmaVersion) { + List allFiles = Lists.newArrayList(additionalJSFiles(ecmaVersion)); allFiles.add(inputFile); return allFiles; } - @NotNull - protected List getOutputFilePaths(@NotNull String filename, @NotNull EnumSet ecmaVersions) { - List result = Lists.newArrayList(); - for (EcmaVersion ecmaVersion : ecmaVersions) { - result.add(getOutputFilePath(filename, ecmaVersion)); - } - return result; - } - @NotNull protected String getOutputFilePath(@NotNull String filename, @NotNull EcmaVersion ecmaVersion) { return getOutputPath() + convertFileNameToDotJsFile(filename, ecmaVersion); diff --git a/js/js.tests/test/org/jetbrains/k2js/test/MultipleFilesTranslationTest.java b/js/js.tests/test/org/jetbrains/k2js/test/MultipleFilesTranslationTest.java index 81c8b7225e8..5287f640950 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/MultipleFilesTranslationTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/MultipleFilesTranslationTest.java @@ -51,8 +51,7 @@ public abstract class MultipleFilesTranslationTest extends BasicTest { @NotNull Object expectedResult) throws Exception { generateJsFromDir(dirName, ecmaVersions); - runRhinoTests(getOutputFilePaths(dirName + ".kt", ecmaVersions), - new RhinoFunctionResultChecker(namespaceName, functionName, expectedResult)); + runRhinoTests(dirName + ".kt", ecmaVersions, new RhinoFunctionResultChecker(namespaceName, functionName, expectedResult)); } public void checkFooBoxIsTrue(@NotNull String dirName) throws Exception { diff --git a/js/js.tests/test/org/jetbrains/k2js/test/SingleFileTranslationTest.java b/js/js.tests/test/org/jetbrains/k2js/test/SingleFileTranslationTest.java index da0572c0ec3..24654b139b5 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/SingleFileTranslationTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/SingleFileTranslationTest.java @@ -47,8 +47,7 @@ public abstract class SingleFileTranslationTest extends BasicTest { @NotNull String functionName, @NotNull Object expectedResult) throws Exception { generateJavaScriptFiles(kotlinFilename, MainCallParameters.noCall(), ecmaVersions); - runRhinoTests(getOutputFilePaths(kotlinFilename, ecmaVersions), - new RhinoFunctionResultChecker(namespaceName, functionName, expectedResult)); + runRhinoTests(kotlinFilename, ecmaVersions, new RhinoFunctionResultChecker(namespaceName, functionName, expectedResult)); } public void checkFooBoxIsTrue(@NotNull String filename, @NotNull EnumSet ecmaVersions) throws Exception { @@ -82,7 +81,7 @@ public abstract class SingleFileTranslationTest extends BasicTest { @NotNull EnumSet ecmaVersions, String... args) throws Exception { generateJavaScriptFiles(kotlinFilename, MainCallParameters.mainWithArguments(Lists.newArrayList(args)), ecmaVersions); - runRhinoTests(getOutputFilePaths(kotlinFilename, ecmaVersions), new RhinoSystemOutputChecker(expectedResult)); + runRhinoTests(kotlinFilename, ecmaVersions, new RhinoSystemOutputChecker(expectedResult)); } protected void performTestWithMain(@NotNull EnumSet ecmaVersions, diff --git a/js/js.tests/test/org/jetbrains/k2js/test/rhino/RhinoFunctionResultChecker.java b/js/js.tests/test/org/jetbrains/k2js/test/rhino/RhinoFunctionResultChecker.java index d2f04c07e88..396ff1dba12 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/rhino/RhinoFunctionResultChecker.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/rhino/RhinoFunctionResultChecker.java @@ -21,7 +21,6 @@ import org.mozilla.javascript.Context; import org.mozilla.javascript.Scriptable; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; /** * @author Pavel Talanov @@ -61,7 +60,7 @@ public class RhinoFunctionResultChecker implements RhinoResultChecker { private String functionCallString() { String result = functionName + "()"; if (namespaceName != null) { - result = namespaceName + "." + result; + result = "Kotlin.defs." + namespaceName + "." + result; } return result; } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/rhino/RhinoUtils.java b/js/js.tests/test/org/jetbrains/k2js/test/rhino/RhinoUtils.java index 330ac850ff3..1d8d2ff982b 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/rhino/RhinoUtils.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/rhino/RhinoUtils.java @@ -17,6 +17,8 @@ package org.jetbrains.k2js.test.rhino; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.k2js.config.EcmaVersion; import org.mozilla.javascript.Context; import org.mozilla.javascript.Scriptable; @@ -48,13 +50,19 @@ public final class RhinoUtils { public static void runRhinoTest(@NotNull List fileNames, @NotNull RhinoResultChecker checker) throws Exception { - runRhinoTest(fileNames, checker, null); + runRhinoTest(fileNames, checker, null, EcmaVersion.defaultVersion()); } public static void runRhinoTest(@NotNull List fileNames, @NotNull RhinoResultChecker checker, - Map variables) throws Exception { + @Nullable Map variables, + @NotNull EcmaVersion ecmaVersion) throws Exception { 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); + } + Scriptable scope = context.initStandardObjects(); if (variables != null) { Set> entries = variables.entrySet(); diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/ExamplesTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/ExamplesTest.java index de4d049dd61..c6b7a88552d 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/ExamplesTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/ExamplesTest.java @@ -18,12 +18,11 @@ package org.jetbrains.k2js.test.semantics; import junit.framework.Test; import org.jetbrains.annotations.NotNull; +import org.jetbrains.k2js.config.EcmaVersion; import org.jetbrains.k2js.test.BasicTest; import org.jetbrains.k2js.test.SingleFileTranslationTest; import org.jetbrains.k2js.translate.context.Namer; -import static org.jetbrains.k2js.test.utils.JsTestUtils.failsOnEcmaV5; - @SuppressWarnings("JUnitTestCaseWithNoTests") public final class ExamplesTest extends SingleFileTranslationTest { @@ -38,7 +37,7 @@ public final class ExamplesTest extends SingleFileTranslationTest { @Override public void runTest() throws Exception { - runFunctionOutputTest(failsOnEcmaV5(), filename, Namer.getRootNamespaceName(), "box", "OK"); + runFunctionOutputTest(EcmaVersion.all(), filename, Namer.getRootNamespaceName(), "box", "OK"); } public static Test suite() throws Exception { diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/ExtensionPropertyTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/ExtensionPropertyTest.java index eb8ebb19e16..29588d3eea5 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/ExtensionPropertyTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/ExtensionPropertyTest.java @@ -18,8 +18,6 @@ package org.jetbrains.k2js.test.semantics; import org.jetbrains.k2js.test.SingleFileTranslationTest; -import static org.jetbrains.k2js.test.utils.JsTestUtils.failsOnEcmaV5; - /** * @author Pavel Talanov */ @@ -30,14 +28,14 @@ public final class ExtensionPropertyTest extends SingleFileTranslationTest { } public void testSimplePropertyWithGetter() throws Exception { - fooBoxTest(failsOnEcmaV5()); + fooBoxTest(); } public void testPropertyWithGetterAndSetter() throws Exception { - fooBoxTest(failsOnEcmaV5()); + fooBoxTest(); } public void testAbsExtension() throws Exception { - fooBoxTest(failsOnEcmaV5()); + fooBoxTest(); } } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/KotlinLibTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/KotlinLibTest.java index 6bef0e27707..03e895b5f10 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/KotlinLibTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/KotlinLibTest.java @@ -17,6 +17,7 @@ package org.jetbrains.k2js.test.semantics; import org.jetbrains.annotations.NotNull; +import org.jetbrains.k2js.config.EcmaVersion; import org.jetbrains.k2js.test.SingleFileTranslationTest; import org.jetbrains.k2js.test.rhino.RhinoFunctionResultChecker; import org.jetbrains.k2js.test.rhino.RhinoResultChecker; @@ -35,7 +36,7 @@ public final class KotlinLibTest extends SingleFileTranslationTest { } public void testKotlinJsLibRunsWithRhino() throws Exception { - runRhinoTest(additionalJSFiles(), new RhinoResultChecker() { + runRhinoTest(additionalJSFiles(EcmaVersion.v3), new RhinoResultChecker() { @Override public void runChecks(Context context, Scriptable scope) throws Exception { //do nothing @@ -83,7 +84,7 @@ public final class KotlinLibTest extends SingleFileTranslationTest { private void runJavascriptTest(@NotNull String filename) throws Exception { - runRhinoTest(withAdditionalFiles(cases(filename)), + runRhinoTest(withAdditionalFiles(cases(filename), EcmaVersion.v3), new RhinoFunctionResultChecker("test", true)); } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/MiscTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/MiscTest.java index 04c8335fc9f..9828978cd3a 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/MiscTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/MiscTest.java @@ -20,8 +20,6 @@ import org.jetbrains.k2js.config.EcmaVersion; import org.jetbrains.k2js.translate.context.Namer; import org.mozilla.javascript.JavaScriptException; -import static org.jetbrains.k2js.test.utils.JsTestUtils.failsOnEcmaV5; - /** * @author Pavel Talanov *

@@ -38,7 +36,7 @@ public final class MiscTest extends AbstractExpressionTest { } public void testIntRange() throws Exception { - fooBoxTest(failsOnEcmaV5()); + fooBoxTest(); } @@ -47,7 +45,7 @@ public final class MiscTest extends AbstractExpressionTest { } public void testClassWithoutNamespace() throws Exception { - runFunctionOutputTest(failsOnEcmaV5(), "classWithoutNamespace.kt", Namer.getRootNamespaceName(), "box", true); + runFunctionOutputTest("classWithoutNamespace.kt", Namer.getRootNamespaceName(), "box", true); } public void testIfElseAsExpressionWithThrow() throws Exception { @@ -73,7 +71,7 @@ public final class MiscTest extends AbstractExpressionTest { } public void testKt740_2() throws Exception { - checkFooBoxIsOk(failsOnEcmaV5(), "KT-740-2.kt"); + checkFooBoxIsOk("KT-740-2.kt"); } public void testKt1361_1() throws Exception { @@ -89,7 +87,7 @@ public final class MiscTest extends AbstractExpressionTest { } public void testKt740_3() throws Exception { - checkFooBoxIsOk(failsOnEcmaV5(), "KT-740-3.kt"); + checkFooBoxIsOk("KT-740-3.kt"); } public void testFunInConstructor() throws Exception { @@ -109,11 +107,11 @@ public final class MiscTest extends AbstractExpressionTest { } public void testExtensionLiteralCreatedAtNamespaceLevel() throws Exception { - fooBoxTest(failsOnEcmaV5()); + fooBoxTest(); } public void testTemporaryVariableCreatedInNamespaceInitializer() throws Exception { - fooBoxTest(failsOnEcmaV5()); + fooBoxTest(); } public void testWhenReturnedWithoutBlock() throws Exception { diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/NativeInteropTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/NativeInteropTest.java index 874b23b206a..d3b5e839078 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/NativeInteropTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/NativeInteropTest.java @@ -37,8 +37,8 @@ public final class NativeInteropTest extends SingleFileTranslationTest { } @Override - protected List additionalJSFiles() { - List result = Lists.newArrayList(super.additionalJSFiles()); + protected List additionalJSFiles(EcmaVersion ecmaVersion) { + List result = Lists.newArrayList(super.additionalJSFiles(ecmaVersion)); result.addAll(JsTestUtils.getAllFilesInDir(pathToTestFiles() + NATIVE)); return result; } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/OperatorOverloadingTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/OperatorOverloadingTest.java index d23b2b51044..9b2a0c962b0 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/OperatorOverloadingTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/OperatorOverloadingTest.java @@ -18,8 +18,6 @@ package org.jetbrains.k2js.test.semantics; import org.jetbrains.k2js.test.SingleFileTranslationTest; -import static org.jetbrains.k2js.test.utils.JsTestUtils.failsOnEcmaV5; - /** * @author Pavel Talanov */ @@ -60,7 +58,7 @@ public final class OperatorOverloadingTest extends SingleFileTranslationTest { public void testOperatorOverloadOnPropertyCallGetterAndSetterOnlyOnce() throws Exception { - fooBoxTest(failsOnEcmaV5()); + fooBoxTest(); } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/PropertyAccessTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/PropertyAccessTest.java index 388a70c7a83..1e01ecba839 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/PropertyAccessTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/PropertyAccessTest.java @@ -16,9 +16,10 @@ package org.jetbrains.k2js.test.semantics; +import org.jetbrains.k2js.config.EcmaVersion; import org.jetbrains.k2js.test.SingleFileTranslationTest; -import static org.jetbrains.k2js.test.utils.JsTestUtils.failsOnEcmaV5; +import java.util.EnumSet; /** * @author Pavel Talanov @@ -45,12 +46,12 @@ public final class PropertyAccessTest extends SingleFileTranslationTest { public void testCustomGetter() throws Exception { - fooBoxTest(failsOnEcmaV5()); + fooBoxTest(); } public void testCustomSetter() throws Exception { - fooBoxTest(failsOnEcmaV5()); + fooBoxTest(); } public void testNamespacePropertyInitializer() throws Exception { @@ -63,7 +64,7 @@ public final class PropertyAccessTest extends SingleFileTranslationTest { } public void testNamespaceCustomAccessors() throws Exception { - fooBoxTest(failsOnEcmaV5()); + fooBoxTest(); } @@ -74,4 +75,8 @@ public final class PropertyAccessTest extends SingleFileTranslationTest { public void testExtensionLiteralSafeCall() throws Exception { fooBoxTest(); } + + public void testInitInstanceProperties() throws Exception { + fooBoxTest(EnumSet.of(EcmaVersion.v5)); + } } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/RangeTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/RangeTest.java index 23bbd0a6938..10a497e40a9 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/RangeTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/RangeTest.java @@ -18,8 +18,6 @@ package org.jetbrains.k2js.test.semantics; import org.jetbrains.k2js.test.SingleFileTranslationTest; -import static org.jetbrains.k2js.test.utils.JsTestUtils.failsOnEcmaV5; - /** * @author Pavel Talanov */ @@ -30,12 +28,12 @@ public final class RangeTest extends SingleFileTranslationTest { } public void testExplicitRange() throws Exception { - fooBoxTest(failsOnEcmaV5()); + fooBoxTest(); } public void testRangeSugarSyntax() throws Exception { - fooBoxTest(failsOnEcmaV5()); + fooBoxTest(); } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/StandardClassesTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/StandardClassesTest.java index 0bf924d4c6f..73926759e25 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/StandardClassesTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/StandardClassesTest.java @@ -18,8 +18,6 @@ package org.jetbrains.k2js.test.semantics; import org.jetbrains.k2js.test.SingleFileTranslationTest; -import static org.jetbrains.k2js.test.utils.JsTestUtils.failsOnEcmaV5; - /** * @author Pavel Talanov */ @@ -45,7 +43,7 @@ public final class StandardClassesTest extends SingleFileTranslationTest { public void testArrayFunctionConstructor() throws Exception { - fooBoxTest(failsOnEcmaV5()); + fooBoxTest(); } @@ -62,6 +60,6 @@ public final class StandardClassesTest extends SingleFileTranslationTest { public void testArraysIterator() throws Exception { - fooBoxTest(failsOnEcmaV5()); + fooBoxTest(); } -} +} \ No newline at end of file diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/StdLibTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/StdLibTest.java index 26766d30e0d..84de810aede 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/StdLibTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/StdLibTest.java @@ -21,7 +21,6 @@ import org.jetbrains.k2js.config.EcmaVersion; import org.jetbrains.k2js.facade.MainCallParameters; import org.jetbrains.k2js.test.SingleFileTranslationTest; import org.jetbrains.k2js.test.rhino.RhinoFunctionNativeObjectResultChecker; -import org.jetbrains.k2js.test.rhino.RhinoFunctionResultChecker; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -44,11 +43,11 @@ public final class StdLibTest extends SingleFileTranslationTest { @Override protected void generateJavaScriptFiles(@NotNull String kotlinFilename, @NotNull MainCallParameters mainCallParameters, - @NotNull EnumSet ecmaVersions) throws Exception { + @NotNull Iterable ecmaVersions) throws Exception { List files = Arrays.asList(getInputFilePath(kotlinFilename)); generateJavaScriptFiles(files, kotlinFilename, mainCallParameters, ecmaVersions); - runRhinoTests(getOutputFilePaths(kotlinFilename, ecmaVersions), + runRhinoTests(kotlinFilename, ecmaVersions, new RhinoFunctionNativeObjectResultChecker("test.browser", "foo", "Some Dynamically Created Content!!!")); } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/WebDemoCanvasExamplesTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/WebDemoCanvasExamplesTest.java index 89e34bc1ade..cac14f33e4d 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/WebDemoCanvasExamplesTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/WebDemoCanvasExamplesTest.java @@ -17,6 +17,7 @@ package org.jetbrains.k2js.test.semantics; import org.jetbrains.annotations.NotNull; +import org.jetbrains.k2js.config.EcmaVersion; import org.jetbrains.k2js.test.SingleFileTranslationTest; import org.mozilla.javascript.EcmaError; diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/WebDemoExamples2Test.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/WebDemoExamples2Test.java index 739b5e1dc8a..28afb839d55 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/WebDemoExamples2Test.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/WebDemoExamples2Test.java @@ -18,8 +18,6 @@ package org.jetbrains.k2js.test.semantics; import org.jetbrains.k2js.test.SingleFileTranslationTest; -import static org.jetbrains.k2js.test.utils.JsTestUtils.failsOnEcmaV5; - /** * @author Pavel Talanov */ @@ -35,11 +33,11 @@ public final class WebDemoExamples2Test extends SingleFileTranslationTest { } public void testLife() throws Exception { - performTestWithMain(failsOnEcmaV5(), "life", "", "2"); + performTestWithMain("life", "", "2"); } public void testBuilder() throws Exception { - performTestWithMain(failsOnEcmaV5(), "builder", ""); - performTestWithMain(failsOnEcmaV5(), "builder", "1", "over9000"); + performTestWithMain("builder", ""); + performTestWithMain("builder", "1", "over9000"); } } diff --git a/js/js.tests/test/org/jetbrains/k2js/test/utils/JsTestUtils.java b/js/js.tests/test/org/jetbrains/k2js/test/utils/JsTestUtils.java index 2229ea0eb3e..b0d5ec2a053 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/utils/JsTestUtils.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/utils/JsTestUtils.java @@ -50,7 +50,6 @@ public final class JsTestUtils { return failsOn(EcmaVersion.v5); } - @NotNull public static String convertFileNameToDotJsFile(@NotNull String filename, EcmaVersion ecmaVersion) { String postFix = "_" + ecmaVersion.toString() + ".js"; diff --git a/js/js.tests/test/org/jetbrains/k2js/test/utils/TranslationUtils.java b/js/js.tests/test/org/jetbrains/k2js/test/utils/TranslationUtils.java index 76c88714074..44c5a3f669d 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/utils/TranslationUtils.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/utils/TranslationUtils.java @@ -57,7 +57,6 @@ public final class TranslationUtils { JsProgram program = getTranslator(project, version).generateProgram(psiFiles, mainCallParameters); FileWriter writer = new FileWriter(new File(outputFile)); try { - writer.write("\"use strict\";\n"); writer.write(CodeGenerator.toString(program)); } finally { diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/context/Namer.java b/js/js.translator/src/org/jetbrains/k2js/translate/context/Namer.java index 3d792f17527..52da0995874 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/context/Namer.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/context/Namer.java @@ -30,10 +30,10 @@ import static org.jetbrains.k2js.translate.utils.JsAstUtils.setQualifier; public final class Namer { private static final String INITIALIZE_METHOD_NAME = "initialize"; - private static final String CLASS_OBJECT_NAME = "Class"; - private static final String TRAIT_OBJECT_NAME = "Trait"; - private static final String NAMESPACE_OBJECT_NAME = "Namespace"; - private static final String OBJECT_OBJECT_NAME = "object"; + private static final String CLASS_OBJECT_NAME = "createClass"; + private static final String TRAIT_OBJECT_NAME = "createTrait"; + private static final String NAMESPACE_OBJECT_NAME = "createNamespace"; + private static final String OBJECT_OBJECT_NAME = "createObject"; private static final String SETTER_PREFIX = "set_"; private static final String GETTER_PREFIX = "get_"; private static final String BACKING_FIELD_PREFIX = "$"; @@ -70,7 +70,11 @@ public final class Namer { } @NotNull - public static String getNameForAccessor(@NotNull String propertyName, boolean isGetter) { + public static String getNameForAccessor(@NotNull String propertyName, boolean isGetter, boolean useNativeAccessor) { + if (useNativeAccessor) { + return propertyName; + } + if (isGetter) { return getNameForGetter(propertyName); } @@ -112,6 +116,12 @@ public final class Namer { @NotNull private final JsName objectName; + @NotNull + private final JsName isTypeName; + + @NotNull + private final JsPropertyInitializer writablePropertyDescriptorField; + private Namer(@NotNull JsScope rootScope) { kotlinName = rootScope.declareName(KOTLIN_OBJECT_NAME); kotlinScope = new JsScope(rootScope, "Kotlin standard object"); @@ -119,26 +129,30 @@ public final class Namer { namespaceName = kotlinScope.declareName(NAMESPACE_OBJECT_NAME); className = kotlinScope.declareName(CLASS_OBJECT_NAME); objectName = kotlinScope.declareName(OBJECT_OBJECT_NAME); + + isTypeName = kotlinScope.declareName("isType"); + + writablePropertyDescriptorField = new JsPropertyInitializer(new JsNameRef("writable"), rootScope.getProgram().getTrueLiteral()); } @NotNull public JsExpression classCreationMethodReference() { - return kotlin(createMethodReference(className)); + return kotlin(className); } @NotNull public JsExpression traitCreationMethodReference() { - return kotlin(createMethodReference(traitName)); + return kotlin(traitName); } @NotNull public JsExpression namespaceCreationMethodReference() { - return kotlin(createMethodReference(namespaceName)); + return kotlin(namespaceName); } @NotNull public JsExpression objectCreationMethodReference() { - return kotlin(createMethodReference(objectName)); + return kotlin(objectName); } @NotNull @@ -149,17 +163,15 @@ public final class Namer { } @NotNull - private static JsNameRef createMethodReference(@NotNull JsName name) { - JsNameRef qualifier = name.makeRef(); - JsNameRef reference = AstUtil.newQualifiedNameRef("create"); - setQualifier(reference, qualifier); + private JsExpression kotlin(@NotNull JsName name) { + JsNameRef reference = name.makeRef(); + reference.setQualifier(kotlinName.makeRef()); return reference; } @NotNull private JsExpression kotlin(@NotNull JsExpression reference) { - JsNameRef kotlinReference = kotlinName.makeRef(); - setQualifier(reference, kotlinReference); + setQualifier(reference, kotlinName.makeRef()); return reference; } @@ -170,7 +182,12 @@ public final class Namer { @NotNull public JsExpression isOperationReference() { - return kotlin(AstUtil.newQualifiedNameRef("isType")); + return kotlin(isTypeName); + } + + @NotNull + public JsPropertyInitializer writablePropertyDescriptorField() { + return writablePropertyDescriptorField; } @NotNull diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/context/StaticContext.java b/js/js.translator/src/org/jetbrains/k2js/translate/context/StaticContext.java index 4ac198b5539..24f94e7736b 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/context/StaticContext.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/context/StaticContext.java @@ -30,6 +30,7 @@ import org.jetbrains.k2js.translate.context.generator.Rule; import org.jetbrains.k2js.translate.intrinsic.Intrinsics; import org.jetbrains.k2js.translate.utils.AnnotationsUtils; import org.jetbrains.k2js.translate.utils.JsAstUtils; +import org.jetbrains.k2js.translate.utils.JsDescriptorUtils; import org.jetbrains.k2js.translate.utils.PredefinedAnnotation; import java.util.Map; @@ -200,10 +201,13 @@ public final class StaticContext { return null; } boolean isGetter = descriptor instanceof PropertyGetterDescriptor; - String propertyName = ((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty().getName().getName(); - String accessorName = Namer.getNameForAccessor(propertyName, isGetter); + final PropertyAccessorDescriptor accessorDescriptor = (PropertyAccessorDescriptor) descriptor; + String propertyName = accessorDescriptor.getCorrespondingProperty().getName().getName(); + String accessorName = Namer.getNameForAccessor(propertyName, isGetter, !accessorDescriptor.getReceiverParameter().exists() && isEcma5()); NamingScope enclosingScope = getEnclosingScope(descriptor); - return enclosingScope.declareObfuscatableName(accessorName); + return isEcma5() + ? enclosingScope.declareUnobfuscatableName(accessorName) + : enclosingScope.declareObfuscatableName(accessorName); } }; @@ -232,9 +236,7 @@ public final class StaticContext { NamingScope enclosingScope = getEnclosingScope(descriptor); if (isEcma5()) { String name = descriptor.getName().getName(); - PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; - if (!isDefaultAccessor(propertyDescriptor.getGetter()) || !isDefaultAccessor(propertyDescriptor.getSetter())) { - // _ is more preferable than $ should be discussed later + if (JsDescriptorUtils.isAsPrivate((PropertyDescriptor) descriptor)) { name = '_' + name; } @@ -244,10 +246,6 @@ public final class StaticContext { return enclosingScope.declareObfuscatableName(Namer.getKotlinBackingFieldName(descriptor.getName().getName())); } } - - private boolean isDefaultAccessor(PropertyAccessorDescriptor accessorDescriptor) { - return accessorDescriptor == null || accessorDescriptor.isDefault(); - } }; //TODO: hack! Rule toStringHack = new Rule() { diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassDeclarationTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassDeclarationTranslator.java index bf67a37340b..5c90678041e 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassDeclarationTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassDeclarationTranslator.java @@ -128,7 +128,7 @@ public final class ClassDeclarationTranslator extends AbstractTranslator { @NotNull private JsStatement generateDeclaration(@NotNull JetClass declaration) { JsName localClassName = generateLocalAlias(declaration); - JsInvocation classDeclarationExpression = + JsExpression classDeclarationExpression = Translation.translateClassDeclaration(declaration, localToGlobalClassName.inverse(), context()); return newVar(localClassName, classDeclarationExpression); } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassTranslator.java index c3c82da08a9..c5ab497e195 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/ClassTranslator.java @@ -30,6 +30,7 @@ import org.jetbrains.k2js.translate.context.TemporaryVariable; import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.general.AbstractTranslator; import org.jetbrains.k2js.translate.general.Translation; +import org.jetbrains.k2js.translate.initializer.InitializerUtils; import org.jetbrains.k2js.translate.utils.JsAstUtils; import java.util.ArrayList; @@ -55,21 +56,21 @@ public final class ClassTranslator extends AbstractTranslator { @NotNull public static JsPropertyInitializer translateAsProperty(@NotNull JetClassOrObject classDeclaration, @NotNull TranslationContext context) { - JsInvocation classCreationExpression = + JsExpression classCreationExpression = generateClassCreationExpression(classDeclaration, context); JsName className = context.getNameForElement(classDeclaration); return new JsPropertyInitializer(className.makeRef(), classCreationExpression); } @NotNull - public static JsInvocation generateClassCreationExpression(@NotNull JetClassOrObject classDeclaration, + public static JsExpression generateClassCreationExpression(@NotNull JetClassOrObject classDeclaration, @NotNull Map aliasingMap, @NotNull TranslationContext context) { return (new ClassTranslator(classDeclaration, aliasingMap, context)).translateClassOrObjectCreation(); } @NotNull - public static JsInvocation generateClassCreationExpression(@NotNull JetClassOrObject classDeclaration, + public static JsExpression generateClassCreationExpression(@NotNull JetClassOrObject classDeclaration, @NotNull TranslationContext context) { return (new ClassTranslator(classDeclaration, Collections.emptyMap(), context)).translateClassOrObjectCreation(); @@ -122,9 +123,11 @@ public final class ClassTranslator extends AbstractTranslator { } @NotNull - private JsInvocation translateClassOrObjectCreation() { + private JsExpression translateClassOrObjectCreation() { JsInvocation jsClassDeclaration = classCreateMethodInvocation(); - addSuperclassReferences(jsClassDeclaration); + if (!isObject()) { + addSuperclassReferences(jsClassDeclaration); + } addClassOwnDeclarations(jsClassDeclaration); return jsClassDeclaration; } @@ -134,7 +137,7 @@ public final class ClassTranslator extends AbstractTranslator { if (isObject()) { return AstUtil.newInvocation(context().namer().objectCreationMethodReference()); } - else if (isTrait()) { + else if (isTrait() && !context().isEcma5()) { return AstUtil.newInvocation(context().namer().traitCreationMethodReference()); } else { @@ -151,13 +154,47 @@ public final class ClassTranslator extends AbstractTranslator { } private void addClassOwnDeclarations(@NotNull JsInvocation jsClassDeclaration) { - JsObjectLiteral jsClassDescription = translateClassDeclarations(); - jsClassDeclaration.getArguments().add(jsClassDescription); + TranslationContext classDeclarationContext = getClassDeclarationContext(); + JsObjectLiteral properties = new JsObjectLiteral(); + List propertyList = properties.getPropertyInitializers(); + if (!isTrait()) { + JsFunction initializer = Translation.generateClassInitializerMethod(classDeclaration, classDeclarationContext); + if (context().isEcma5()) { + jsClassDeclaration.getArguments().add(isObject() ? initializer : JsAstUtils.encloseFunction(initializer)); + } + else { + propertyList.add(InitializerUtils.generateInitializeMethod(initializer)); + } + } + else if (context().isEcma5()) { + jsClassDeclaration.getArguments().add(context().program().getNullLiteral()); + } + + propertyList.addAll(translatePropertiesAsConstructorParameters(classDeclarationContext)); + propertyList.addAll(declarationBodyVisitor.traverseClass(classDeclaration, classDeclarationContext)); + + if (!propertyList.isEmpty() || !context().isEcma5()) { + jsClassDeclaration.getArguments().add(properties); + } } private void addSuperclassReferences(@NotNull JsInvocation jsClassDeclaration) { - for (JsExpression superClassReference : getSuperclassNameReferences()) { - jsClassDeclaration.getArguments().add(superClassReference); + List superClassReferences = getSuperclassNameReferences(); + List expressions = jsClassDeclaration.getArguments(); + if (context().isEcma5()) { + if (superClassReferences.isEmpty()) { + jsClassDeclaration.getArguments().add(context().program().getNullLiteral()); + return; + } + else if (superClassReferences.size() > 1) { + JsArrayLiteral arrayLiteral = new JsArrayLiteral(); + jsClassDeclaration.getArguments().add(arrayLiteral); + expressions = arrayLiteral.getExpressions(); + } + } + + for (JsExpression superClassReference : superClassReferences) { + expressions.add(superClassReference); } } @@ -206,21 +243,6 @@ public final class ClassTranslator extends AbstractTranslator { return ancestorClass; } - @NotNull - private JsObjectLiteral translateClassDeclarations() { - TranslationContext classDeclarationContext = getClassDeclarationContext(); - List propertyList = new ArrayList(); - if (!isTrait()) { - propertyList.add(Translation.generateClassInitializerMethod(classDeclaration, classDeclarationContext)); - } - // skip for ecma5, because accessors defined via Object.defineProperties - if (!context().isEcma5()) { - propertyList.addAll(translatePropertiesAsConstructorParameters(classDeclarationContext)); - } - propertyList.addAll(declarationBodyVisitor.traverseClass(classDeclaration, classDeclarationContext)); - return JsAstUtils.newObjectLiteral(propertyList); - } - @NotNull private List translatePropertiesAsConstructorParameters(@NotNull TranslationContext classDeclarationContext) { List result = new ArrayList(); diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/DeclarationBodyVisitor.java b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/DeclarationBodyVisitor.java index b662af5724a..27b177b4ae5 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/DeclarationBodyVisitor.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/DeclarationBodyVisitor.java @@ -18,6 +18,7 @@ package org.jetbrains.k2js.translate.declaration; import com.google.dart.compiler.backend.js.ast.JsPropertyInitializer; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.psi.*; @@ -25,20 +26,20 @@ import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.general.Translation; import org.jetbrains.k2js.translate.general.TranslatorVisitor; import org.jetbrains.k2js.translate.utils.BindingUtils; +import org.jetbrains.k2js.translate.utils.JsAstUtils; import java.util.ArrayList; import java.util.Collections; import java.util.List; import static org.jetbrains.k2js.translate.utils.BindingUtils.getDeclarationsForNamespace; +import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptor; import static org.jetbrains.k2js.translate.utils.BindingUtils.getPropertyDescriptorForObjectDeclaration; /** * @author Pavel Talanov */ public final class DeclarationBodyVisitor extends TranslatorVisitor> { - - @NotNull public List traverseClass(@NotNull JetClassOrObject jetClass, @NotNull TranslationContext context) { @@ -69,7 +70,12 @@ public final class DeclarationBodyVisitor extends TranslatorVisitor visitNamedFunction(@NotNull JetNamedFunction expression, @NotNull TranslationContext context) { - return Collections.singletonList(Translation.functionTranslator(expression, context).translateAsMethod()); + JsPropertyInitializer o = Translation.functionTranslator(expression, context).translateAsMethod(); + if (context.isEcma5()) { + final FunctionDescriptor descriptor = getFunctionDescriptor(context.bindingContext(), expression); + o.setValueExpr(JsAstUtils.createPropertyDataDescriptor(descriptor.getModality().isOverridable(), o.getValueExpr(), context)); + } + return Collections.singletonList(o); } @Override @@ -92,6 +98,10 @@ public final class DeclarationBodyVisitor extends TranslatorVisitor visitObjectDeclarationName(@NotNull JetObjectDeclarationName expression, @NotNull TranslationContext context) { + if (context.isEcma5()) { + return Collections.emptyList(); + } + PropertyDescriptor propertyDescriptor = getPropertyDescriptorForObjectDeclaration(context.bindingContext(), expression); return PropertyTranslator.translateAccessors(propertyDescriptor, context); diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceDeclarationTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceDeclarationTranslator.java index b2da3265770..76cad438282 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceDeclarationTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceDeclarationTranslator.java @@ -17,8 +17,7 @@ package org.jetbrains.k2js.translate.declaration; import com.google.common.collect.Lists; -import com.google.dart.compiler.backend.js.ast.JsNameRef; -import com.google.dart.compiler.backend.js.ast.JsStatement; +import com.google.dart.compiler.backend.js.ast.*; import com.google.dart.compiler.util.AstUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; @@ -28,6 +27,7 @@ import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.k2js.translate.context.Namer; import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.general.AbstractTranslator; +import org.jetbrains.k2js.translate.utils.JsAstUtils; import org.jetbrains.k2js.translate.utils.JsDescriptorUtils; import org.jetbrains.k2js.translate.utils.TranslationUtils; @@ -88,7 +88,7 @@ public final class NamespaceDeclarationTranslator extends AbstractTranslator { private List namespacesDeclarations() { List result = Lists.newArrayList(); List namespaceTranslators = getTranslatorsForNonEmptyNamespaces(); - result.addAll(declarationStatements(namespaceTranslators)); + result.addAll(declarationStatements(namespaceTranslators, context())); result.addAll(initializeStatements(namespaceTranslators)); return result; } @@ -103,10 +103,19 @@ public final class NamespaceDeclarationTranslator extends AbstractTranslator { } @NotNull - private static List declarationStatements(@NotNull List namespaceTranslators) { + private static List declarationStatements(@NotNull List namespaceTranslators, TranslationContext context) { List result = Lists.newArrayList(); + + JsNameRef defs = JsAstUtils.qualified(context.jsScope().declareName("defs"), context.namer().kotlinObject()); for (NamespaceTranslator translator : namespaceTranslators) { - result.add(translator.getDeclarationAsVar()); + JsVars vars = translator.getDeclarationAsVar(); + + JsVars.JsVar var = vars.iterator().next(); + JsNameRef ref = new JsNameRef(var.getName()); + ref.setQualifier(defs); + + result.add(vars); + result.add(JsAstUtils.assignment(ref, new JsNameRef(var.getName())).makeStmt()); } return result; } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceTranslator.java index 5e35b6c24aa..93846c51f98 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/NamespaceTranslator.java @@ -25,6 +25,7 @@ import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.general.AbstractTranslator; import org.jetbrains.k2js.translate.general.Translation; +import org.jetbrains.k2js.translate.initializer.InitializerUtils; import org.jetbrains.k2js.translate.utils.JsDescriptorUtils; import java.util.ArrayList; @@ -58,7 +59,7 @@ public final class NamespaceTranslator extends AbstractTranslator { @NotNull - public JsStatement getDeclarationAsVar() { + public JsVars getDeclarationAsVar() { return newVar(namespaceName, getNamespaceDeclaration()); } @@ -70,7 +71,20 @@ public final class NamespaceTranslator extends AbstractTranslator { @NotNull private JsInvocation getNamespaceDeclaration() { JsInvocation namespaceDeclaration = namespaceCreateMethodInvocation(); - namespaceDeclaration.getArguments().add(translateNamespaceMemberDeclarations()); + + JsFunction initializer = Translation.generateNamespaceInitializerMethod(descriptor, context()); + List properties = new DeclarationBodyVisitor().traverseNamespace(descriptor, context()); + if (context().isEcma5()) { + namespaceDeclaration.getArguments().add(initializer); + namespaceDeclaration.getArguments().add(newObjectLiteral(properties)); + } + else { + List propertyList = new ArrayList(); + propertyList.add(InitializerUtils.generateInitializeMethod(initializer)); + propertyList.addAll(properties); + namespaceDeclaration.getArguments().add(newObjectLiteral(propertyList)); + } + namespaceDeclaration.getArguments().add(getClassesAndNestedNamespaces()); return namespaceDeclaration; } @@ -108,12 +122,4 @@ public final class NamespaceTranslator extends AbstractTranslator { } return result; } - - @NotNull - private JsObjectLiteral translateNamespaceMemberDeclarations() { - List propertyList = new ArrayList(); - propertyList.add(Translation.generateNamespaceInitializerMethod(descriptor, context())); - propertyList.addAll(new DeclarationBodyVisitor().traverseNamespace(descriptor, context())); - return newObjectLiteral(propertyList); - } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/PropertyTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/PropertyTranslator.java index b3130f3520b..165e1f4dc41 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/declaration/PropertyTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/declaration/PropertyTranslator.java @@ -19,14 +19,18 @@ package org.jetbrains.k2js.translate.declaration; import com.google.dart.compiler.backend.js.ast.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.PropertyAccessorDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyGetterDescriptor; import org.jetbrains.jet.lang.descriptors.PropertySetterDescriptor; import org.jetbrains.jet.lang.psi.JetProperty; import org.jetbrains.jet.lang.psi.JetPropertyAccessor; import org.jetbrains.k2js.translate.context.TranslationContext; +import org.jetbrains.k2js.translate.expression.FunctionTranslator; import org.jetbrains.k2js.translate.general.AbstractTranslator; import org.jetbrains.k2js.translate.general.Translation; +import org.jetbrains.k2js.translate.utils.JsDescriptorUtils; +import org.jetbrains.k2js.translate.utils.TranslationUtils; import java.util.ArrayList; import java.util.Collections; @@ -54,12 +58,19 @@ public final class PropertyTranslator extends AbstractTranslator { static public List translateAccessors(@NotNull PropertyDescriptor descriptor, @NotNull TranslationContext context) { - if (context.isEcma5()) { + if (context.isEcma5() && !JsDescriptorUtils.isAsPrivate(descriptor)) { return Collections.emptyList(); } PropertyTranslator propertyTranslator = new PropertyTranslator(descriptor, context); - return propertyTranslator.translate(); + List propertyInitializers = propertyTranslator.translate(); + if (context.isEcma5() && !descriptor.getReceiverParameter().exists()) { + JsObjectLiteral objectLiteral = new JsObjectLiteral(); + objectLiteral.getPropertyInitializers().addAll(propertyInitializers); + return Collections.singletonList( + new JsPropertyInitializer(context.program().getStringLiteral(descriptor.getName().getName()), objectLiteral)); + } + return propertyInitializers; } private PropertyTranslator(@NotNull PropertyDescriptor property, @NotNull TranslationContext context) { @@ -123,8 +134,7 @@ public final class PropertyTranslator extends AbstractTranslator { private JsPropertyInitializer generateDefaultGetter() { PropertyGetterDescriptor getterDescriptor = property.getGetter(); assert getterDescriptor != null : "Getter descriptor should not be null"; - return newNamedMethod(context().getNameForDescriptor(getterDescriptor), - generateDefaultGetterFunction(getterDescriptor)); + return generateDefaultAccessor(getterDescriptor, generateDefaultGetterFunction(getterDescriptor)); } @NotNull @@ -139,8 +149,7 @@ public final class PropertyTranslator extends AbstractTranslator { private JsPropertyInitializer generateDefaultSetter() { PropertySetterDescriptor setterDescriptor = property.getSetter(); assert setterDescriptor != null : "Setter descriptor should not be null"; - return newNamedMethod(context().getNameForDescriptor(setterDescriptor), - generateDefaultSetterFunction(setterDescriptor)); + return generateDefaultAccessor(setterDescriptor, generateDefaultSetterFunction(setterDescriptor)); } @NotNull @@ -154,6 +163,15 @@ public final class PropertyTranslator extends AbstractTranslator { return result; } + private JsPropertyInitializer generateDefaultAccessor(PropertyAccessorDescriptor accessorDescriptor, JsFunction function) { + if (context().isEcma5()) { + return TranslationUtils.translateFunctionAsEcma5PropertyDescriptor(function, accessorDescriptor, context()); + } + else { + return newNamedMethod(context().getNameForDescriptor(accessorDescriptor), function); + } + } + @NotNull private TranslationContext propertyAccessContext(@NotNull PropertySetterDescriptor propertySetterDescriptor) { return context().newDeclaration(propertySetterDescriptor); @@ -161,6 +179,7 @@ public final class PropertyTranslator extends AbstractTranslator { @NotNull private JsPropertyInitializer translateCustomAccessor(@NotNull JetPropertyAccessor expression) { - return Translation.functionTranslator(expression, context()).translateAsMethod(); + FunctionTranslator translator = Translation.functionTranslator(expression, context()); + return context().isEcma5() ? translator.translateAsEcma5PropertyDescriptor() : translator.translateAsMethod(); } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/expression/FunctionTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/expression/FunctionTranslator.java index e5c536b0b99..38e2bf40afc 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/expression/FunctionTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/expression/FunctionTranslator.java @@ -129,6 +129,12 @@ public final class FunctionTranslator extends AbstractTranslator { return functionObject; } + @NotNull + public JsPropertyInitializer translateAsEcma5PropertyDescriptor() { + generateFunctionObject(); + return TranslationUtils.translateFunctionAsEcma5PropertyDescriptor(functionObject, descriptor, context()); + } + @NotNull public JsPropertyInitializer translateAsMethod() { JsName functionName = context().getNameForElement(functionDeclaration); diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/expression/PatternTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/expression/PatternTranslator.java index e54d42c7ad5..95fdb69d868 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/expression/PatternTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/expression/PatternTranslator.java @@ -16,10 +16,7 @@ package org.jetbrains.k2js.translate.expression; -import com.google.dart.compiler.backend.js.ast.JsExpression; -import com.google.dart.compiler.backend.js.ast.JsInvocation; -import com.google.dart.compiler.backend.js.ast.JsName; -import com.google.dart.compiler.backend.js.ast.JsNameRef; +import com.google.dart.compiler.backend.js.ast.*; import com.google.dart.compiler.util.AstUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -135,7 +132,19 @@ public final class PatternTranslator extends AbstractTranslator { @NotNull private JsExpression translateExpressionPattern(@NotNull JsExpression expressionToMatch, JetExpressionPattern pattern) { JsExpression expressionToMatchAgainst = translateExpressionForExpressionPattern(pattern); - return equality(expressionToMatch, expressionToMatchAgainst); + JsBinaryOperation eq = equality(expressionToMatch, expressionToMatchAgainst); + // Uncaught TypeError: Cannot convert object to primitive value + if (context().isEcma5()) { + if (expressionToMatchAgainst instanceof JsNumberLiteral || + expressionToMatchAgainst instanceof JsStringLiteral || + expressionToMatchAgainst instanceof JsBooleanLiteral) { + JsNameRef valueOf = new JsNameRef("valueOf"); + valueOf.setQualifier(expressionToMatch); + return and(valueOf, eq); + } + } + + return eq; } @NotNull diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/expression/foreach/IteratorForTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/expression/foreach/IteratorForTranslator.java index 2a29eb211d7..d6e28144f7c 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/expression/foreach/IteratorForTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/expression/foreach/IteratorForTranslator.java @@ -21,15 +21,19 @@ import com.google.dart.compiler.util.AstUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.CallableDescriptor; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetForExpression; +import org.jetbrains.k2js.translate.context.Namer; import org.jetbrains.k2js.translate.context.TemporaryVariable; import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.general.Translation; import org.jetbrains.k2js.translate.reference.CallBuilder; -import static org.jetbrains.k2js.translate.utils.BindingUtils.*; +import static org.jetbrains.k2js.translate.utils.BindingUtils.getHasNextCallable; +import static org.jetbrains.k2js.translate.utils.BindingUtils.getIteratorFunction; +import static org.jetbrains.k2js.translate.utils.BindingUtils.getNextFunction; import static org.jetbrains.k2js.translate.utils.JsAstUtils.convertToBlock; import static org.jetbrains.k2js.translate.utils.JsAstUtils.newVar; import static org.jetbrains.k2js.translate.utils.PsiUtils.getLoopBody; @@ -81,7 +85,27 @@ public final class IteratorForTranslator extends ForTranslator { @NotNull private JsExpression hasNextMethodInvocation() { CallableDescriptor hasNextFunction = getHasNextCallable(bindingContext(), getLoopRange(expression)); - return translateMethodInvocation(iterator.reference(), hasNextFunction); + if (hasNextFunction instanceof FunctionDescriptor && !isJavaUtilIterator(hasNextFunction)) { + return translateMethodInvocation(iterator.reference(), hasNextFunction); + } + + // develar: I don't know, why hasNext called as function for PropertyDescriptor, our JS side define it as property and all other code translate it as property + JsNameRef hasNext = new JsNameRef(Namer.getNameForAccessor("hasNext", true, context().isEcma5())); + hasNext.setQualifier(iterator.reference()); + if (context().isEcma5()) { + return hasNext; + } + else { + JsInvocation invocation = new JsInvocation(); + invocation.setQualifier(hasNext); + return invocation; + } + } + + // kotlin iterator define hasNext as property, but java util as function, our js side expects as property + private static boolean isJavaUtilIterator(CallableDescriptor descriptor) { + final DeclarationDescriptor declaration = descriptor.getContainingDeclaration(); + return declaration != null && declaration.getName().getName().equals("Iterator"); } @NotNull diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/general/Translation.java b/js/js.translator/src/org/jetbrains/k2js/translate/general/Translation.java index 65abfa1a6a9..ca98bca0745 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/general/Translation.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/general/Translation.java @@ -78,7 +78,7 @@ public final class Translation { } @NotNull - public static JsInvocation translateClassDeclaration(@NotNull JetClass classDeclaration, + public static JsExpression translateClassDeclaration(@NotNull JetClass classDeclaration, @NotNull Map aliasingMap, @NotNull TranslationContext context) { return ClassTranslator.generateClassCreationExpression(classDeclaration, aliasingMap, context); @@ -128,14 +128,14 @@ public final class Translation { //TODO: see if generate*Initializer methods fit somewhere else @NotNull - public static JsPropertyInitializer generateClassInitializerMethod(@NotNull JetClassOrObject classDeclaration, + public static JsFunction generateClassInitializerMethod(@NotNull JetClassOrObject classDeclaration, @NotNull TranslationContext context) { final ClassInitializerTranslator classInitializerTranslator = new ClassInitializerTranslator(classDeclaration, context); return classInitializerTranslator.generateInitializeMethod(); } @NotNull - public static JsPropertyInitializer generateNamespaceInitializerMethod(@NotNull NamespaceDescriptor namespace, + public static JsFunction generateNamespaceInitializerMethod(@NotNull NamespaceDescriptor namespace, @NotNull TranslationContext context) { final NamespaceInitializerTranslator namespaceInitializerTranslator = new NamespaceInitializerTranslator(namespace, context); return namespaceInitializerTranslator.generateInitializeMethod(); @@ -164,11 +164,17 @@ public final class Translation { //TODO: move some of the code somewhere JetStandardLibrary standardLibrary = JetStandardLibrary.getInstance(); StaticContext staticContext = StaticContext.generateStaticContext(standardLibrary, bindingContext, ecmaVersion); - JsBlock block = staticContext.getProgram().getFragmentBlock(0); + JsProgram program = staticContext.getProgram(); + JsBlock block = program.getGlobalBlock(); + + JsFunction rootFunction = JsAstUtils.createPackage(block.getStatements(), program.getScope()); + List statements = rootFunction.getBody().getStatements(); + statements.add(program.getStringLiteral("use strict").makeStmt()); + TranslationContext context = TranslationContext.rootContext(staticContext); - block.getStatements().addAll(translateFiles(files, context)); + statements.addAll(translateFiles(files, context)); if (mainCallParameters.shouldBeGenerated()) { - block.getStatements().add(generateCallToMain(context, files, mainCallParameters.arguments())); + statements.add(generateCallToMain(context, files, mainCallParameters.arguments())); } JsNamer namer = new JsPrettyNamer(); namer.exec(context.program()); diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/initializer/ClassInitializerTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/initializer/ClassInitializerTranslator.java index 4786f384376..700d9416ad4 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/initializer/ClassInitializerTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/initializer/ClassInitializerTranslator.java @@ -17,6 +17,7 @@ package org.jetbrains.k2js.translate.initializer; import com.google.dart.compiler.backend.js.ast.*; +import com.google.dart.compiler.util.AstUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor; @@ -29,7 +30,6 @@ import org.jetbrains.jet.lang.psi.JetParameter; import org.jetbrains.k2js.translate.context.Namer; import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.general.AbstractTranslator; -import org.jetbrains.k2js.translate.utils.JsAstUtils; import java.util.ArrayList; import java.util.List; @@ -37,7 +37,6 @@ import java.util.List; import static org.jetbrains.k2js.translate.utils.BindingUtils.*; import static org.jetbrains.k2js.translate.utils.JsAstUtils.*; import static org.jetbrains.k2js.translate.utils.PsiUtils.getPrimaryConstructorParameters; -import static org.jetbrains.k2js.translate.utils.TranslationUtils.assignmentToBackingField; import static org.jetbrains.k2js.translate.utils.TranslationUtils.translateArgumentList; /** @@ -48,8 +47,6 @@ public final class ClassInitializerTranslator extends AbstractTranslator { private final JetClassOrObject classDeclaration; @NotNull private final List initializerStatements = new ArrayList(); - @NotNull - private final JsObjectLiteral propertiesDefinition = new JsObjectLiteral(); public ClassInitializerTranslator(@NotNull JetClassOrObject classDeclaration, @NotNull TranslationContext context) { // Note: it's important we use scope for class descriptor because anonymous function used in property initializers @@ -59,37 +56,45 @@ public final class ClassInitializerTranslator extends AbstractTranslator { } @NotNull - public JsPropertyInitializer generateInitializeMethod() { + public JsFunction generateInitializeMethod() { //TODO: it's inconsistent that we have scope for class and function for constructor, currently have problems implementing better way ConstructorDescriptor primaryConstructor = getConstructor(bindingContext(), classDeclaration); JsFunction result = context().getFunctionObject(primaryConstructor); //NOTE: while we translate constructor parameters we also add property initializer statements // for properties declared as constructor parameters setParameters(result, translatePrimaryConstructorParameters()); - mayBeAddCallToSuperMethod(); - initializerStatements.addAll((InitializerVisitor.create(context())).traverseClass(classDeclaration, context())); + mayBeAddCallToSuperMethod(result); + initializerStatements.addAll(new InitializerVisitor().traverseClass(classDeclaration, context())); result.getBody().getStatements().addAll(initializerStatements); - if (!propertiesDefinition.getPropertyInitializers().isEmpty()) { - result.getBody().getStatements().add(JsAstUtils.defineProperties(propertiesDefinition)); - } - - return InitializerUtils.generateInitializeMethod(result); + return result; } - private void mayBeAddCallToSuperMethod() { + private void mayBeAddCallToSuperMethod(JsFunction initializer) { if (hasAncestorClass(bindingContext(), classDeclaration)) { JetDelegatorToSuperCall superCall = getSuperCall(); if (superCall == null) return; - addCallToSuperMethod(superCall); + addCallToSuperMethod(superCall, initializer); } } - private void addCallToSuperMethod(@NotNull JetDelegatorToSuperCall superCall) { - //TODO: can be problematic to maintain - JsName superMethodName = context().jsScope().declareName(Namer.superMethodName()); - superMethodName.setObfuscatable(false); + private void addCallToSuperMethod(@NotNull JetDelegatorToSuperCall superCall, JsFunction initializer) { List arguments = translateArguments(superCall); - initializerStatements.add(convertToStatement(newInvocation(thisQualifiedReference(superMethodName), arguments))); + + //TODO: can be problematic to maintain + if (context().isEcma5()) { + JsName ref = context().jsScope().declareName("$initializer"); + initializer.setName(ref); + JsInvocation call = new JsInvocation(); + call.setQualifier(AstUtil.newNameRef(AstUtil.newNameRef(ref.makeRef(), "baseInitializer"), "call")); + call.getArguments().add(new JsThisRef()); + call.getArguments().addAll(arguments); + initializerStatements.add(call.makeStmt()); + } + else { + JsName superMethodName = context().jsScope().declareName(Namer.superMethodName()); + superMethodName.setObfuscatable(false); + initializerStatements.add(convertToStatement(newInvocation(thisQualifiedReference(superMethodName), arguments))); + } } @NotNull @@ -140,13 +145,6 @@ public final class ClassInitializerTranslator extends AbstractTranslator { } private void addInitializerOrPropertyDefinition(@NotNull JsNameRef initialValue, @NotNull PropertyDescriptor propertyDescriptor) { - if (context().isEcma5()) { - propertiesDefinition.getPropertyInitializers().add(JsAstUtils.propertyDescriptor(propertyDescriptor, initialValue, context())); - } - else { - JsStatement assignmentToBackingFieldExpression = - assignmentToBackingField(context(), propertyDescriptor, initialValue).makeStmt(); - initializerStatements.add(assignmentToBackingFieldExpression); - } + initializerStatements.add(InitializerUtils.generateInitializerForProperty(context(), propertyDescriptor, initialValue)); } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/initializer/Ecma3InitializerVisitor.java b/js/js.translator/src/org/jetbrains/k2js/translate/initializer/Ecma3InitializerVisitor.java deleted file mode 100644 index 7645f4943fe..00000000000 --- a/js/js.translator/src/org/jetbrains/k2js/translate/initializer/Ecma3InitializerVisitor.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2010-2012 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.k2js.translate.initializer; - -import com.google.dart.compiler.backend.js.ast.JsExpression; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; -import org.jetbrains.k2js.translate.context.TranslationContext; - -import static org.jetbrains.k2js.translate.utils.TranslationUtils.assignmentToBackingField; - -/** - * @author Pavel Talanov - */ -public final class Ecma3InitializerVisitor extends InitializerVisitor { - @Override - @Nullable - protected JsExpression generateInitializerForProperty(@NotNull PropertyDescriptor propertyDescriptor, - @NotNull JsExpression value, @NotNull TranslationContext context) { - return assignmentToBackingField(context, propertyDescriptor, value); - } -} diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/initializer/Ecma5InitializerVisitor.java b/js/js.translator/src/org/jetbrains/k2js/translate/initializer/Ecma5InitializerVisitor.java deleted file mode 100644 index 3378f81baf8..00000000000 --- a/js/js.translator/src/org/jetbrains/k2js/translate/initializer/Ecma5InitializerVisitor.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2010-2012 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.k2js.translate.initializer; - -import com.google.dart.compiler.backend.js.ast.JsExpression; -import com.google.dart.compiler.backend.js.ast.JsObjectLiteral; -import com.google.dart.compiler.backend.js.ast.JsStatement; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; -import org.jetbrains.jet.lang.psi.JetDeclaration; -import org.jetbrains.k2js.translate.context.TranslationContext; -import org.jetbrains.k2js.translate.utils.JsAstUtils; - -import java.util.List; - -public final class Ecma5InitializerVisitor extends InitializerVisitor { - @NotNull - private final JsObjectLiteral propertiesDefinition = new JsObjectLiteral(); - - @Override - @Nullable - protected JsExpression generateInitializerForProperty(@NotNull PropertyDescriptor propertyDescriptor, - @NotNull JsExpression value, @NotNull TranslationContext context) { - propertiesDefinition.getPropertyInitializers().add(JsAstUtils.propertyDescriptor(propertyDescriptor, value, context)); - return null; - } - - @NotNull - @Override - protected List generateInitializerStatements(@NotNull List declarations, - @NotNull TranslationContext context) { - List statements = super.generateInitializerStatements(declarations, context); - if (!propertiesDefinition.getPropertyInitializers().isEmpty()) { - JsStatement statement = JsAstUtils.defineProperties(propertiesDefinition); - statements.add(0, statement); - } - return statements; - } -} diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/initializer/InitializerUtils.java b/js/js.translator/src/org/jetbrains/k2js/translate/initializer/InitializerUtils.java index 8eb8589935a..d56f97a77e6 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/initializer/InitializerUtils.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/initializer/InitializerUtils.java @@ -16,12 +16,17 @@ package org.jetbrains.k2js.translate.initializer; +import com.google.dart.compiler.backend.js.ast.JsExpression; import com.google.dart.compiler.backend.js.ast.JsFunction; import com.google.dart.compiler.backend.js.ast.JsPropertyInitializer; +import com.google.dart.compiler.backend.js.ast.JsStatement; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.k2js.translate.context.Namer; import org.jetbrains.k2js.translate.context.TranslationContext; -import org.jetbrains.k2js.translate.general.AbstractTranslator; +import org.jetbrains.k2js.translate.utils.JsAstUtils; + +import static org.jetbrains.k2js.translate.utils.TranslationUtils.assignmentToBackingField; /** * @author Pavel Talanov @@ -39,4 +44,15 @@ public final class InitializerUtils { return initializer; } + @NotNull + public static JsStatement generateInitializerForProperty(@NotNull TranslationContext context, + @NotNull PropertyDescriptor descriptor, + @NotNull JsExpression value) { + if (context.isEcma5()) { + return JsAstUtils.definePropertyDataDescriptor(descriptor, value, context).makeStmt(); + } + else { + return assignmentToBackingField(context, descriptor, value).makeStmt(); + } + } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/initializer/InitializerVisitor.java b/js/js.translator/src/org/jetbrains/k2js/translate/initializer/InitializerVisitor.java index 302802d84d2..e37ec14b97c 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/initializer/InitializerVisitor.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/initializer/InitializerVisitor.java @@ -21,7 +21,6 @@ import com.google.dart.compiler.backend.js.ast.JsExpression; import com.google.dart.compiler.backend.js.ast.JsInvocation; import com.google.dart.compiler.backend.js.ast.JsStatement; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.psi.*; @@ -29,7 +28,6 @@ import org.jetbrains.k2js.translate.context.TranslationContext; import org.jetbrains.k2js.translate.declaration.ClassTranslator; import org.jetbrains.k2js.translate.general.Translation; import org.jetbrains.k2js.translate.general.TranslatorVisitor; -import org.jetbrains.k2js.translate.utils.JsAstUtils; import java.util.Arrays; import java.util.Collections; @@ -42,11 +40,7 @@ import static org.jetbrains.k2js.translate.utils.PsiUtils.getObjectDeclarationFo /** * @author Pavel Talanov */ -public abstract class InitializerVisitor extends TranslatorVisitor> { - static InitializerVisitor create(TranslationContext context) { - return context.isEcma5() ? new Ecma5InitializerVisitor() : new Ecma3InitializerVisitor(); - } - +public final class InitializerVisitor extends TranslatorVisitor> { @Override @NotNull public final List visitProperty(@NotNull JetProperty property, @NotNull TranslationContext context) { @@ -54,16 +48,16 @@ public abstract class InitializerVisitor extends TranslatorVisitor generateInitializerForProperty(@NotNull PropertyDescriptor descriptor, + @NotNull JsExpression value, @NotNull TranslationContext context) { + return Collections.singletonList(InitializerUtils.generateInitializerForProperty(context, descriptor, value)); + } @Override @NotNull @@ -85,13 +79,12 @@ public abstract class InitializerVisitor extends TranslatorVisitor generateInitializerStatements(@NotNull List declarations, + private List generateInitializerStatements(@NotNull List declarations, @NotNull TranslationContext context) { List statements = Lists.newArrayList(); for (JetDeclaration declaration : declarations) { diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/initializer/NamespaceInitializerTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/initializer/NamespaceInitializerTranslator.java index d539718c14d..8340c683c76 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/initializer/NamespaceInitializerTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/initializer/NamespaceInitializerTranslator.java @@ -42,14 +42,13 @@ public final class NamespaceInitializerTranslator { } @NotNull - public JsPropertyInitializer generateInitializeMethod() { + public JsFunction generateInitializeMethod() { JsFunction result = JsAstUtils.createFunctionWithEmptyBody(namespaceContext.jsScope()); TranslationContext namespaceInitializerContext = namespaceContext.innerContextWithGivenScopeAndBlock(result.getScope(), result.getBody()); - List initializerStatements = (InitializerVisitor.create(namespaceContext)).traverseNamespace(namespace, - namespaceInitializerContext); + List initializerStatements = new InitializerVisitor().traverseNamespace(namespace, namespaceInitializerContext); result.getBody().getStatements().addAll(initializerStatements); - return InitializerUtils.generateInitializeMethod(result); + return result; } } \ No newline at end of file diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/primitive/PrimitiveRangeToIntrinsic.java b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/primitive/PrimitiveRangeToIntrinsic.java index ec908e4b72f..c5baca2e3a2 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/primitive/PrimitiveRangeToIntrinsic.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/primitive/PrimitiveRangeToIntrinsic.java @@ -16,10 +16,7 @@ package org.jetbrains.k2js.translate.intrinsic.primitive; -import com.google.dart.compiler.backend.js.ast.JsBinaryOperation; -import com.google.dart.compiler.backend.js.ast.JsBooleanLiteral; -import com.google.dart.compiler.backend.js.ast.JsExpression; -import com.google.dart.compiler.backend.js.ast.JsNew; +import com.google.dart.compiler.backend.js.ast.*; import com.google.dart.compiler.util.AstUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -53,10 +50,11 @@ public final class PrimitiveRangeToIntrinsic implements Intrinsic { JsBinaryOperation rangeSize = sum(subtract(rangeEnd, rangeStart), context.program().getNumberLiteral(1)); //TODO: provide a way not to hard code this value - JsNew numberRangeConstructorInvocation = new JsNew(AstUtil.newQualifiedNameRef("Kotlin.NumberRange")); + JsNameRef expr = AstUtil.newQualifiedNameRef("Kotlin.NumberRange"); + HasArguments numberRangeConstructorInvocation = context.isEcma5() ? AstUtil.newInvocation(expr) : new JsNew(expr); //TODO: add tests and correct expression for reversed ranges. JsBooleanLiteral isRangeReversed = context.program().getFalseLiteral(); setArguments(numberRangeConstructorInvocation, rangeStart, rangeSize, isRangeReversed); - return numberRangeConstructorInvocation; + return (JsExpression) numberRangeConstructorInvocation; } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallTranslator.java index bf762ef4080..57eda81cfb5 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/reference/CallTranslator.java @@ -17,10 +17,7 @@ package org.jetbrains.k2js.translate.reference; import com.google.common.collect.Lists; -import com.google.dart.compiler.backend.js.ast.JsExpression; -import com.google.dart.compiler.backend.js.ast.JsInvocation; -import com.google.dart.compiler.backend.js.ast.JsNameRef; -import com.google.dart.compiler.backend.js.ast.JsNew; +import com.google.dart.compiler.backend.js.ast.*; import com.google.dart.compiler.util.AstUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -138,8 +135,14 @@ public final class CallTranslator extends AbstractTranslator { @NotNull private JsExpression constructorCall() { JsExpression constructorReference = translateAsFunctionWithNoThisObject(descriptor); - JsNew constructorCall = new JsNew(constructorReference); - setArguments(constructorCall, arguments); + JsExpression constructorCall; + if (context().isEcma5() && !AnnotationsUtils.isNativeObject(resolvedCall.getCandidateDescriptor())) { + constructorCall = AstUtil.newInvocation(constructorReference); + } + else { + constructorCall = new JsNew(constructorReference); + } + ((HasArguments) constructorCall).getArguments().addAll(arguments); return constructorCall; } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/reference/ReferenceTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/reference/ReferenceTranslator.java index 993d73c790d..74396e94106 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/reference/ReferenceTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/reference/ReferenceTranslator.java @@ -21,7 +21,6 @@ import com.google.dart.compiler.backend.js.ast.JsName; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; -import org.jetbrains.jet.lang.descriptors.PropertyAccessorDescriptor; import org.jetbrains.jet.lang.psi.JetSimpleNameExpression; import org.jetbrains.k2js.translate.context.TranslationContext; @@ -56,26 +55,8 @@ public final class ReferenceTranslator { @NotNull public static JsExpression translateAsLocalNameReference(@NotNull DeclarationDescriptor referencedDescriptor, @NotNull TranslationContext context) { - DeclarationDescriptor effectiveDescriptor = getReferencedDescriptor(referencedDescriptor, context); - // Preconditions.checkNotNull(effectiveDescriptor, "Could not find DeclarationDescriptor for %s", referencedDescriptor); - return context.getNameForDescriptor(effectiveDescriptor).makeRef(); - } - - - //TODO: should not be doing this - @NotNull - private static DeclarationDescriptor getReferencedDescriptor(@NotNull DeclarationDescriptor referencedDescriptor, - @NotNull TranslationContext context) { - DeclarationDescriptor effectiveDescriptor; - if (context.isEcma5() && referencedDescriptor instanceof PropertyAccessorDescriptor) { - effectiveDescriptor = ((PropertyAccessorDescriptor) referencedDescriptor).getCorrespondingProperty(); - // Preconditions.checkNotNull(effectiveDescriptor, "No correspondingProperty available for descriptor %s", referencedDescriptor); - } - else { - effectiveDescriptor = referencedDescriptor; - // Preconditions.checkNotNull(effectiveDescriptor, "No referencedDescriptor available"); - } - return effectiveDescriptor; + //Preconditions.checkNotNull(referencedDescriptor, "No referencedDescriptor available"); + return context.getNameForDescriptor(referencedDescriptor).makeRef(); } @NotNull diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsAstUtils.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsAstUtils.java index fe59022b93c..607ad84e389 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsAstUtils.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsAstUtils.java @@ -30,15 +30,12 @@ import java.util.*; * @author Pavel Talanov */ public final class JsAstUtils { - private static final JsNameRef VALUE = new JsNameRef("value"); - private static final JsPropertyInitializer WRITABLE = new JsPropertyInitializer(new JsNameRef("writable"), null); - private static final JsNameRef DEFINE_PROPERTIES = new JsNameRef("defineProperties"); - private static final JsNameRef CREATE = new JsNameRef("create"); + private static final JsNameRef DEFINE_PROPERTY = new JsNameRef("defineProperty"); + private static final JsNameRef EMPTY_REF = new JsNameRef(""); static { JsNameRef globalObjectReference = new JsNameRef("Object"); - DEFINE_PROPERTIES.setQualifier(globalObjectReference); - CREATE.setQualifier(globalObjectReference); + DEFINE_PROPERTY.setQualifier(globalObjectReference); } private JsAstUtils() { @@ -227,13 +224,13 @@ public final class JsAstUtils { arguments.addAll(newArgs); } - public static void setArguments(@NotNull JsNew invocation, @NotNull List newArgs) { + public static void setArguments(@NotNull HasArguments invocation, @NotNull List newArgs) { List arguments = invocation.getArguments(); assert arguments.isEmpty() : "Arguments already set."; arguments.addAll(newArgs); } - public static void setArguments(@NotNull JsNew invocation, JsExpression... arguments) { + public static void setArguments(@NotNull HasArguments invocation, JsExpression... arguments) { setArguments(invocation, Arrays.asList(arguments)); } @@ -287,36 +284,44 @@ public final class JsAstUtils { } @NotNull - public static JsStatement defineProperties(@NotNull JsObjectLiteral propertiesDefinition) { - return AstUtil.newInvocation(DEFINE_PROPERTIES, new JsThisRef(), propertiesDefinition).makeStmt(); + public static JsInvocation definePropertyDataDescriptor(@NotNull PropertyDescriptor descriptor, + @NotNull JsExpression value, + @NotNull TranslationContext context) { + return AstUtil.newInvocation(DEFINE_PROPERTY, new JsThisRef(), + context.program().getStringLiteral(context.getNameForDescriptor(descriptor).getIdent()), + createPropertyDataDescriptor(descriptor.isVar(), value, context)); } @NotNull - public static JsPropertyInitializer propertyDescriptor(@NotNull PropertyDescriptor descriptor, - @NotNull JsExpression value, @NotNull TranslationContext context) { + public static JsObjectLiteral createPropertyDataDescriptor(boolean writable, + @NotNull JsExpression value, + @NotNull TranslationContext context) { JsObjectLiteral jsPropertyDescriptor = new JsObjectLiteral(); List meta = jsPropertyDescriptor.getPropertyInitializers(); - meta.add(new JsPropertyInitializer(VALUE, value)); - if (descriptor.isVar()) { - meta.add(getWritable(context)); + meta.add(new JsPropertyInitializer(context.program().getStringLiteral("value"), value)); + if (writable) { + meta.add(context.namer().writablePropertyDescriptorField()); } - // TODO: accessors - return new JsPropertyInitializer(context.getNameForDescriptor(descriptor).makeRef(), jsPropertyDescriptor); + return jsPropertyDescriptor; } @NotNull - private static JsPropertyInitializer getWritable(@NotNull TranslationContext context) { - if (WRITABLE.getValueExpr() == null) { - WRITABLE.setValueExpr(context.program().getTrueLiteral()); - } - return WRITABLE; + public static JsInvocation encloseFunction(JsFunction function) { + JsInvocation blockFunctionInvocation = new JsInvocation(); + blockFunctionInvocation.setQualifier(EMPTY_REF); + blockFunctionInvocation.getArguments().add(function); + return blockFunctionInvocation; } @NotNull - public static List nullableExpressionToStatementList(@Nullable JsExpression initalizerForProperty) { - if (initalizerForProperty == null) { - return Collections.emptyList(); - } - return Collections.singletonList(initalizerForProperty.makeStmt()); + public static JsFunction createPackage(List to, JsScope scope) { + JsFunction packageBlockFunction = createFunctionWithEmptyBody(scope); + + JsInvocation packageBlockFunctionInvocation = encloseFunction(packageBlockFunction); + JsInvocation packageBlock = new JsInvocation(); + packageBlock.setQualifier(packageBlockFunctionInvocation); + to.add(packageBlock.makeStmt()); + + return packageBlockFunction; } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsDescriptorUtils.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsDescriptorUtils.java index bf6c8815991..d708a6fb16e 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsDescriptorUtils.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/JsDescriptorUtils.java @@ -281,4 +281,14 @@ public final class JsDescriptorUtils { } return null; } + + private static boolean isDefaultAccessor(@Nullable PropertyAccessorDescriptor accessorDescriptor) { + return accessorDescriptor == null || accessorDescriptor.isDefault(); + } + + public static boolean isAsPrivate(@NotNull PropertyDescriptor propertyDescriptor) { + return propertyDescriptor.getReceiverParameter().exists() || + !isDefaultAccessor(propertyDescriptor.getGetter()) || + !isDefaultAccessor(propertyDescriptor.getSetter()); + } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/TranslationUtils.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/TranslationUtils.java index c7a87419c46..734881362dc 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/TranslationUtils.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/TranslationUtils.java @@ -45,6 +45,24 @@ public final class TranslationUtils { private TranslationUtils() { } + @NotNull + public static JsPropertyInitializer translateFunctionAsEcma5PropertyDescriptor(@NotNull JsFunction function, + @NotNull FunctionDescriptor descriptor, + @NotNull TranslationContext context) { + if (descriptor.getReceiverParameter().exists()) { + JsObjectLiteral meta = new JsObjectLiteral(); + meta.getPropertyInitializers().add(new JsPropertyInitializer(context.program().getStringLiteral("value"), function)); + if (descriptor.getModality().isOverridable()) { + meta.getPropertyInitializers().add(context.namer().writablePropertyDescriptorField()); + } + return new JsPropertyInitializer(context.getNameForDescriptor(descriptor).makeRef(), meta); + } + else { + return new JsPropertyInitializer( + context.program().getStringLiteral(descriptor instanceof PropertyGetterDescriptor ? "get" : "set"), function); + } + } + @NotNull public static JsBinaryOperation notNullCheck(@NotNull TranslationContext context, @NotNull JsExpression expressionToCheck) { diff --git a/js/js.translator/testFiles/extensionProperty/cases/propertyWithGetterAndSetter.kt b/js/js.translator/testFiles/extensionProperty/cases/propertyWithGetterAndSetter.kt index aba51251279..a562b82128b 100644 --- a/js/js.translator/testFiles/extensionProperty/cases/propertyWithGetterAndSetter.kt +++ b/js/js.translator/testFiles/extensionProperty/cases/propertyWithGetterAndSetter.kt @@ -10,6 +10,8 @@ var Test.b : Int a = c - 1 } +val Test.d : Int = 44 + fun box() : Boolean { val c = Test() if (c.a != 0) return false; @@ -19,5 +21,6 @@ fun box() : Boolean { c.b = 10; if (c.a != 9) return false; if (c.b != 27) return false; + if (c.d != 44) return false; return true; } \ No newline at end of file diff --git a/js/js.translator/testFiles/kotlinLib/cases/hashMap.js b/js/js.translator/testFiles/kotlinLib/cases/hashMap.js index d444a7775b9..1b5ab93cb15 100644 --- a/js/js.translator/testFiles/kotlinLib/cases/hashMap.js +++ b/js/js.translator/testFiles/kotlinLib/cases/hashMap.js @@ -14,7 +14,7 @@ * limitations under the License. */ -var map = new Kotlin.HashMap() +var map = Kotlin.$new(Kotlin.HashMap)() map.put(3, 4) map.put(6, 3) @@ -38,4 +38,4 @@ function test() { return true; -} \ No newline at end of file +} diff --git a/js/js.translator/testFiles/kotlinLib/cases/isAncestorType.js b/js/js.translator/testFiles/kotlinLib/cases/isAncestorType.js index 46d961cc92e..d290b0ac269 100644 --- a/js/js.translator/testFiles/kotlinLib/cases/isAncestorType.js +++ b/js/js.translator/testFiles/kotlinLib/cases/isAncestorType.js @@ -14,10 +14,10 @@ * limitations under the License. */ -var A = Kotlin.Class.create(); -var B = Kotlin.Class.create(A); +var A = Kotlin.createClass(); +var B = Kotlin.createClass(A); var b = new B; test = function() { return (Kotlin.isType(b, A) && Kotlin.isType(b, B)); -} \ No newline at end of file +} diff --git a/js/js.translator/testFiles/kotlinLib/cases/isComplexTest.js b/js/js.translator/testFiles/kotlinLib/cases/isComplexTest.js index bf23199a7ce..e50a0e99645 100644 --- a/js/js.translator/testFiles/kotlinLib/cases/isComplexTest.js +++ b/js/js.translator/testFiles/kotlinLib/cases/isComplexTest.js @@ -14,12 +14,12 @@ * limitations under the License. */ -var A = Kotlin.Class.create(); -var B = Kotlin.Class.create(A); +var A = Kotlin.createClass(); +var B = Kotlin.createClass(A); var b = new B; -var C = Kotlin.Class.create(B); +var C = Kotlin.createClass(B); var c = new C; -var E = Kotlin.Class.create(A) +var E = Kotlin.createClass(A) var e = new E; test1 = function() { @@ -37,4 +37,4 @@ test3 = function() { test = function() { return test1() && test2() && test3() -} \ No newline at end of file +} diff --git a/js/js.translator/testFiles/kotlinLib/cases/isNotOtherType.js b/js/js.translator/testFiles/kotlinLib/cases/isNotOtherType.js index 8a265d953c9..a9d2e53119a 100644 --- a/js/js.translator/testFiles/kotlinLib/cases/isNotOtherType.js +++ b/js/js.translator/testFiles/kotlinLib/cases/isNotOtherType.js @@ -14,11 +14,11 @@ * limitations under the License. */ -var A = Kotlin.Class.create(); -var B = Kotlin.Class.create(A); -var C = Kotlin.Class.create(); +var A = Kotlin.createClass(); +var B = Kotlin.createClass(A); +var C = Kotlin.createClass(); var c = new C; test = function() { return ((!isType(c, A)) && !isType(c, B)); -} \ No newline at end of file +} diff --git a/js/js.translator/testFiles/kotlinLib/cases/isSameType.js b/js/js.translator/testFiles/kotlinLib/cases/isSameType.js index 3148ba5fafc..e2abd90c636 100644 --- a/js/js.translator/testFiles/kotlinLib/cases/isSameType.js +++ b/js/js.translator/testFiles/kotlinLib/cases/isSameType.js @@ -14,9 +14,9 @@ * limitations under the License. */ -var A = Kotlin.Class.create(); -var a = new A; +var A = Kotlin.createClass(); +var a = Kotlin.$new(A)(); test = function() { return Kotlin.isType(a, A); -} \ No newline at end of file +} diff --git a/js/js.translator/testFiles/kotlinLib/cases/namespace.js b/js/js.translator/testFiles/kotlinLib/cases/namespace.js index efb33d78ab5..2348996f0a9 100644 --- a/js/js.translator/testFiles/kotlinLib/cases/namespace.js +++ b/js/js.translator/testFiles/kotlinLib/cases/namespace.js @@ -14,7 +14,7 @@ * limitations under the License. */ -foo = Kotlin.Namespace.create({initialize:function(){ +foo = Kotlin.createNamespace({initialize:function(){ } , box:function(){ return !false; diff --git a/js/js.translator/testFiles/kotlinLib/cases/namespaceWithClasses.js b/js/js.translator/testFiles/kotlinLib/cases/namespaceWithClasses.js index 9246b4fff22..69a33df0984 100644 --- a/js/js.translator/testFiles/kotlinLib/cases/namespaceWithClasses.js +++ b/js/js.translator/testFiles/kotlinLib/cases/namespaceWithClasses.js @@ -16,7 +16,7 @@ { classes = function(){ - var A = Kotlin.Class.create({initialize:function(){ + var A = Kotlin.createClass({initialize:function(){ this.$order = ''; { this.set_order(this.get_order() + 'A'); @@ -29,14 +29,14 @@ return this.$order; } }); - var B = Kotlin.Class.create(A, {initialize:function(){ + var B = Kotlin.createClass(A, {initialize:function(){ this.super_init(); { this.set_order(this.get_order() + 'B'); } } }); - var C = Kotlin.Class.create(B, {initialize:function(){ + var C = Kotlin.createClass(B, {initialize:function(){ this.super_init(); { this.set_order(this.get_order() + 'C'); @@ -46,7 +46,7 @@ return {A:A, B:B, C:C}; } (); - foo = Kotlin.Namespace.create(classes, {initialize:function(){ + foo = Kotlin.createNamespace(classes, {initialize:function(){ } , box:function(){ return (new foo.C).get_order() === 'ABC' && (new foo.B).get_order() === 'AB' && (new foo.A).get_order() === 'A'; diff --git a/js/js.translator/testFiles/kotlinLib/cases/trait.js b/js/js.translator/testFiles/kotlinLib/cases/trait.js index 8cd2e9b0ed9..90b9c39846f 100644 --- a/js/js.translator/testFiles/kotlinLib/cases/trait.js +++ b/js/js.translator/testFiles/kotlinLib/cases/trait.js @@ -16,11 +16,11 @@ foo = {}; (function(foo){ - foo.Test = Kotlin.Trait.create({addFoo:function(s){ + foo.Test = Kotlin.createTrait({addFoo:function(s){ return s + 'FOO'; } }); - foo.ExtendedTest = Kotlin.Trait.create(foo.Test, {hooray:function(){ + foo.ExtendedTest = Kotlin.createTrait(foo.Test, {hooray:function(){ return 'hooray'; } }); diff --git a/js/js.translator/testFiles/kotlin_lib.js b/js/js.translator/testFiles/kotlin_lib.js index 625c6809031..89f0540e861 100644 --- a/js/js.translator/testFiles/kotlin_lib.js +++ b/js/js.translator/testFiles/kotlin_lib.js @@ -1,282 +1,5 @@ -/** - * Copyright 2010 Tim Down. - * - * 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. - */ - -/* Prototype JavaScript framework, version 1.6.1 - * (c) 2005-2009 Sam Stephenson - * - * Prototype is freely distributable under the terms of an MIT-style license. - * For details, see the Prototype web site: http://www.prototypejs.org/ - * - *--------------------------------------------------------------------------*/ -var Kotlin; (function () { "use strict"; - function $A(iterable) { - if (!iterable) return []; - if ('toArray' in Object(iterable)) return iterable.toArray(); - var length = iterable.length || 0, results = new Array(length); - while (length--) results[length] = iterable[length]; - return results; - } - - (function () { - - - function extend(destination, source) { - for (var property in source) - destination[property] = source[property]; - return destination; - } - - - function keys(object) { - var results = []; - for (var property in object) { - if (object.hasOwnProperty(property)) { - results.push(property); - } - } - return results; - } - - function values(object) { - var results = []; - for (var property in object) - results.push(object[property]); - return results; - } - - extend(Object, { - extend:extend, - keys:Object.keys || keys, - values:values - }); - })(); - - - Object.extend(Function.prototype, (function () { - var slice = Array.prototype.slice; - - function update(array, args) { - var arrayLength = array.length, length = args.length; - while (length--) array[arrayLength + length] = args[length]; - return array; - } - - function merge(array, args) { - array = slice.call(array, 0); - return update(array, args); - } - - function argumentNames() { - var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1] - .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '') - .replace(/\s+/g, '').split(','); - return names.length == 1 && !names[0] ? [] : names; - } - - function bind(context) { - if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; - var __method = this, args = slice.call(arguments, 1); - return function () { - var a = merge(args, arguments); - return __method.apply(context, a); - }; - } - - function bindAsEventListener(context) { - var __method = this, args = slice.call(arguments, 1); - return function (event) { - var a = update([event || window.event], args); - return __method.apply(context, a); - }; - } - - function wrap(wrapper) { - var __method = this; - return function () { - var a = update([__method.bind(this)], arguments); - return wrapper.apply(this, a); - }; - } - - return { - argumentNames:argumentNames, - bind:bind, - bindAsEventListener:bindAsEventListener, - wrap:wrap - }; - })()); - - var isType = function (object, klass) { - if (object === null) { - return false; - } - var current = object.get_class(); - while (current !== klass) { - if (current === null) { - return false; - } - current = current.superclass; - } - return true; - }; - - var emptyFunction = function () { - }; - - var Class = (function () { - - function subclass() { - } - - function create() { - var parent = null, properties = $A(arguments); - if (typeof (properties[0]) == "function") { - parent = properties.shift(); - } - - function klass() { - this.initializing = klass; - this.initialize.apply(this, arguments); - } - - Object.extend(klass, Class.Methods); - klass.superclass = parent; - klass.subclasses = []; - - if (parent) { - subclass.prototype = parent.prototype; - klass.prototype = new subclass(); - parent.subclasses.push(klass); - } - - klass.addMethods( - { - get_class:function () { - return klass; - } - }); - - if (parent !== null) { - klass.addMethods( - { - super_init:function () { - this.initializing = this.initializing.superclass; - this.initializing.prototype.initialize.apply(this, arguments); - } - }); - } - - for (var i = 0, length = properties.length; i < length; i++) - klass.addMethods(properties[i]); - - if (!klass.prototype.initialize) { - klass.prototype.initialize = emptyFunction; - } - - klass.prototype.constructor = klass; - return klass; - } - - function addMethods(source) { - var ancestor = this.superclass && this.superclass.prototype, - properties = Object.keys(source); - - - for (var i = 0, length = properties.length; i < length; i++) { - var property = properties[i], value = source[property]; - if (ancestor && (typeof (value) == "function") && - value.argumentNames()[0] == "$super") { - var method = value; - value = (function (m) { - return function () { - return ancestor[m].apply(this, arguments); - }; - })(property).wrap(method); - - } - this.prototype[property] = value; - } - - return this; - } - - return { - create:create, - Methods:{ - addMethods:addMethods - } - }; - })(); - - var Trait = (function () { - - function add(object, source) { - var properties = Object.keys(source); - for (var i = 0, length = properties.length; i < length; i++) { - var property = properties[i]; - var value = source[property]; - object[property] = value; - } - return this; - } - - function create() { - var result = {}; - for (var i = 0, length = arguments.length; i < length; i++) { - add(result, arguments[i]); - } - return result; - } - - return { - create:create - }; - })(); - - - var Namespace = (function () { - - function create() { - return Trait.create.apply(Trait, arguments); - } - - return { - create:create - }; - })(); - - var object = (function () { - function create() { - var singletonClass = Class.create.apply(Class, arguments); - return new singletonClass(); - } - - return { - create:create - }; - })(); - - Kotlin = {}; - Kotlin.Class = Class; - Kotlin.Namespace = Namespace; - Kotlin.Trait = Trait; - Kotlin.isType = isType; - Kotlin.object = object; Kotlin.equals = function (obj1, obj2) { if (typeof obj1 == "object") { @@ -287,22 +10,66 @@ var Kotlin; return (obj1 === obj2); }; + Kotlin.defs = {}; Kotlin.Exceptions = {}; - Kotlin.Exception = Kotlin.Class.create(); - Kotlin.RuntimeException = Kotlin.Class.create(Kotlin.Exception); - Kotlin.Exceptions.IndexOutOfBounds = Kotlin.Class.create(Kotlin.Exception); - Kotlin.Exceptions.NullPointerException = Kotlin.Class.create(Kotlin.Exception); - Kotlin.Exceptions.NoSuchElementException = Kotlin.Class.create(Kotlin.Exception); - Kotlin.Exceptions.IllegalArgumentException = Kotlin.Class.create(Kotlin.Exception); - Kotlin.Exceptions.IllegalStateException = Kotlin.Class.create(Kotlin.Exception); - Kotlin.Exceptions.IndexOutOfBoundsException = Kotlin.Class.create(Kotlin.Exception); - Kotlin.Exceptions.UnsupportedOperationException = Kotlin.Class.create(Kotlin.Exception); + Kotlin.Exception = Kotlin.$createClass(); + Kotlin.RuntimeException = Kotlin.$createClass(Kotlin.Exception); + Kotlin.Exceptions.IndexOutOfBounds = Kotlin.$createClass(Kotlin.Exception); + Kotlin.Exceptions.NullPointerException = Kotlin.$createClass(Kotlin.Exception); + Kotlin.Exceptions.NoSuchElementException = Kotlin.$createClass(Kotlin.Exception); + Kotlin.Exceptions.IllegalArgumentException = Kotlin.$createClass(Kotlin.Exception); + Kotlin.Exceptions.IllegalStateException = Kotlin.$createClass(Kotlin.Exception); + Kotlin.Exceptions.IndexOutOfBoundsException = Kotlin.$createClass(Kotlin.Exception); + Kotlin.Exceptions.UnsupportedOperationException = Kotlin.$createClass(Kotlin.Exception); Kotlin.throwNPE = function() { - throw new Kotlin.Exceptions.NullPointerException(); + throw Kotlin.$new(Kotlin.Exceptions.NullPointerException)(); }; - Kotlin.ArrayList = Class.create({ + Kotlin.AbstractList = Kotlin.$createClass({ + set:function (index, value) { + throw Kotlin.$new(Kotlin.Exceptions.UnsupportedOperationException)(); + }, + iterator:function () { + return Kotlin.$new(Kotlin.ArrayIterator)(this); + }, + isEmpty:function () { + return (this.size() === 0); + }, + add:function (element) { + throw Kotlin.$new(Kotlin.Exceptions.UnsupportedOperationException)(); + }, + addAll:function (collection) { + var it = collection.iterator(); + while (it.get_hasNext()) { + this.add(it.next()); + } + }, + remove:function(value) { + for (var i = 0; i < this.$size; ++i) { + if (this.array[i] == value) { + this.removeByIndex(i); + return; + } + } + }, + removeByIndex:function (index) { + throw Kotlin.$new(Kotlin.Exceptions.UnsupportedOperationException)(); + }, + clear:function () { + throw Kotlin.$new(Kotlin.Exceptions.UnsupportedOperationException)(); + }, + contains:function (obj) { + for (var i = 0; i < this.$size; ++i) { + if (Kotlin.equals(this.array[i], obj)) { + return true; + } + } + return false; + } + }); + + Kotlin.ArrayList = Kotlin.$createClass({ initialize:function () { this.array = []; this.$size = 0; @@ -323,7 +90,7 @@ var Kotlin; return this.$size; }, iterator:function () { - return new Kotlin.ArrayIterator(this); + return Kotlin.$new(Kotlin.ArrayIterator)(this); }, isEmpty:function () { return (this.$size === 0); @@ -333,7 +100,7 @@ var Kotlin; }, addAll:function (collection) { var it = collection.iterator(); - while (it.hasNext()) { + while (it.get_hasNext()) { this.add(it.next()); } }, @@ -366,50 +133,6 @@ var Kotlin; }); - Kotlin.AbstractList = Class.create({ - set:function (index, value) { - throw new Kotlin.Exceptions.UnsupportedOperationException(); - }, - iterator:function () { - return new Kotlin.ArrayIterator(this); - }, - isEmpty:function () { - return (this.size() === 0); - }, - add:function (element) { - throw new Kotlin.Exceptions.UnsupportedOperationException(); - }, - addAll:function (collection) { - var it = collection.iterator(); - while (it.hasNext()) { - this.add(it.next()); - } - }, - remove:function(value) { - for (var i = 0; i < this.$size; ++i) { - if (this.array[i] == value) { - this.removeByIndex(i); - return; - } - } - }, - removeByIndex:function (index) { - throw new Kotlin.Exceptions.UnsupportedOperationException(); - }, - clear:function () { - throw new Kotlin.Exceptions.UnsupportedOperationException(); - }, - contains:function (obj) { - for (var i = 0; i < this.$size; ++i) { - if (Kotlin.equals(this.array[i], obj)) { - return true; - } - } - return false; - } - }); - - Kotlin.parseInt = function (str) { return parseInt(str, 10); } @@ -467,37 +190,33 @@ var Kotlin; Kotlin.System.out().print(s); }; - Kotlin.AbstractFunctionInvocationError = Class.create(); + Kotlin.AbstractFunctionInvocationError = Kotlin.$createClass(); - Kotlin.Iterator = Class.create({ + Kotlin.Iterator = Kotlin.$createClass({ initialize:function () { }, next:function () { - throw new Kotlin.AbstractFunctionInvocationError(); + throw Kotlin.$new(Kotlin.AbstractFunctionInvocationError)(); }, - hasNext:function () { - throw new Kotlin.AbstractFunctionInvocationError(); + get_hasNext:function () { + throw Kotlin.$new(Kotlin.AbstractFunctionInvocationError)(); } }); - Kotlin.ArrayIterator = Class.create(Kotlin.Iterator, { - initialize:function (array) { + Kotlin.ArrayIterator = Kotlin.$createClass(Kotlin.Iterator, { + initialize: function (array) { this.array = array; this.index = 0; }, - next:function () { + next: function () { return this.array.get(this.index++); }, - hasNext:function () { - return (this.array.size() > this.index); - }, - get_hasNext:function () { - return this.hasNext(); + get_hasNext: function () { + return this.array.size() > this.index; } }); - - Kotlin.RangeIterator = Kotlin.Class.create(Kotlin.Iterator, { + Kotlin.RangeIterator = Kotlin.$createClass(Kotlin.Iterator, { initialize:function (start, count, reversed) { this.$start = start; this.$count = count; @@ -525,14 +244,13 @@ var Kotlin; this.set_i(this.get_i() + 1); return this.get_i() - 1; } - }, hasNext:function () { + }, + get_hasNext: function () { return this.get_count() > 0; - }, get_hasNext:function () { - return this.hasNext(); } }); - Kotlin.NumberRange = Kotlin.Class.create({initialize:function (start, size, reversed) { + Kotlin.NumberRange = Kotlin.$createClass({initialize:function (start, size, reversed) { this.$start = start; this.$size = size; this.$reversed = reversed; @@ -552,25 +270,23 @@ var Kotlin; return number >= this.get_start() && number < this.get_start() + this.get_size(); } }, iterator:function () { - return new Kotlin.RangeIterator(this.get_start(), this.get_size(), this.get_reversed()); + return Kotlin.$new(Kotlin.RangeIterator)(this.get_start(), this.get_size(), this.get_reversed()); } }); - Kotlin.Comparator = Kotlin.Class.create( - { - initialize:function () { - }, - compare:function (el1, el2) { - throw new Kotlin.AbstractFunctionInvocationError(); - } + Kotlin.Comparator = Kotlin.$createClass( + { + initialize: function () { + }, + compare: function (el1, el2) { + throw Kotlin.$new(Kotlin.AbstractFunctionInvocationError)(); } + } ); Kotlin.comparator = function (f) { - var result = new Kotlin.Comparator(); - result.compare = function (el1, el2) { - return f(el1, el2); - }; + var result = Kotlin.$new(Kotlin.Comparator)(); + result.compare = f; return result; }; @@ -581,7 +297,7 @@ var Kotlin; throw Kotlin.Exception(); } var max = it.next(); - while (it.hasNext()) { + while (it.get_hasNext()) { var el = it.next(); if (comp.compare(max, el) < 0) { max = el; @@ -590,7 +306,7 @@ var Kotlin; return max; }; - Kotlin.StringBuilder = Kotlin.Class.create( + Kotlin.StringBuilder = Kotlin.$createClass( { initialize:function () { this.string = ""; @@ -627,31 +343,28 @@ var Kotlin; }; Kotlin.arrayIndices = function (arr) { - return new Kotlin.NumberRange(0, arr.length); + return Kotlin.$new(Kotlin.NumberRange)(0, arr.length); }; - var intrinsicArrayIterator = Kotlin.Class.create( - Kotlin.Iterator, - { - initialize:function (arr) { - this.arr = arr; - this.len = arr.length; - this.i = 0; - }, - hasNext:function () { - return (this.i < this.len); - }, - next:function () { - return this.arr[this.i++]; - }, - get_hasNext:function () { - return this.hasNext(); - } + var intrinsicArrayIterator = Kotlin.$createClass( + Kotlin.Iterator, + { + initialize: function (arr) { + this.arr = arr; + this.len = arr.length; + this.i = 0; + }, + next: function () { + return this.arr[this.i++]; + }, + get_hasNext: function () { + return this.i < this.len; } + } ); Kotlin.arrayIterator = function (arr) { - return new intrinsicArrayIterator(arr); + return Kotlin.$new(intrinsicArrayIterator)(arr); }; Kotlin.toString = function (obj) { @@ -975,7 +688,7 @@ var Kotlin; this.values = function() { var values = this._values(); var i = values.length - var result = new Kotlin.ArrayList(); + var result = Kotlin.$new(Kotlin.ArrayList)(); while (--i) { result.add(values[i]); } @@ -1047,7 +760,7 @@ var Kotlin; }; this.keySet = function () { - var res = new Kotlin.HashSet(); + var res = Kotlin.$new(Kotlin.HashSet)(); var keys = this._keys(); var i = keys.length; while (i--) { @@ -1060,7 +773,7 @@ var Kotlin; Kotlin.HashTable = Hashtable; })(); - Kotlin.HashMap = Kotlin.Class.create( + Kotlin.HashMap = Kotlin.$createClass( { initialize:function () { Kotlin.HashTable.call(this); @@ -1089,13 +802,7 @@ var Kotlin; }; this.iterator = function () { - var list = new Kotlin.ArrayList(); - var values = this.values(); - var i = values.length; - while (i--) { - list.add(values[i]); - } - return list.iterator(); + return Kotlin.arrayIterator(this.values()); }; this.remove = function (o) { @@ -1159,13 +866,8 @@ var Kotlin; }; } - Kotlin.HashSet = Kotlin.Class.create( - { - initialize:function () { - HashSet.call(this); - } - } - ); + Kotlin.HashSet = Kotlin.$createClass({initialize: function () { + HashSet.call(this); + }}); }()); - })(); diff --git a/js/js.translator/testFiles/kotlin_lib_ecma3.js b/js/js.translator/testFiles/kotlin_lib_ecma3.js new file mode 100644 index 00000000000..78f5df321b0 --- /dev/null +++ b/js/js.translator/testFiles/kotlin_lib_ecma3.js @@ -0,0 +1,262 @@ +/** + * Copyright 2010 Tim Down. + * + * 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. + */ + +/* Prototype JavaScript framework, version 1.6.1 + * (c) 2005-2009 Sam Stephenson + * + * Prototype is freely distributable under the terms of an MIT-style license. + * For details, see the Prototype web site: http://www.prototypejs.org/ + * + *--------------------------------------------------------------------------*/ +var Kotlin = {}; + +(function () { + "use strict"; + var emptyFunction = function () { + }; + + function $A(iterable) { + if (!iterable) return []; + if ('toArray' in Object(iterable)) return iterable.toArray(); + var length = iterable.length || 0, results = new Array(length); + while (length--) results[length] = iterable[length]; + return results; + } + + (function () { + function extend(destination, source) { + for (var property in source) { + destination[property] = source[property]; + } + return destination; + } + + function keys(object) { + var results = []; + for (var property in object) { + if (object.hasOwnProperty(property)) { + results.push(property); + } + } + return results; + } + + function values(object) { + var results = []; + for (var property in object) { + results.push(object[property]); + } + return results; + } + + extend(Object, { + extend: extend, + keys: Object.keys || keys, + values: values + }); + })(); + + Object.extend(Function.prototype, (function () { + var slice = Array.prototype.slice; + + function update(array, args) { + var arrayLength = array.length, length = args.length; + while (length--) array[arrayLength + length] = args[length]; + return array; + } + + function merge(array, args) { + array = slice.call(array, 0); + return update(array, args); + } + + function argumentNames() { + var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1] + .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '') + .replace(/\s+/g, '').split(','); + return names.length == 1 && !names[0] ? [] : names; + } + + function bind(context) { + if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; + var __method = this, args = slice.call(arguments, 1); + return function () { + var a = merge(args, arguments); + return __method.apply(context, a); + }; + } + + function bindAsEventListener(context) { + var __method = this, args = slice.call(arguments, 1); + return function (event) { + var a = update([event || window.event], args); + return __method.apply(context, a); + }; + } + + function wrap(wrapper) { + var __method = this; + return function () { + var a = update([__method.bind(this)], arguments); + return wrapper.apply(this, a); + }; + } + + return { + argumentNames: argumentNames, + bind: bind, + bindAsEventListener: bindAsEventListener, + wrap: wrap + }; + })()); + + Kotlin.isType = function (object, klass) { + if (object === null) { + return false; + } + + var current = object.get_class(); + while (current !== klass) { + if (current === null) { + return false; + } + current = current.superclass; + } + return true; + }; + + Kotlin.createTrait = (function () { + function add(object, source) { + var properties = Object.keys(source); + for (var i = 0, length = properties.length; i < length; i++) { + var property = properties[i]; + object[property] = source[property]; + } + return this; + } + + return function () { + var result = {}; + for (var i = 0, length = arguments.length; i < length; i++) { + add(result, arguments[i]); + } + return result; + } + })(); + + Kotlin.createNamespace = function () { + return Kotlin.createTrait.apply(null, arguments); + }; + + Kotlin.createClass = (function () { + var METHODS = {addMethods: addMethods}; + + function subclass() { + } + + function create() { + var parent = null, properties = $A(arguments); + if (typeof (properties[0]) == "function") { + parent = properties.shift(); + } + + function klass() { + this.initializing = klass; + if (this.initialize) { + this.initialize.apply(this, arguments); + } + } + + Object.extend(klass, METHODS); + klass.superclass = parent; + klass.subclasses = []; + + if (parent) { + subclass.prototype = parent.prototype; + klass.prototype = new subclass(); + parent.subclasses.push(klass); + } + + klass.addMethods( + { + get_class: function () { + return klass; + } + }); + + if (parent !== null) { + klass.addMethods( + { + super_init: function () { + this.initializing = this.initializing.superclass; + this.initializing.prototype.initialize.apply(this, arguments); + } + }); + } + + for (var i = 0, length = properties.length; i < length; i++) { + klass.addMethods(properties[i]); + } + + if (!klass.prototype.initialize) { + klass.prototype.initialize = emptyFunction; + } + + klass.prototype.constructor = klass; + return klass; + } + + function addMethods(source) { + var ancestor = this.superclass && this.superclass.prototype, + properties = Object.keys(source); + + + for (var i = 0, length = properties.length; i < length; i++) { + var property = properties[i], value = source[property]; + if (ancestor && (typeof (value) == "function") && + value.argumentNames()[0] == "$super") { + var method = value; + value = (function (m) { + return function () { + return ancestor[m].apply(this, arguments); + }; + })(property).wrap(method); + + } + this.prototype[property] = value; + } + + return this; + } + + return create; + })(); + + Kotlin.$createClass = Kotlin.createClass; + + Kotlin.$new = function (f) { + var o = {'__proto__': f.prototype}; + return function () { + f.apply(o, arguments); + return o; + }; + }; + + Kotlin.createObject = function () { + var singletonClass = Kotlin.createClass.apply(null, arguments); + return new singletonClass(); + }; +})(); diff --git a/js/js.translator/testFiles/kotlin_lib_ecma5.js b/js/js.translator/testFiles/kotlin_lib_ecma5.js new file mode 100644 index 00000000000..65272d9fac9 --- /dev/null +++ b/js/js.translator/testFiles/kotlin_lib_ecma5.js @@ -0,0 +1,171 @@ +// Be aware — Google Chrome has serious issue — you can rewrite READ-ONLY property (if it is defined in prototype). Firefox and Safari work correct. +// Always test property access issues in Firefox, but not in Chrome. + +var Kotlin = {}; + +(function () { + "use strict"; + + Kotlin.isType = function (object, klass) { + if (object === null) { + return false; + } + + var proto = Object.getPrototypeOf(object); + // todo test nested class + //noinspection RedundantIfStatementJS + if (proto == klass.proto) { + return true; + } + + return false; + }; + + // todo compatibility for opera https://raw.github.com/gist/1000718/es5compat-gs.js + // proto must be created for class even if it is not needed (requires for is operator) + Kotlin.createClass = (function () { + function create(bases, initializer, properties) { + var proto; + var baseInitializer = null; + var isTrait = initializer == null; + if (!bases) { + proto = !properties && isTrait ? null : Object.create(null, properties || undefined); + } + else if (!Array.isArray(bases)) { + baseInitializer = bases.initializer; + proto = !properties && isTrait ? bases.proto : Object.create(bases.proto, properties || undefined); + } + else { + proto = computeProto(bases, properties); + // first is superclass, other are traits + baseInitializer = bases[0].initializer; + // all bases are traits without properties + if (proto == null && !isTrait) { + proto = Object.create(null, properties || undefined); + } + } + + var constructor = createConstructor(proto, initializer); + Object.defineProperty(constructor, "proto", {value: proto}); + Object.defineProperty(constructor, "properties", {value: properties || null}); + // null for trait + if (!isTrait) { + Object.defineProperty(constructor, "initializer", {value: initializer}); + + Object.defineProperty(initializer, "baseInitializer", {value: baseInitializer}); + Object.seal(initializer); + } + + Object.seal(constructor); + return constructor; + } + + // as separate function to reduce scope + function createConstructor(proto, initializer) { + return function () { + var o = Object.create(proto); + if (initializer != null) { + initializer.apply(o, arguments); + } + if (initializer == null || !initializer.hasOwnProperty("skipSeal")) { + Object.seal(o); + } + return o; + }; + } + + function computeProto(bases, properties) { + var proto = null; + for (var i = 0, n = bases.length; i < n; i++) { + var base = bases[i]; + var baseProto = base.proto; + if (baseProto == null || base.properties == null) { + continue; + } + + if (!proto) { + proto = Object.create(baseProto, properties || undefined); + continue; + } + + // chrome bug related to getOwnPropertyDescriptor (sometimes returns undefined), so, we keep properties + //var names = Object.getOwnPropertyNames(baseProto); + //for (var j = 0, k = names.length; j < k; j++) { + // var descriptor = Object.getOwnPropertyDescriptor(baseProto, names[i]); + // Object.defineProperty(proto, names[i], descriptor); + //} + Object.defineProperties(proto, base.properties); + + // todo test A -> B, C(->D) *properties from D is not yet added to proto* + } + + return proto; + } + + return create; + })(); + + Kotlin.createObject = function (initializer, properties) { + var o = Object.create(null, properties || undefined); + initializer.call(o); + return o; + }; + + Kotlin.createNamespace = function (initializer, properties, classesAndNestedNamespaces) { + var o = Object.create(null, properties || undefined); + Object.defineProperty(o, "initialize", {value: initializer}); + var keys = Object.keys(classesAndNestedNamespaces); + for (var i = 0, n = keys.length; i < n; i++) { + var name = keys[i]; + Object.defineProperty(o, name, {value: classesAndNestedNamespaces[name]}); + } + return o; + }; + + Kotlin.$new = function (f) { + return f; + }; + + Kotlin.$createClass = function (parent, properties) { + if (typeof (parent) != "function") { + properties = parent; + parent = null; + } + + var initializer = null; + var descriptors = properties ? {} : null; + if (descriptors != null) { + var ownPropertyNames = Object.getOwnPropertyNames(properties); + for (var i = 0, n = ownPropertyNames.length; i < n; i++) { + var name = ownPropertyNames[i]; + var value = properties[name]; + if (name == "initialize") { + initializer = value; + } + else if (name.indexOf("get_") === 0) { + // our std lib contains collision: hasNext property vs hasNext as function, we prefer function (actually, it does work) + var getterName = name.substring(4); + if (!descriptors.hasOwnProperty(getterName)) { + descriptors[getterName] = {get: value}; + descriptors[name] = {value: value}; + } + } + else if (name.indexOf("set_") === 0) { + descriptors[name.substring(4)] = {set: value}; + // std lib code can refers to + descriptors[name] = {value: value}; + } + else { + // we assume all our std lib functions are open + descriptors[name] = {value: value, writable: true}; + } + } + } + + if (initializer) { + Object.defineProperty(initializer, "skipSeal", {value: true}); + } + + return Kotlin.createClass(parent || null, initializer, descriptors); + }; +})(); diff --git a/js/js.translator/testFiles/propertyAccess/cases/initInstanceProperties.kt b/js/js.translator/testFiles/propertyAccess/cases/initInstanceProperties.kt new file mode 100644 index 00000000000..4bff8d97a43 --- /dev/null +++ b/js/js.translator/testFiles/propertyAccess/cases/initInstanceProperties.kt @@ -0,0 +1,12 @@ +package foo + +class Test() { + val a : Int = 100 + var b : Int = a + val c : Int = a + b +} + +fun box() : Boolean { + val test = Test() + return (100 == test.a && 100 == test.b && 200 == test.c) +} diff --git a/js/js.translator/testFiles/test.html b/js/js.translator/testFiles/test.html new file mode 100644 index 00000000000..9ad9246f5a5 --- /dev/null +++ b/js/js.translator/testFiles/test.html @@ -0,0 +1,13 @@ + + + + + + + + + + +