JS: prevent Any.equals from mangling

This commit is contained in:
Alexey Andreev
2016-12-07 18:43:21 +03:00
parent a2d45153ba
commit cc819928de
7 changed files with 61 additions and 19 deletions
@@ -230,6 +230,7 @@ class NameSuggestion {
when (overriddenDescriptor.fqNameUnsafe.asString()) { when (overriddenDescriptor.fqNameUnsafe.asString()) {
"kotlin.CharSequence.subSequence" -> return NameAndStability("substring", true) "kotlin.CharSequence.subSequence" -> return NameAndStability("substring", true)
"kotlin.CharSequence.get" -> return NameAndStability("charAt", true) "kotlin.CharSequence.get" -> return NameAndStability("charAt", true)
"kotlin.Any.equals" -> return NameAndStability("equals", true)
} }
} }
@@ -5609,6 +5609,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
doTest(fileName); 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") @TestMetadata("eval.kt")
public void testEval() throws Exception { public void testEval() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/native/eval.kt"); String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/native/eval.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_HASH_CODE = "hashCode"
val STABLE_TO_STRING = "toString" val STABLE_TO_STRING = "toString"
val STABLE_EQUALS_2 = "equals_wn2jw4$" val STABLE_EQUALS_2 = "equals_wn2jw4$"
+10
View File
@@ -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;
};
+25
View File
@@ -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"
}
+2 -2
View File
@@ -48,8 +48,8 @@ Kotlin.equals = function (obj1, obj2) {
return false; return false;
} }
if (typeof obj1 == "object" && typeof obj1.equals_za3rmp$ === "function") { if (typeof obj1 == "object" && typeof obj1.equals === "function") {
return obj1.equals_za3rmp$(obj2); return obj1.equals(obj2);
} }
return obj1 === obj2; return obj1 === obj2;
+16 -16
View File
@@ -297,7 +297,7 @@ Kotlin.Long.prototype.toString = function(opt_radix) {
} }
if (this.isNegative()) { 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 // 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. // the bottom-most digit in this base and then recurse to do the rest.
var radixLong = Kotlin.Long.fromNumber(radix); var radixLong = Kotlin.Long.fromNumber(radix);
@@ -358,7 +358,7 @@ Kotlin.Long.prototype.getLowBitsUnsigned = function() {
*/ */
Kotlin.Long.prototype.getNumBitsAbs = function() { Kotlin.Long.prototype.getNumBitsAbs = function() {
if (this.isNegative()) { if (this.isNegative()) {
if (this.equals(Kotlin.Long.MIN_VALUE)) { if (this.equalsLong(Kotlin.Long.MIN_VALUE)) {
return 64; return 64;
} else { } else {
return this.negate().getNumBitsAbs(); return this.negate().getNumBitsAbs();
@@ -397,7 +397,7 @@ Kotlin.Long.prototype.isOdd = function() {
* @param {Kotlin.Long} other Long to compare against. * @param {Kotlin.Long} other Long to compare against.
* @return {boolean} Whether this Long equals the other. * @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_); 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. * @param {Kotlin.Long} other Long to compare against.
* @return {boolean} Whether this Long does not equal the other. * @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_); 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. * if the given one is greater.
*/ */
Kotlin.Long.prototype.compare = function(other) { Kotlin.Long.prototype.compare = function(other) {
if (this.equals(other)) { if (this.equalsLong(other)) {
return 0; return 0;
} }
@@ -478,7 +478,7 @@ Kotlin.Long.prototype.compare = function(other) {
/** @return {!Kotlin.Long} The negation of this value. */ /** @return {!Kotlin.Long} The negation of this value. */
Kotlin.Long.prototype.negate = function() { Kotlin.Long.prototype.negate = function() {
if (this.equals(Kotlin.Long.MIN_VALUE)) { if (this.equalsLong(Kotlin.Long.MIN_VALUE)) {
return Kotlin.Long.MIN_VALUE; return Kotlin.Long.MIN_VALUE;
} else { } else {
return this.not().add(Kotlin.Long.ONE); return this.not().add(Kotlin.Long.ONE);
@@ -542,9 +542,9 @@ Kotlin.Long.prototype.multiply = function(other) {
return Kotlin.Long.ZERO; 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; 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; return this.isOdd() ? Kotlin.Long.MIN_VALUE : Kotlin.Long.ZERO;
} }
@@ -614,17 +614,17 @@ Kotlin.Long.prototype.div = function(other) {
return Kotlin.Long.ZERO; return Kotlin.Long.ZERO;
} }
if (this.equals(Kotlin.Long.MIN_VALUE)) { if (this.equalsLong(Kotlin.Long.MIN_VALUE)) {
if (other.equals(Kotlin.Long.ONE) || if (other.equalsLong(Kotlin.Long.ONE) ||
other.equals(Kotlin.Long.NEG_ONE)) { other.equalsLong(Kotlin.Long.NEG_ONE)) {
return Kotlin.Long.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE 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; return Kotlin.Long.ONE;
} else { } else {
// At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|. // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|.
var halfThis = this.shiftRight(1); var halfThis = this.shiftRight(1);
var approx = halfThis.div(other).shiftLeft(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; return other.isNegative() ? Kotlin.Long.ONE : Kotlin.Long.NEG_ONE;
} else { } else {
var rem = this.subtract(other.multiply(approx)); var rem = this.subtract(other.multiply(approx));
@@ -632,7 +632,7 @@ Kotlin.Long.prototype.div = function(other) {
return result; return result;
} }
} }
} else if (other.equals(Kotlin.Long.MIN_VALUE)) { } else if (other.equalsLong(Kotlin.Long.MIN_VALUE)) {
return Kotlin.Long.ZERO; return Kotlin.Long.ZERO;
} }
@@ -810,8 +810,8 @@ Kotlin.Long.prototype.shiftRightUnsigned = function(numBits) {
}; };
// Support for Kotlin // Support for Kotlin
Kotlin.Long.prototype.equals_za3rmp$ = function (other) { Kotlin.Long.prototype.equals = function (other) {
return other instanceof Kotlin.Long && this.equals(other); return other instanceof Kotlin.Long && this.equalsLong(other);
}; };
Kotlin.Long.prototype.compareTo_za3rmp$ = Kotlin.Long.prototype.compare; Kotlin.Long.prototype.compareTo_za3rmp$ = Kotlin.Long.prototype.compare;