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 76da1dd74ea..15514125405 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 @@ -134,6 +134,9 @@ public final class ClassDeclarationTranslator extends AbstractTranslator { } return; } + if (!vars.isEmpty() || !propertyInitializers.isEmpty()) { + throw new IllegalStateException(); // check, that all class generate as final class + } dummyFunction.setBody(new JsBlock(new JsVars(vars, true), new JsReturn(new JsObjectLiteral(propertyInitializers)))); classesVar.setInitExpression(new JsInvocation(dummyFunction)); @@ -215,7 +218,7 @@ public final class ClassDeclarationTranslator extends AbstractTranslator { @Nullable public JsNameRef getQualifiedReference(ClassDescriptor descriptor) { - if (descriptor.getModality() != Modality.FINAL) { + if (descriptor.getModality() != Modality.FINAL && false) { //noinspection ConstantConditions return classDescriptorToQualifiedLabel.get(descriptor, null); } @@ -226,7 +229,7 @@ public final class ClassDeclarationTranslator extends AbstractTranslator { public JsPropertyInitializer translate(@NotNull JetClassOrObject declaration, TranslationContext context) { ClassDescriptor descriptor = getClassDescriptor(context().bindingContext(), declaration); JsExpression value; - if (descriptor.getModality() == Modality.FINAL) { + if (descriptor.getModality() == Modality.FINAL || true) { value = new ClassTranslator(declaration, classDescriptorToQualifiedLabel, context).translate(); } else { 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 8f5732d0c1e..11b48d4dc1f 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 @@ -164,7 +164,7 @@ public final class ClassTranslator extends AbstractTranslator { }); } - invocationArguments.add(getSuperclassReferences()); + invocationArguments.add(getSuperclassReferences(declarationContext)); if (!isTrait()) { JsFunction initializer = new ClassInitializerTranslator(classDeclaration, declarationContext).generateInitializeMethod(); invocationArguments.add(initializer.getBody().getStatements().isEmpty() ? JsLiteral.NULL : initializer); @@ -214,16 +214,12 @@ public final class ClassTranslator extends AbstractTranslator { } } - private JsExpression getSuperclassReferences() { + private JsExpression getSuperclassReferences(@NotNull TranslationContext declarationContext) { List superClassReferences = getSupertypesNameReferences(); if (superClassReferences.isEmpty()) { return JsLiteral.NULL; - } - else if (superClassReferences.size() == 1) { - return superClassReferences.get(0); - } - else { - return new JsArrayLiteral(superClassReferences); + } else { + return simpleReturnFunction(declarationContext.scope(), new JsArrayLiteral(superClassReferences)); } } diff --git a/js/js.translator/testFiles/kotlinLib/cases/isAncestorType.js b/js/js.translator/testFiles/kotlinLib/cases/isAncestorType.js index 019bbb36316..a4694167c85 100644 --- a/js/js.translator/testFiles/kotlinLib/cases/isAncestorType.js +++ b/js/js.translator/testFiles/kotlinLib/cases/isAncestorType.js @@ -14,8 +14,8 @@ * limitations under the License. */ -var A = Kotlin.createClass(); -var B = Kotlin.createClass(A); +var A = Kotlin.createClassNow(); +var B = Kotlin.createClassNow(A); var b = new B; function test() { diff --git a/js/js.translator/testFiles/kotlinLib/cases/isComplexTest.js b/js/js.translator/testFiles/kotlinLib/cases/isComplexTest.js index 542c0012f1a..18ce4776603 100644 --- a/js/js.translator/testFiles/kotlinLib/cases/isComplexTest.js +++ b/js/js.translator/testFiles/kotlinLib/cases/isComplexTest.js @@ -14,27 +14,27 @@ * limitations under the License. */ -var A = Kotlin.createClass(); -var B = Kotlin.createClass(A); +var A = Kotlin.createClassNow(); +var B = Kotlin.createClassNow(A); var b = new B; -var C = Kotlin.createClass(B); +var C = Kotlin.createClassNow(B); var c = new C; -var E = Kotlin.createClass(A) +var E = Kotlin.createClassNow(A); var e = new E; var test1 = function() { - var b2 = b + var b2 = b; return (Kotlin.isType(b, A) && Kotlin.isType(b, B)); -} +}; var test2 = function() { return (Kotlin.isType(c, C) && Kotlin.isType(c, B) && Kotlin.isType(c, A) && (!Kotlin.isType(c, E))); -} +}; var test3 = function() { return Kotlin.isType(e, E) && !Kotlin.isType(e, B) && !Kotlin.isType(e, C) && Kotlin.isType(e, A) -} +}; var test = function() { return test1() && test2() && test3() -} +}; diff --git a/js/js.translator/testFiles/kotlinLib/cases/isNotOtherType.js b/js/js.translator/testFiles/kotlinLib/cases/isNotOtherType.js index 11d886b7581..bbb008e27d3 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.createClass(); -var B = Kotlin.createClass(A); -var C = Kotlin.createClass(); +var A = Kotlin.createClassNow(); +var B = Kotlin.createClassNow(A); +var C = Kotlin.createClassNow(); var c = new C; test = function() { - return ((!isType(c, A)) && !isType(c, B)); -} + return ((!Kotlin.isType(c, A)) && !Kotlin.isType(c, B)); +}; diff --git a/js/js.translator/testFiles/kotlinLib/cases/isSameType.js b/js/js.translator/testFiles/kotlinLib/cases/isSameType.js index 612ed1460d2..4d0303f2cee 100644 --- a/js/js.translator/testFiles/kotlinLib/cases/isSameType.js +++ b/js/js.translator/testFiles/kotlinLib/cases/isSameType.js @@ -14,7 +14,7 @@ * limitations under the License. */ -var A = Kotlin.createClass(); +var A = Kotlin.createClassNow(); var a = new A(); function test() { diff --git a/js/js.translator/testFiles/kotlinLib/cases/namespaceWithClasses.js b/js/js.translator/testFiles/kotlinLib/cases/namespaceWithClasses.js index 3a1e2ad8b8f..6d0f8e88180 100644 --- a/js/js.translator/testFiles/kotlinLib/cases/namespaceWithClasses.js +++ b/js/js.translator/testFiles/kotlinLib/cases/namespaceWithClasses.js @@ -16,7 +16,7 @@ { var items = function () { - var A = Kotlin.createClass(null, + var A = Kotlin.createClassNow(null, function $fun() { this.$order = ''; { @@ -31,13 +31,13 @@ return this.$order; } }); - var B = Kotlin.createClass(A, function $fun() { + var B = Kotlin.createClassNow(A, function $fun() { $fun.baseInitializer.call(this); { this.set_order(this.get_order() + 'B'); } }); - var C = Kotlin.createClass(B, function $fun() { + var C = Kotlin.createClassNow(B, function $fun() { $fun.baseInitializer.call(this); { this.set_order(this.get_order() + 'C'); diff --git a/js/js.translator/testFiles/kotlin_lib.js b/js/js.translator/testFiles/kotlin_lib.js index 63ff1646dd7..220248e1375 100644 --- a/js/js.translator/testFiles/kotlin_lib.js +++ b/js/js.translator/testFiles/kotlin_lib.js @@ -72,13 +72,13 @@ String.prototype.contains = function (s) { Kotlin.modules = {}; - Kotlin.RuntimeException = Kotlin.createClass(); - Kotlin.NullPointerException = Kotlin.createClass(); - Kotlin.NoSuchElementException = Kotlin.createClass(); - Kotlin.IllegalArgumentException = Kotlin.createClass(); - Kotlin.IllegalStateException = Kotlin.createClass(); - Kotlin.UnsupportedOperationException = Kotlin.createClass(); - Kotlin.IOException = Kotlin.createClass(); + Kotlin.RuntimeException = Kotlin.createClassNow(); + Kotlin.NullPointerException = Kotlin.createClassNow(); + Kotlin.NoSuchElementException = Kotlin.createClassNow(); + Kotlin.IllegalArgumentException = Kotlin.createClassNow(); + Kotlin.IllegalStateException = Kotlin.createClassNow(); + Kotlin.UnsupportedOperationException = Kotlin.createClassNow(); + Kotlin.IOException = Kotlin.createClassNow(); Kotlin.throwNPE = function () { throw new Kotlin.NullPointerException(); @@ -96,12 +96,12 @@ String.prototype.contains = function (s) { }; } - Kotlin.Iterator = Kotlin.createClass(null, null, { + Kotlin.Iterator = Kotlin.createClassNow(null, null, { next: throwAbstractFunctionInvocationError("Iterator#next"), hasNext: throwAbstractFunctionInvocationError("Iterator#hasNext") }); - var ArrayIterator = Kotlin.createClass(Kotlin.Iterator, + var ArrayIterator = Kotlin.createClassNow(Kotlin.Iterator, function (array) { this.array = array; this.size = array.length; @@ -115,7 +115,7 @@ String.prototype.contains = function (s) { } }); - var ListIterator = Kotlin.createClass(ArrayIterator, + var ListIterator = Kotlin.createClassNow(ArrayIterator, function (list) { this.list = list; this.size = list.size(); @@ -126,9 +126,9 @@ String.prototype.contains = function (s) { } }); - Kotlin.Collection = Kotlin.createClass(); + Kotlin.Collection = Kotlin.createClassNow(); - Kotlin.Enum = Kotlin.createClass(null, + Kotlin.Enum = Kotlin.createClassNow(null, function () { this.name$ = undefined; this.ordinal$ = undefined; @@ -170,13 +170,13 @@ String.prototype.contains = function (s) { }; })(); - Kotlin.PropertyMetadata = Kotlin.createClass(null, + Kotlin.PropertyMetadata = Kotlin.createClassNow(null, function(name) { this.name = name; } ); - Kotlin.AbstractCollection = Kotlin.createClass(Kotlin.Collection, null, { + Kotlin.AbstractCollection = Kotlin.createClassNow(Kotlin.Collection, null, { size: function () { return this.$size; }, @@ -229,7 +229,7 @@ String.prototype.contains = function (s) { } }); - Kotlin.AbstractList = Kotlin.createClass(Kotlin.AbstractCollection, null, { + Kotlin.AbstractList = Kotlin.createClassNow(Kotlin.AbstractCollection, null, { iterator: function () { return new ListIterator(this); }, @@ -245,7 +245,7 @@ String.prototype.contains = function (s) { }); //TODO: should be JS Array-like (https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Predefined_Core_Objects#Working_with_Array-like_objects) - Kotlin.ArrayList = Kotlin.createClass(Kotlin.AbstractList, + Kotlin.ArrayList = Kotlin.createClassNow(Kotlin.AbstractList, function () { this.array = []; this.$size = 0; @@ -313,19 +313,19 @@ String.prototype.contains = function (s) { } }); - Kotlin.Runnable = Kotlin.createClass(null, null, { + Kotlin.Runnable = Kotlin.createClassNow(null, null, { run: throwAbstractFunctionInvocationError("Runnable#run") }); - Kotlin.Comparable = Kotlin.createClass(null, null, { + Kotlin.Comparable = Kotlin.createClassNow(null, null, { compareTo: throwAbstractFunctionInvocationError("Comparable#compareTo") }); - Kotlin.Appendable = Kotlin.createClass(null, null, { + Kotlin.Appendable = Kotlin.createClassNow(null, null, { append: throwAbstractFunctionInvocationError("Appendable#append") }); - Kotlin.Closeable = Kotlin.createClass(null, null, { + Kotlin.Closeable = Kotlin.createClassNow(null, null, { close: throwAbstractFunctionInvocationError("Closeable#close") }); @@ -397,7 +397,7 @@ String.prototype.contains = function (s) { Kotlin.System.out().print(s); }; - Kotlin.RangeIterator = Kotlin.createClass(Kotlin.Iterator, + Kotlin.RangeIterator = Kotlin.createClassNow(Kotlin.Iterator, function (start, end, increment) { this.start = start; this.end = end; @@ -414,7 +414,7 @@ String.prototype.contains = function (s) { } }); - Kotlin.NumberRange = Kotlin.createClass(null, + Kotlin.NumberRange = Kotlin.createClassNow(null, function (start, end) { this.start = start; this.end = end; @@ -428,7 +428,7 @@ String.prototype.contains = function (s) { } }); - Kotlin.Progression = Kotlin.createClass(null, + Kotlin.Progression = Kotlin.createClassNow(null, function (start, end, increment) { this.start = start; this.end = end; @@ -439,11 +439,11 @@ String.prototype.contains = function (s) { } }); - Kotlin.Comparator = Kotlin.createClass(null, null, { + Kotlin.Comparator = Kotlin.createClassNow(null, null, { compare: throwAbstractFunctionInvocationError("Comparator#compare") }); - var ComparatorImpl = Kotlin.createClass(Kotlin.Comparator, + var ComparatorImpl = Kotlin.createClassNow(Kotlin.Comparator, function (comparator) { this.compare = comparator; } @@ -504,7 +504,7 @@ String.prototype.contains = function (s) { }; - Kotlin.StringBuilder = Kotlin.createClass(null, + Kotlin.StringBuilder = Kotlin.createClassNow(null, function () { this.string = ""; }, { diff --git a/js/js.translator/testFiles/kotlin_lib_ecma5.js b/js/js.translator/testFiles/kotlin_lib_ecma5.js index cda0378616a..332f9860810 100644 --- a/js/js.translator/testFiles/kotlin_lib_ecma5.js +++ b/js/js.translator/testFiles/kotlin_lib_ecma5.js @@ -117,7 +117,8 @@ var Kotlin = {}; Kotlin.TYPE = { CLASS: "class", TRAIT: "trait", - OBJECT: "object" + OBJECT: "object", + INIT_FUN: "init fun" }; Kotlin.classCount = 0; @@ -185,7 +186,7 @@ var Kotlin = {}; return object; } - Kotlin.createClass = function (bases, constructor, properties, staticProperties) { + Kotlin.createClassNow = function (bases, constructor, properties, staticProperties) { if (constructor == null) { constructor = emptyFunction(); } @@ -214,8 +215,8 @@ var Kotlin = {}; return constructor; }; - Kotlin.createObject = function (bases, constructor, functions) { - var noNameClass = Kotlin.createClass(bases, constructor, functions); + Kotlin.createObjectNow = function (bases, constructor, functions) { + var noNameClass = Kotlin.createClassNow(bases, constructor, functions); var obj = new noNameClass(); obj.$metadata$ = { type: Kotlin.TYPE.OBJECT @@ -223,7 +224,7 @@ var Kotlin = {}; return obj; }; - Kotlin.createTrait = function (bases, properties, staticProperties) { + Kotlin.createTraitNow = function (bases, properties, staticProperties) { var obj = function () {}; copyProperties(obj, staticProperties); @@ -237,6 +238,38 @@ var Kotlin = {}; return obj; }; + function getBases(basesFun) { + if (typeof basesFun === "function") { + return basesFun(); + } else { + return basesFun; + } + } + + Kotlin.createClass = function (basesFun, constructor, properties, staticProperties) { + function $o() { + var klass = Kotlin.createClassNow(getBases(basesFun), constructor, properties, staticProperties); + Object.defineProperty(this, $o.className, {value: klass}); + return klass; + } + $o.type = Kotlin.TYPE.INIT_FUN; + return $o; + }; + + Kotlin.createTrait = function (basesFun, properties, staticProperties) { + function $o() { + var klass = Kotlin.createTraitNow(getBases(basesFun), properties, staticProperties); + Object.defineProperty(this, $o.className, {value: klass}); + return klass; + } + $o.type = Kotlin.TYPE.INIT_FUN; + return $o; + }; + + Kotlin.createObject = function (basesFun, constructor, functions) { + return Kotlin.createObjectNow(getBases(basesFun), constructor, functions); + }; + Kotlin.callGetter = function(thisObject, klass, propertyName) { return klass.$metadata$.properties[propertyName].get.call(thisObject); }; @@ -303,7 +336,15 @@ var Kotlin = {}; for (var p in members) { if (members.hasOwnProperty(p)) { if ((typeof members[p]) === "function") { - definition[p] = members[p]; + if (members[p].type === Kotlin.TYPE.INIT_FUN) { + members[p].className = p; + Object.defineProperty(definition, p, { + get: members[p], + configurable: true + }); + } else { + definition[p] = members[p]; + } } else { Object.defineProperty(definition, p, members[p]); } diff --git a/js/js.translator/testFiles/maps.js b/js/js.translator/testFiles/maps.js index 4e5c08473eb..e2556d7a769 100644 --- a/js/js.translator/testFiles/maps.js +++ b/js/js.translator/testFiles/maps.js @@ -385,9 +385,9 @@ Kotlin.HashTable = Hashtable; })(); -Kotlin.Map = Kotlin.createClass(); +Kotlin.Map = Kotlin.createClassNow(); -Kotlin.HashMap = Kotlin.createClass(Kotlin.Map, +Kotlin.HashMap = Kotlin.createClassNow(Kotlin.Map, function () { Kotlin.HashTable.call(this); } @@ -396,7 +396,7 @@ Kotlin.HashMap = Kotlin.createClass(Kotlin.Map, Kotlin.ComplexHashMap = Kotlin.HashMap; (function () { - var PrimitiveHashMapValuesIterator = Kotlin.createClass(Kotlin.Iterator, + var PrimitiveHashMapValuesIterator = Kotlin.createClassNow(Kotlin.Iterator, function (map, keys) { this.map = map; this.keys = keys; @@ -411,7 +411,7 @@ Kotlin.ComplexHashMap = Kotlin.HashMap; } }); - var PrimitiveHashMapValues = Kotlin.createClass(Kotlin.Collection, + var PrimitiveHashMapValues = Kotlin.createClassNow(Kotlin.Collection, function (map) { this.map = map; }, { @@ -426,7 +426,7 @@ Kotlin.ComplexHashMap = Kotlin.HashMap; } }); - Kotlin.PrimitiveHashMap = Kotlin.createClass(Kotlin.Map, + Kotlin.PrimitiveHashMap = Kotlin.createClassNow(Kotlin.Map, function () { this.$size = 0; this.map = {}; @@ -502,9 +502,9 @@ Kotlin.ComplexHashMap = Kotlin.HashMap; }); }()); -Kotlin.Set = Kotlin.createClass(Kotlin.Collection); +Kotlin.Set = Kotlin.createClassNow(Kotlin.Collection); -Kotlin.PrimitiveHashSet = Kotlin.createClass(Kotlin.AbstractCollection, +Kotlin.PrimitiveHashSet = Kotlin.createClassNow(Kotlin.AbstractCollection, function () { this.$size = 0; this.map = {}; @@ -662,7 +662,7 @@ Kotlin.PrimitiveHashSet = Kotlin.createClass(Kotlin.AbstractCollection, }; } - Kotlin.HashSet = Kotlin.createClass(Kotlin.Set, + Kotlin.HashSet = Kotlin.createClassNow(Kotlin.Set, function () { HashSet.call(this); } diff --git a/js/js.translator/testFiles/native/native/library.js b/js/js.translator/testFiles/native/native/library.js index c6d72ef61d8..a9e95d801cd 100644 --- a/js/js.translator/testFiles/native/native/library.js +++ b/js/js.translator/testFiles/native/native/library.js @@ -17,7 +17,7 @@ (function () { var c = 0; - Kotlin.A = Kotlin.createClass(null, + Kotlin.A = Kotlin.createClassNow(null, function () { this.f = function(i) { if (i === undefined && c === 0) {