diff --git a/js/js.libraries/src/core/annotations.kt b/js/js.libraries/src/core/annotations.kt index adafe8c4aa9..67dba0140cb 100644 --- a/js/js.libraries/src/core/annotations.kt +++ b/js/js.libraries/src/core/annotations.kt @@ -3,4 +3,6 @@ package js; native annotation class native(name : String = "") {} native -annotation class library(name : String = "") {} \ No newline at end of file +annotation class library(name : String = "") {} +native +annotation class enumerable() {} \ No newline at end of file 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 1e01ecba839..3f602c95099 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,10 +16,14 @@ package org.jetbrains.k2js.test.semantics; +import com.google.common.collect.Lists; +import org.jetbrains.annotations.NotNull; import org.jetbrains.k2js.config.EcmaVersion; import org.jetbrains.k2js.test.SingleFileTranslationTest; +import org.jetbrains.k2js.test.utils.JsTestUtils; import java.util.EnumSet; +import java.util.List; /** * @author Pavel Talanov @@ -79,4 +83,18 @@ public final class PropertyAccessTest extends SingleFileTranslationTest { public void testInitInstanceProperties() throws Exception { fooBoxTest(EnumSet.of(EcmaVersion.v5)); } + + public void testEnumerable() throws Exception { + fooBoxTest(JsTestUtils.successOnEcmaV5()); + } + + @Override + @NotNull + protected List additionalJSFiles(@NotNull EcmaVersion ecmaVersion) { + List result = Lists.newArrayList(super.additionalJSFiles(ecmaVersion)); + if (getName().equals("testEnumerable")) { + result.add(pathToTestFiles() + "enumerate.js"); + } + return result; + } } 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 dd103c1a1b0..2f3165fc4e2 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 @@ -24,6 +24,7 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; +import java.util.EnumSet; import java.util.List; /** @@ -34,6 +35,11 @@ public final class JsTestUtils { private JsTestUtils() { } + @NotNull + public static EnumSet successOnEcmaV5() { + return EnumSet.of(EcmaVersion.v5); + } + @NotNull public static String convertFileNameToDotJsFile(@NotNull String filename, @NotNull EcmaVersion ecmaVersion) { String postFix = "_" + ecmaVersion.toString() + ".js"; 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 52da0995874..61499a1b728 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 @@ -122,6 +122,9 @@ public final class Namer { @NotNull private final JsPropertyInitializer writablePropertyDescriptorField; + @NotNull + private final JsPropertyInitializer enumerablePropertyDescriptorField; + private Namer(@NotNull JsScope rootScope) { kotlinName = rootScope.declareName(KOTLIN_OBJECT_NAME); kotlinScope = new JsScope(rootScope, "Kotlin standard object"); @@ -132,7 +135,9 @@ public final class Namer { isTypeName = kotlinScope.declareName("isType"); - writablePropertyDescriptorField = new JsPropertyInitializer(new JsNameRef("writable"), rootScope.getProgram().getTrueLiteral()); + JsProgram program = rootScope.getProgram(); + writablePropertyDescriptorField = new JsPropertyInitializer(program.getStringLiteral("writable"), program.getTrueLiteral()); + enumerablePropertyDescriptorField = new JsPropertyInitializer(program.getStringLiteral("enumerable"), program.getTrueLiteral()); } @NotNull @@ -190,6 +195,11 @@ public final class Namer { return writablePropertyDescriptorField; } + @NotNull + public JsPropertyInitializer enumerablePropertyDescriptorField() { + return enumerablePropertyDescriptorField; + } + @NotNull /*package*/ JsScope getKotlinScope() { return kotlinScope; 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 683b7427ce1..73a973e089a 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 @@ -71,10 +71,9 @@ public final class DeclarationBodyVisitor extends TranslatorVisitor _enumerate(o:T):T = noImpl + +native +fun _findFirst(o:Any):T = noImpl + +enumerable +class Test() { + val a:Int = 100 + val b:String = "s" +} + +class P() { + enumerable + val a:Int = 100 + val b:String = "s" +} + +fun box():Boolean { + val test = _enumerate(Test()) + val p = _enumerate(P()) + return (100 == test.a && "s" == test.b) && p.a == 100 && _findFirst(object {val test = 100}) == 100; +} diff --git a/js/js.translator/testFiles/propertyAccess/enumerate.js b/js/js.translator/testFiles/propertyAccess/enumerate.js new file mode 100644 index 00000000000..d8c8d0491d7 --- /dev/null +++ b/js/js.translator/testFiles/propertyAccess/enumerate.js @@ -0,0 +1,13 @@ +function _enumerate(o) { + var r = {}; + for (var p in o) { + r[p] = o[p]; + } + return r; +} + +function _findFirst(o) { + for (var p in o) { + return o[p]; + } +}