diff --git a/js/js.libraries/src/core/javautil.kt b/js/js.libraries/src/core/javautil.kt index 9633f527eb8..9a64ea25e65 100644 --- a/js/js.libraries/src/core/javautil.kt +++ b/js/js.libraries/src/core/javautil.kt @@ -55,125 +55,77 @@ val Collections = object { list[i2] = tmp } } - - } library -public open class ArrayList() : java.util.List { - public override fun size() : Int = js.noImpl - public override fun isEmpty() : Boolean = js.noImpl - public override fun contains(o : Any?) : Boolean = js.noImpl - public override fun iterator() : Iterator = js.noImpl - // public override fun indexOf(o : Any?) : Int = js.noImpl - // public override fun lastIndexOf(o : Any?) : Int = js.noImpl - // public override fun toArray() : Array = js.noImpl - // public override fun toArray(a : Array) : Array = js.noImpl - public override fun get(index : Int) : E = js.noImpl - public override fun set(index : Int, element : E) : E = js.noImpl - public override fun add(e : E) : Boolean = js.noImpl - public override fun add(index : Int, element : E) : Unit = js.noImpl - library("removeByIndex") - public override fun remove(index : Int) : E = js.noImpl - public override fun remove(o : Any?) : Boolean = js.noImpl - public override fun clear() : Unit = js.noImpl - public override fun addAll(c : java.util.Collection) : Boolean = js.noImpl - // public override fun addAll(index : Int, c : java.util.Collection) : Boolean = js.noImpl -} - -library -public trait Collection : java.lang.Iterable { - open fun size() : Int - open fun isEmpty() : Boolean - open fun contains(o : Any?) : Boolean - override fun iterator() : java.util.Iterator - // open fun toArray() : Array - // open fun toArray(a : Array) : Array - open fun add(e : E) : Boolean - open fun remove(o : Any?) : Boolean +public trait Collection: Iterable { + open fun size(): Int + open fun isEmpty(): Boolean + open fun contains(o: Any?): Boolean + override fun iterator(): Iterator + fun toArray(): Array + // open fun toArray(a : Array) : Array + open fun add(e: E): Boolean + open fun remove(o: Any?): Boolean //open fun containsAll(c : java.util.Collection<*>) : Boolean - open fun addAll(c : java.util.Collection) : Boolean + open fun addAll(c: Collection): Boolean //open fun removeAll(c : java.util.Collection<*>) : Boolean //open fun retainAll(c : java.util.Collection<*>) : Boolean - open fun clear() : Unit + open fun clear(): Unit } library -public abstract open class AbstractCollection() : Collection { +public abstract class AbstractCollection() : Collection { + override fun toArray(): Array = js.noImpl + + override fun isEmpty(): Boolean = js.noImpl + override fun contains(o: Any?): Boolean = js.noImpl + override fun iterator(): Iterator = js.noImpl + + override fun add(e: E): Boolean = js.noImpl + override fun remove(o: Any?): Boolean = js.noImpl + + override fun addAll(c: Collection): Boolean = js.noImpl + + override fun clear(): Unit = js.noImpl + override fun size(): Int = js.noImpl } library -public abstract open class AbstractList() : AbstractCollection(), List { - public override fun isEmpty() : Boolean = js.noImpl - public override fun contains(o : Any?) : Boolean = js.noImpl - public override fun iterator() : Iterator = js.noImpl - // public override fun indexOf(o : Any?) : Int = js.noImpl - // public override fun lastIndexOf(o : Any?) : Int = js.noImpl - // public override fun toArray() : Array = js.noImpl - // public override fun toArray(a : Array) : Array = js.noImpl - public override fun set(index : Int, element : E) : E = js.noImpl - public override fun add(e : E) : Boolean = js.noImpl - public override fun add(index : Int, element : E) : Unit = js.noImpl - library("removeByIndex") - public override fun remove(index : Int) : E = js.noImpl - public override fun remove(o : Any?) : Boolean = js.noImpl - public override fun clear() : Unit = js.noImpl - public override fun addAll(c : java.util.Collection) : Boolean = js.noImpl - // public override fun addAll(index : Int, c : java.util.Collection) : Boolean = js.noImpl +public trait List: Collection { + fun get(index: Int): E + fun set(index: Int, element: E): E + + fun add(index: Int, element: E): Unit + fun remove(index: Int): E + + fun indexOf(o: E?): Int } library -public trait List : Collection { - override fun size() : Int - override fun isEmpty() : Boolean - override fun contains(o : Any?) : Boolean - override fun iterator() : java.util.Iterator - // override fun toArray() : Array - // Simulate Java's array covariance - // override fun toArray(a : Array) : Array - override fun add(e : E) : Boolean - override fun remove(o : Any?) : Boolean - // override fun containsAll(c : java.util.Collection<*>) : Boolean - override fun addAll(c : java.util.Collection) : Boolean - // open fun addAll(index : Int, c : java.util.Collection) : Boolean - // override fun removeAll(c : java.util.Collection<*>) : Boolean - // override fun retainAll(c : java.util.Collection<*>) : Boolean - override fun clear() : Unit - open fun get(index : Int) : E - open fun set(index : Int, element : E) : E - open fun add(index : Int, element : E) : Unit - open fun remove(index : Int) : E - // open fun indexOf(o : Any?) : Int - // open fun lastIndexOf(o : Any?) : Int +public abstract class AbstractList(): AbstractCollection(), List { + override fun get(index: Int): E = js.noImpl + override fun set(index: Int, element: E): E = js.noImpl + + library("addAt") + override fun add(index: Int, element: E): Unit = js.noImpl + + library("removeAt") + override fun remove(index: Int): E = js.noImpl + + override fun indexOf(o: E?): Int = js.noImpl +} + +library +public open class ArrayList() : AbstractList() { } library public trait Set : Collection { - override fun size() : Int - override fun isEmpty() : Boolean - override fun contains(o : Any?) : Boolean - override fun iterator() : java.util.Iterator - // override fun toArray() : Array - // override fun toArray(a : Array) : Array - override fun add(e : E) : Boolean - override fun remove(o : Any?) : Boolean - //override fun containsAll(c : java.util.Collection<*>) : Boolean - override fun addAll(c : java.util.Collection) : Boolean - //override fun retainAll(c : java.util.Collection<*>) : Boolean - //override fun removeAll(c : java.util.Collection<*>) : Boolean - override fun clear() : Unit } library -public open class HashSet() : java.util.Set { - public override fun iterator() : java.util.Iterator = js.noImpl - public override fun size() : Int = js.noImpl - public override fun isEmpty() : Boolean = js.noImpl - public override fun contains(o : Any?) : Boolean = js.noImpl - public override fun add(e : E) : Boolean = js.noImpl - public override fun remove(o : Any?) : Boolean = js.noImpl - public override fun clear() : Unit = js.noImpl - override fun addAll(c : java.util.Collection) : Boolean = js.noImpl +public open class HashSet(): AbstractCollection(), java.util.Set { } library @@ -220,22 +172,13 @@ public open class HashMap() : java.util.Map { } library -public open class LinkedList() : List { - public override fun iterator() : java.util.Iterator = js.noImpl - public override fun isEmpty() : Boolean = js.noImpl - public override fun contains(o : Any?) : Boolean = js.noImpl - public override fun size() : Int = js.noImpl - public override fun add(e : E) : Boolean = js.noImpl - public override fun remove(o : Any?) : Boolean = js.noImpl - public override fun addAll(c : java.util.Collection) : Boolean = js.noImpl - public override fun clear() : Unit = js.noImpl - public override fun get(index : Int) : E = js.noImpl - public override fun set(index : Int, element : E) : E = js.noImpl - public override fun add(index : Int, element : E) : Unit = js.noImpl - public override fun remove(index : Int) : E = js.noImpl - public fun poll() : E? = js.noImpl - public fun peek() : E? = js.noImpl - public fun offer(e : E) : Boolean = js.noImpl +public open class LinkedList(): AbstractList() { + public override fun get(index: Int): E = js.noImpl + public override fun set(index: Int, element: E): E = js.noImpl + public override fun add(index: Int, element: E): Unit = js.noImpl + public fun poll(): E? = js.noImpl + public fun peek(): E? = js.noImpl + public fun offer(e: E): Boolean = js.noImpl } library diff --git a/js/js.tests/test/org/jetbrains/k2js/test/semantics/ArrayListTest.java b/js/js.tests/test/org/jetbrains/k2js/test/semantics/ArrayListTest.java index 4a2f0b6ff1f..8f8551acee7 100644 --- a/js/js.tests/test/org/jetbrains/k2js/test/semantics/ArrayListTest.java +++ b/js/js.tests/test/org/jetbrains/k2js/test/semantics/ArrayListTest.java @@ -51,6 +51,10 @@ public final class ArrayListTest extends JavaClassesTest { fooBoxTest(); } + public void testToArray() throws Exception { + fooBoxTest(); + } + public void testIndexOOB() throws Exception { try { fooBoxTest(); diff --git a/js/js.translator/testFiles/java/arrayList/cases/toArray.kt b/js/js.translator/testFiles/java/arrayList/cases/toArray.kt new file mode 100644 index 00000000000..65da1d0d93f --- /dev/null +++ b/js/js.translator/testFiles/java/arrayList/cases/toArray.kt @@ -0,0 +1,13 @@ +package foo + +import java.util.ArrayList + +fun box() : Boolean { + var i = 0 + val list = ArrayList() + while (i++ < 3) { + list.add(i) + } + val array = list.toArray() + return array[0] == 1 && array[1] == 2 && array[2] == 3 +} \ No newline at end of file diff --git a/js/js.translator/testFiles/kotlin_lib.js b/js/js.translator/testFiles/kotlin_lib.js index 48a25bcf9fb..2722a7e4201 100644 --- a/js/js.translator/testFiles/kotlin_lib.js +++ b/js/js.translator/testFiles/kotlin_lib.js @@ -28,7 +28,7 @@ var kotlin = {set:function (receiver, key, value) { return obj1.equals(obj2); } } - return (obj1 === obj2); + return obj1 === obj2; }; Kotlin.modules = {}; @@ -48,117 +48,122 @@ var kotlin = {set:function (receiver, key, value) { throw Kotlin.$new(Kotlin.Exceptions.NullPointerException)(); }; - 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; - } - }); + function throwAbstractFunctionInvocationError() { + throw new TypeError("Function is abstract"); + } - Kotlin.ArrayList = Kotlin.$createClass({ - initialize:function () { - this.array = []; - this.$size = 0; + Kotlin.Iterator = Kotlin.$createClass({ + initialize: function () { }, - get:function (index) { - if ((index < 0) || (index >= this.$size)) { - throw Kotlin.Exceptions.IndexOutOfBounds; - } - return (this.array)[index]; + next: throwAbstractFunctionInvocationError, + get_hasNext: throwAbstractFunctionInvocationError + }); + + var ArrayIterator = Kotlin.$createClass(Kotlin.Iterator, { + initialize: function (array) { + this.array = array; + this.size = array.length; + this.index = 0; }, - set:function (index, value) { - if ((index < 0) || (index >= this.$size)) { - throw Kotlin.Exceptions.IndexOutOfBounds; - } - (this.array)[index] = value; + next: function () { + return this.array[this.index++]; }, - size:function () { - return this.$size; + get_hasNext: function () { + return this.index < this.size; + } + }); + + var ListIterator = Kotlin.$createClass(ArrayIterator, { + initialize: function (list) { + this.list = list; + this.size = list.size(); + this.index = 0; }, - iterator:function () { - return Kotlin.$new(Kotlin.ArrayIterator)(this); + next: function () { + return this.list.get(this.index++); }, - isEmpty:function () { - return (this.$size === 0); + get_hasNext: function () { + return this.index < this.size; + } + }); + + Kotlin.AbstractList = Kotlin.$createClass({ + iterator: function () { + return Kotlin.$new(ListIterator)(this); }, - add:function (element) { - this.array[this.$size++] = element; + isEmpty: function () { + return this.size() == 0; }, - addAll:function (collection) { + 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; - } + remove: function (o) { + var index = this.indexOf(o); + if (index != -1) { + this.removeAt(index); } }, - removeByIndex:function (index) { - for (var i = index; i < this.$size - 1; ++i) { - this.array[i] = this.array[i + 1]; - } - this.$size--; - }, - clear:function () { - this.array = []; - this.$size = 0; - }, - contains:function (obj) { - for (var i = 0; i < this.$size; ++i) { - if (Kotlin.equals(this.array[i], obj)) { - return true; - } - } - return false; + contains: function (o) { + return this.indexOf(o) != -1; } }); + Kotlin.ArrayList = Kotlin.$createClass(Kotlin.AbstractList, { + initialize: function () { + this.array = []; + this.$size = 0; + }, + get: function (index) { + if (index < 0 || index >= this.$size) { + throw Kotlin.Exceptions.IndexOutOfBounds; + } + return this.array[index]; + }, + set: function (index, value) { + if (index < 0 || index >= this.$size) { + throw Kotlin.Exceptions.IndexOutOfBounds; + } + this.array[index] = value; + }, + toArray: function () { + return this.array.slice(0, this.$size); + }, + size: function () { + return this.$size; + }, + iterator: function () { + return Kotlin.arrayIterator(this.array); + }, + add: function (element) { + this.array[this.$size++] = element; + }, + addAt: function (index, element) { + this.array.splice(index, 0, element); + }, + removeAt: function (index) { + this.array.splice(index, 1); + this.$size--; + }, + clear: function () { + this.array.length = 0; + this.$size = 0; + }, + indexOf: function (o) { + for (var i = 0, n = this.$size; i < n; ++i) { + if (Kotlin.equals(this.array[i], o)) { + return i; + } + } + return -1; + } + }); Kotlin.parseInt = function (str) { return parseInt(str, 10); - } - ; + }; Kotlin.safeParseInt = function(str) { var r = parseInt(str, 10); @@ -212,51 +217,32 @@ var kotlin = {set:function (receiver, key, value) { Kotlin.System.out().print(s); }; - Kotlin.AbstractFunctionInvocationError = Kotlin.$createClass(); - - Kotlin.Iterator = Kotlin.$createClass({ - initialize:function () { - }, - next:function () { - throw Kotlin.$new(Kotlin.AbstractFunctionInvocationError)(); - }, - get_hasNext:function () { - throw Kotlin.$new(Kotlin.AbstractFunctionInvocationError)(); - } - }); - - Kotlin.ArrayIterator = Kotlin.$createClass(Kotlin.Iterator, { - initialize: function (array) { - this.array = array; - this.index = 0; - }, - next: function () { - return this.array.get(this.index++); - }, - get_hasNext: function () { - return this.array.size() > this.index; - } - }); - Kotlin.RangeIterator = Kotlin.$createClass(Kotlin.Iterator, { - initialize:function (start, count, reversed) { + initialize: function (start, count, reversed) { this.$start = start; this.$count = count; this.$reversed = reversed; this.$i = this.get_start(); - }, get_start:function () { + }, + get_start: function () { return this.$start; - }, get_count:function () { + }, + get_count: function () { return this.$count; - }, set_count:function (tmp$0) { + }, + set_count: function (tmp$0) { this.$count = tmp$0; - }, get_reversed:function () { + }, + get_reversed: function () { return this.$reversed; - }, get_i:function () { + }, + get_i: function () { return this.$i; - }, set_i:function (tmp$0) { + }, + set_i: function (tmp$0) { this.$i = tmp$0; - }, next:function () { + }, + next: function () { this.set_count(this.get_count() - 1); if (this.get_reversed()) { this.set_i(this.get_i() - 1); @@ -272,46 +258,48 @@ var kotlin = {set:function (receiver, key, value) { } }); - Kotlin.NumberRange = Kotlin.$createClass({initialize:function (start, size, reversed) { - this.$start = start; - this.$size = size; - this.$reversed = reversed; - }, get_start:function () { - return this.$start; - }, get_size:function () { - return this.$size; - }, get_reversed:function () { - return this.$reversed; - }, get_end:function () { - return this.get_reversed() ? this.get_start() - this.get_size() + 1 : this.get_start() + this.get_size() - 1; - }, contains:function (number) { - if (this.get_reversed()) { - return number <= this.get_start() && number > this.get_start() - this.get_size(); + Kotlin.NumberRange = Kotlin.$createClass({ + initialize: function (start, size, reversed) { + this.$start = start; + this.$size = size; + this.$reversed = reversed; + }, + get_start: function () { + return this.$start; + }, + get_size: function () { + return this.$size; + }, + get_reversed: function () { + return this.$reversed; + }, + get_end: function () { + return this.get_reversed() ? this.get_start() - this.get_size() + 1 : this.get_start() + this.get_size() - 1; + }, + contains: function (number) { + if (this.get_reversed()) { + return number <= this.get_start() && number > this.get_start() - this.get_size(); + } + else { + return number >= this.get_start() && number < this.get_start() + this.get_size(); + } + }, + iterator: function () { + return Kotlin.$new(Kotlin.RangeIterator)(this.get_start(), this.get_size(), this.get_reversed()); } - else { - return number >= this.get_start() && number < this.get_start() + this.get_size(); - } - }, iterator:function () { - return Kotlin.$new(Kotlin.RangeIterator)(this.get_start(), this.get_size(), this.get_reversed()); - } }); - Kotlin.Comparator = Kotlin.$createClass( - { - initialize: function () { - }, - compare: function (el1, el2) { - throw Kotlin.$new(Kotlin.AbstractFunctionInvocationError)(); - } - } - ); + Kotlin.Comparator = Kotlin.$createClass({ + initialize: function () { + }, + compare: throwAbstractFunctionInvocationError + }); var ComparatorImpl = Kotlin.$createClass(Kotlin.Comparator, { - initialize: function (comparator) { - this.compare = comparator; - } - } - ); + initialize: function (comparator) { + this.compare = comparator; + } + }); Kotlin.comparator = function (f) { return Kotlin.$new(ComparatorImpl)(f); @@ -373,25 +361,8 @@ var kotlin = {set:function (receiver, key, value) { return Kotlin.$new(Kotlin.NumberRange)(0, arr.length); }; - 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 Kotlin.$new(intrinsicArrayIterator)(arr); + Kotlin.arrayIterator = function (array) { + return Kotlin.$new(ArrayIterator)(array); }; Kotlin.toString = function (obj) { @@ -800,14 +771,11 @@ var kotlin = {set:function (receiver, key, value) { Kotlin.HashTable = Hashtable; })(); - Kotlin.HashMap = Kotlin.$createClass( - { - initialize:function () { - Kotlin.HashTable.call(this); - } - } - ); - + Kotlin.HashMap = Kotlin.$createClass({ + initialize: function () { + Kotlin.HashTable.call(this); + } + }); (function () { function HashSet(hashingFunction, equalityFunction) { diff --git a/js/js.translator/testFiles/kotlin_lib_ecma5.js b/js/js.translator/testFiles/kotlin_lib_ecma5.js index 221727bfe2c..324a79a5c00 100644 --- a/js/js.translator/testFiles/kotlin_lib_ecma5.js +++ b/js/js.translator/testFiles/kotlin_lib_ecma5.js @@ -20,88 +20,75 @@ var Kotlin = {}; return false; }; - // todo compatibility for opera https://raw.github.com/gist/1000718/es5compat-gs.js + // as separated function to reduce scope + function createConstructor(proto, initializer) { + return function () { + var o = Object.create(proto); + if (initializer != null) { + initializer.apply(o, arguments); + } + + 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; + } + Object.defineProperties(proto, base.properties); + // todo test A -> B, C(->D) *properties from D is not yet added to proto* + } + + return proto; + } + // 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); + Kotlin.createClass = function (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); } - 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); - } + 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.seal(o); - return o; - }; + Object.defineProperty(initializer, "baseInitializer", {value: baseInitializer}); + Object.freeze(initializer); } - 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; - })(); + Object.freeze(constructor); + return constructor; + }; Kotlin.createObject = function (initializer, properties) { var o = Object.create(null, properties || undefined); @@ -128,7 +115,7 @@ var Kotlin = {}; }; Kotlin.$createClass = function (parent, properties) { - if (typeof (parent) != "function") { + if (parent !== null && typeof (parent) != "function") { properties = parent; parent = null; }