diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/naming/NameSuggestion.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/naming/NameSuggestion.kt index f50939670dc..f9b2d9aa8ac 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/naming/NameSuggestion.kt +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/naming/NameSuggestion.kt @@ -230,6 +230,7 @@ class NameSuggestion { when (overriddenDescriptor.fqNameUnsafe.asString()) { "kotlin.CharSequence.subSequence" -> return NameAndStability("substring", true) "kotlin.CharSequence.get" -> return NameAndStability("charAt", true) + "kotlin.Any.equals" -> return NameAndStability("equals", true) } } diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java index 29beaa4a625..312947d5541 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java @@ -5609,6 +5609,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest { doTest(fileName); } + @TestMetadata("equalsMangling.kt") + public void testEqualsMangling() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/native/equalsMangling.kt"); + doTest(fileName); + } + @TestMetadata("eval.kt") public void testEval() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/native/eval.kt"); diff --git a/js/js.translator/testData/box/expression/function/manglingAnyMethods.kt b/js/js.translator/testData/box/expression/function/manglingAnyMethods.kt index a2ea67cde1b..3420bcab92b 100644 --- a/js/js.translator/testData/box/expression/function/manglingAnyMethods.kt +++ b/js/js.translator/testData/box/expression/function/manglingAnyMethods.kt @@ -54,7 +54,7 @@ fun test(expected: String, f: () -> Unit) { } } -val STABLE_EQUALS = "equals_za3rmp$" +val STABLE_EQUALS = "equals" val STABLE_HASH_CODE = "hashCode" val STABLE_TO_STRING = "toString" val STABLE_EQUALS_2 = "equals_wn2jw4$" diff --git a/js/js.translator/testData/box/native/equalsMangling.js b/js/js.translator/testData/box/native/equalsMangling.js new file mode 100644 index 00000000000..e11be900676 --- /dev/null +++ b/js/js.translator/testData/box/native/equalsMangling.js @@ -0,0 +1,10 @@ +function foo(first, second) { + return first.equals(second); +} + +function B(value) { + this.value = value; +} +B.prototype.equals = function(other) { + return other instanceof B && other.value == this.value; +}; \ No newline at end of file diff --git a/js/js.translator/testData/box/native/equalsMangling.kt b/js/js.translator/testData/box/native/equalsMangling.kt new file mode 100644 index 00000000000..a165cb1acb8 --- /dev/null +++ b/js/js.translator/testData/box/native/equalsMangling.kt @@ -0,0 +1,25 @@ +data class A(val number: Int) + +@native fun foo(first: A, second: A): Boolean + +@native class B(value: Int) + +fun box(): String { + val a = A(23) + val b = A(23) + val c = A(42) + + if (!foo(a, b)) return "fail1" + if (!foo(a, a)) return "fail2" + if (foo(a, c)) return "fail3" + + val d = B(23) + val e = B(23) + val f = B(42) + + if (d != e) return "fail4" + if (d != d) return "fail5" + if (d == f) return "fail6" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/kotlin_lib.js b/js/js.translator/testData/kotlin_lib.js index ae7327f61ca..5c114e6aef9 100644 --- a/js/js.translator/testData/kotlin_lib.js +++ b/js/js.translator/testData/kotlin_lib.js @@ -48,8 +48,8 @@ Kotlin.equals = function (obj1, obj2) { return false; } - if (typeof obj1 == "object" && typeof obj1.equals_za3rmp$ === "function") { - return obj1.equals_za3rmp$(obj2); + if (typeof obj1 == "object" && typeof obj1.equals === "function") { + return obj1.equals(obj2); } return obj1 === obj2; diff --git a/js/js.translator/testData/long.js b/js/js.translator/testData/long.js index cba92000547..87df362453b 100644 --- a/js/js.translator/testData/long.js +++ b/js/js.translator/testData/long.js @@ -297,7 +297,7 @@ Kotlin.Long.prototype.toString = function(opt_radix) { } if (this.isNegative()) { - if (this.equals(Kotlin.Long.MIN_VALUE)) { + if (this.equalsLong(Kotlin.Long.MIN_VALUE)) { // We need to change the Long value before it can be negated, so we remove // the bottom-most digit in this base and then recurse to do the rest. var radixLong = Kotlin.Long.fromNumber(radix); @@ -358,7 +358,7 @@ Kotlin.Long.prototype.getLowBitsUnsigned = function() { */ Kotlin.Long.prototype.getNumBitsAbs = function() { if (this.isNegative()) { - if (this.equals(Kotlin.Long.MIN_VALUE)) { + if (this.equalsLong(Kotlin.Long.MIN_VALUE)) { return 64; } else { return this.negate().getNumBitsAbs(); @@ -397,7 +397,7 @@ Kotlin.Long.prototype.isOdd = function() { * @param {Kotlin.Long} other Long to compare against. * @return {boolean} Whether this Long equals the other. */ -Kotlin.Long.prototype.equals = function(other) { +Kotlin.Long.prototype.equalsLong = function(other) { return (this.high_ == other.high_) && (this.low_ == other.low_); }; @@ -406,7 +406,7 @@ Kotlin.Long.prototype.equals = function(other) { * @param {Kotlin.Long} other Long to compare against. * @return {boolean} Whether this Long does not equal the other. */ -Kotlin.Long.prototype.notEquals = function(other) { +Kotlin.Long.prototype.notEqualsLong = function(other) { return (this.high_ != other.high_) || (this.low_ != other.low_); }; @@ -454,7 +454,7 @@ Kotlin.Long.prototype.greaterThanOrEqual = function(other) { * if the given one is greater. */ Kotlin.Long.prototype.compare = function(other) { - if (this.equals(other)) { + if (this.equalsLong(other)) { return 0; } @@ -478,7 +478,7 @@ Kotlin.Long.prototype.compare = function(other) { /** @return {!Kotlin.Long} The negation of this value. */ Kotlin.Long.prototype.negate = function() { - if (this.equals(Kotlin.Long.MIN_VALUE)) { + if (this.equalsLong(Kotlin.Long.MIN_VALUE)) { return Kotlin.Long.MIN_VALUE; } else { return this.not().add(Kotlin.Long.ONE); @@ -542,9 +542,9 @@ Kotlin.Long.prototype.multiply = function(other) { return Kotlin.Long.ZERO; } - if (this.equals(Kotlin.Long.MIN_VALUE)) { + if (this.equalsLong(Kotlin.Long.MIN_VALUE)) { return other.isOdd() ? Kotlin.Long.MIN_VALUE : Kotlin.Long.ZERO; - } else if (other.equals(Kotlin.Long.MIN_VALUE)) { + } else if (other.equalsLong(Kotlin.Long.MIN_VALUE)) { return this.isOdd() ? Kotlin.Long.MIN_VALUE : Kotlin.Long.ZERO; } @@ -614,17 +614,17 @@ Kotlin.Long.prototype.div = function(other) { return Kotlin.Long.ZERO; } - if (this.equals(Kotlin.Long.MIN_VALUE)) { - if (other.equals(Kotlin.Long.ONE) || - other.equals(Kotlin.Long.NEG_ONE)) { + if (this.equalsLong(Kotlin.Long.MIN_VALUE)) { + if (other.equalsLong(Kotlin.Long.ONE) || + other.equalsLong(Kotlin.Long.NEG_ONE)) { return Kotlin.Long.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE - } else if (other.equals(Kotlin.Long.MIN_VALUE)) { + } else if (other.equalsLong(Kotlin.Long.MIN_VALUE)) { return Kotlin.Long.ONE; } else { // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|. var halfThis = this.shiftRight(1); var approx = halfThis.div(other).shiftLeft(1); - if (approx.equals(Kotlin.Long.ZERO)) { + if (approx.equalsLong(Kotlin.Long.ZERO)) { return other.isNegative() ? Kotlin.Long.ONE : Kotlin.Long.NEG_ONE; } else { var rem = this.subtract(other.multiply(approx)); @@ -632,7 +632,7 @@ Kotlin.Long.prototype.div = function(other) { return result; } } - } else if (other.equals(Kotlin.Long.MIN_VALUE)) { + } else if (other.equalsLong(Kotlin.Long.MIN_VALUE)) { return Kotlin.Long.ZERO; } @@ -810,8 +810,8 @@ Kotlin.Long.prototype.shiftRightUnsigned = function(numBits) { }; // Support for Kotlin -Kotlin.Long.prototype.equals_za3rmp$ = function (other) { - return other instanceof Kotlin.Long && this.equals(other); +Kotlin.Long.prototype.equals = function (other) { + return other instanceof Kotlin.Long && this.equalsLong(other); }; Kotlin.Long.prototype.compareTo_za3rmp$ = Kotlin.Long.prototype.compare;