| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index a7c3d7610c42ad192c2396cba4dedea79370ec67..91aa2ae250360535fb89e37dcd6f79f394cc4f3f 100644
|
| --- a/src/objects.cc
|
| +++ b/src/objects.cc
|
| @@ -98,13 +98,13 @@ MaybeHandle<Object> Object::ToNumber(Handle<Object> input) {
|
| if (input->IsNumber()) {
|
| return input;
|
| }
|
| - Isolate* const isolate = Handle<HeapObject>::cast(input)->GetIsolate();
|
| - if (input->IsOddball()) {
|
| - return handle(Handle<Oddball>::cast(input)->to_number(), isolate);
|
| - }
|
| if (input->IsString()) {
|
| return String::ToNumber(Handle<String>::cast(input));
|
| }
|
| + if (input->IsOddball()) {
|
| + return Oddball::ToNumber(Handle<Oddball>::cast(input));
|
| + }
|
| + Isolate* const isolate = Handle<HeapObject>::cast(input)->GetIsolate();
|
| if (input->IsSymbol()) {
|
| THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSymbolToNumber),
|
| Object);
|
| @@ -159,13 +159,114 @@ bool Object::BooleanValue() {
|
| }
|
|
|
|
|
| +namespace {
|
| +
|
| +// TODO(bmeurer): Maybe we should introduce a marker interface Number,
|
| +// where we put all these methods at some point?
|
| +bool NumberEquals(double x, double y) {
|
| + // Must check explicitly for NaN's on Windows, but -0 works fine.
|
| + if (std::isnan(x)) return false;
|
| + if (std::isnan(y)) return false;
|
| + return x == y;
|
| +}
|
| +
|
| +
|
| +bool NumberEquals(const Object* x, const Object* y) {
|
| + return NumberEquals(x->Number(), y->Number());
|
| +}
|
| +
|
| +
|
| +bool NumberEquals(Handle<Object> x, Handle<Object> y) {
|
| + return NumberEquals(*x, *y);
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +
|
| +// static
|
| +Maybe<bool> Object::Equals(Handle<Object> x, Handle<Object> y) {
|
| + while (true) {
|
| + if (x->IsNumber()) {
|
| + if (y->IsNumber()) {
|
| + return Just(NumberEquals(x, y));
|
| + } else if (y->IsBoolean()) {
|
| + return Just(NumberEquals(*x, Handle<Oddball>::cast(y)->to_number()));
|
| + } else if (y->IsString()) {
|
| + return Just(NumberEquals(x, String::ToNumber(Handle<String>::cast(y))));
|
| + } else if (y->IsJSReceiver() && !y->IsUndetectableObject()) {
|
| + if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
|
| + .ToHandle(&y)) {
|
| + return Nothing<bool>();
|
| + }
|
| + } else {
|
| + return Just(false);
|
| + }
|
| + } else if (x->IsString()) {
|
| + if (y->IsString()) {
|
| + return Just(
|
| + String::Equals(Handle<String>::cast(x), Handle<String>::cast(y)));
|
| + } else if (y->IsNumber()) {
|
| + x = String::ToNumber(Handle<String>::cast(x));
|
| + return Just(NumberEquals(x, y));
|
| + } else if (y->IsBoolean()) {
|
| + x = String::ToNumber(Handle<String>::cast(x));
|
| + return Just(NumberEquals(*x, Handle<Oddball>::cast(y)->to_number()));
|
| + } else if (y->IsJSReceiver() && !y->IsUndetectableObject()) {
|
| + if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
|
| + .ToHandle(&y)) {
|
| + return Nothing<bool>();
|
| + }
|
| + } else {
|
| + return Just(false);
|
| + }
|
| + } else if (x->IsBoolean()) {
|
| + if (y->IsOddball()) {
|
| + return Just(x.is_identical_to(y));
|
| + } else if (y->IsNumber()) {
|
| + return Just(NumberEquals(Handle<Oddball>::cast(x)->to_number(), *y));
|
| + } else if (y->IsString()) {
|
| + y = String::ToNumber(Handle<String>::cast(y));
|
| + return Just(NumberEquals(Handle<Oddball>::cast(x)->to_number(), *y));
|
| + } else if (y->IsJSReceiver() && !y->IsUndetectableObject()) {
|
| + if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
|
| + .ToHandle(&y)) {
|
| + return Nothing<bool>();
|
| + }
|
| + x = Oddball::ToNumber(Handle<Oddball>::cast(x));
|
| + } else {
|
| + return Just(false);
|
| + }
|
| + } else if (x->IsSymbol()) {
|
| + return Just(x.is_identical_to(y));
|
| + } else if (x->IsSimd128Value()) {
|
| + if (!y->IsSimd128Value()) return Just(false);
|
| + return Just(Simd128Value::Equals(Handle<Simd128Value>::cast(x),
|
| + Handle<Simd128Value>::cast(y)));
|
| + } else if (x->IsJSReceiver() && !x->IsUndetectableObject()) {
|
| + if (y->IsJSReceiver()) {
|
| + return Just(x.is_identical_to(y));
|
| + } else if (y->IsNull() || y->IsSimd128Value() || y->IsSymbol() ||
|
| + y->IsUndefined()) {
|
| + return Just(false);
|
| + } else if (y->IsBoolean()) {
|
| + y = Oddball::ToNumber(Handle<Oddball>::cast(y));
|
| + }
|
| + if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(x)).ToHandle(&x)) {
|
| + return Nothing<bool>();
|
| + }
|
| + } else {
|
| + return Just(
|
| + (x->IsNull() || x->IsUndefined() || x->IsUndetectableObject()) &&
|
| + (y->IsNull() || y->IsUndefined() || y->IsUndetectableObject()));
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| bool Object::StrictEquals(Object* that) {
|
| if (this->IsNumber()) {
|
| if (!that->IsNumber()) return false;
|
| - double const x = this->Number();
|
| - double const y = that->Number();
|
| - // Must check explicitly for NaN:s on Windows, but -0 works fine.
|
| - return x == y && !std::isnan(x) && !std::isnan(y);
|
| + return NumberEquals(this, that);
|
| } else if (this->IsString()) {
|
| if (!that->IsString()) return false;
|
| return String::cast(this)->Equals(String::cast(that));
|
|
|