Value.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676
  1. /*
  2. * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice, this
  9. * list of conditions and the following disclaimer.
  10. *
  11. * 2. Redistributions in binary form must reproduce the above copyright notice,
  12. * this list of conditions and the following disclaimer in the documentation
  13. * and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  16. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  19. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  21. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  22. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  23. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  24. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include <AK/FlyString.h>
  27. #include <AK/String.h>
  28. #include <AK/StringBuilder.h>
  29. #include <LibJS/Heap/Heap.h>
  30. #include <LibJS/Interpreter.h>
  31. #include <LibJS/Runtime/Accessor.h>
  32. #include <LibJS/Runtime/Array.h>
  33. #include <LibJS/Runtime/BooleanObject.h>
  34. #include <LibJS/Runtime/Error.h>
  35. #include <LibJS/Runtime/Function.h>
  36. #include <LibJS/Runtime/NumberObject.h>
  37. #include <LibJS/Runtime/Object.h>
  38. #include <LibJS/Runtime/PrimitiveString.h>
  39. #include <LibJS/Runtime/StringObject.h>
  40. #include <LibJS/Runtime/Symbol.h>
  41. #include <LibJS/Runtime/SymbolObject.h>
  42. #include <LibJS/Runtime/Value.h>
  43. #include <math.h>
  44. namespace JS {
  45. bool Value::is_array() const
  46. {
  47. return is_object() && as_object().is_array();
  48. }
  49. bool Value::is_function() const
  50. {
  51. return is_object() && as_object().is_function();
  52. }
  53. Function& Value::as_function()
  54. {
  55. ASSERT(is_function());
  56. return static_cast<Function&>(as_object());
  57. }
  58. Accessor& Value::as_accessor()
  59. {
  60. ASSERT(is_accessor());
  61. return static_cast<Accessor&>(*m_value.as_accessor);
  62. }
  63. String Value::to_string_without_side_effects() const
  64. {
  65. if (is_boolean())
  66. return as_bool() ? "true" : "false";
  67. if (is_null())
  68. return "null";
  69. if (is_undefined())
  70. return "undefined";
  71. if (is_number()) {
  72. if (is_nan())
  73. return "NaN";
  74. if (is_infinity())
  75. return as_double() < 0 ? "-Infinity" : "Infinity";
  76. if (is_integer())
  77. return String::number(as_i32());
  78. return String::format("%.4f", as_double());
  79. }
  80. if (is_string())
  81. return m_value.as_string->string();
  82. if (is_symbol())
  83. return as_symbol().to_string();
  84. if (is_accessor())
  85. return "<accessor>";
  86. ASSERT(is_object());
  87. return String::format("[object %s]", as_object().class_name());
  88. }
  89. PrimitiveString* Value::to_primitive_string(Interpreter& interpreter)
  90. {
  91. if (is_string())
  92. return &as_string();
  93. auto string = to_string(interpreter);
  94. if (interpreter.exception())
  95. return nullptr;
  96. return js_string(interpreter, string);
  97. }
  98. String Value::to_string(Interpreter& interpreter) const
  99. {
  100. if (is_boolean())
  101. return as_bool() ? "true" : "false";
  102. if (is_null())
  103. return "null";
  104. if (is_undefined())
  105. return "undefined";
  106. if (is_number()) {
  107. if (is_nan())
  108. return "NaN";
  109. if (is_infinity())
  110. return as_double() < 0 ? "-Infinity" : "Infinity";
  111. if (is_integer())
  112. return String::number(as_i32());
  113. return String::format("%.4f", as_double());
  114. }
  115. if (is_symbol()) {
  116. interpreter.throw_exception<TypeError>("Can't convert symbol to string");
  117. return {};
  118. }
  119. if (is_object()) {
  120. auto primitive_value = as_object().to_primitive(Object::PreferredType::String);
  121. if (interpreter.exception())
  122. return {};
  123. return primitive_value.to_string(interpreter);
  124. }
  125. ASSERT(is_string());
  126. return m_value.as_string->string();
  127. }
  128. bool Value::to_boolean() const
  129. {
  130. switch (m_type) {
  131. case Type::Boolean:
  132. return m_value.as_bool;
  133. case Type::Number:
  134. if (is_nan()) {
  135. return false;
  136. }
  137. return !(m_value.as_double == 0 || m_value.as_double == -0);
  138. case Type::Null:
  139. case Type::Undefined:
  140. return false;
  141. case Type::String:
  142. return !as_string().string().is_empty();
  143. case Type::Object:
  144. case Type::Symbol:
  145. return true;
  146. default:
  147. ASSERT_NOT_REACHED();
  148. }
  149. }
  150. Value Value::to_primitive(Interpreter&) const
  151. {
  152. if (is_object())
  153. return as_object().to_primitive();
  154. return *this;
  155. }
  156. Object* Value::to_object(Interpreter& interpreter) const
  157. {
  158. if (is_object())
  159. return &const_cast<Object&>(as_object());
  160. if (is_string())
  161. return StringObject::create(interpreter.global_object(), *m_value.as_string);
  162. if (is_symbol())
  163. return SymbolObject::create(interpreter.global_object(), *m_value.as_symbol);
  164. if (is_number())
  165. return NumberObject::create(interpreter.global_object(), m_value.as_double);
  166. if (is_boolean())
  167. return BooleanObject::create(interpreter.global_object(), m_value.as_bool);
  168. if (is_null() || is_undefined()) {
  169. interpreter.throw_exception<TypeError>("ToObject on null or undefined.");
  170. return nullptr;
  171. }
  172. dbg() << "Dying because I can't to_object() on " << *this;
  173. ASSERT_NOT_REACHED();
  174. }
  175. Value Value::to_number(Interpreter& interpreter) const
  176. {
  177. switch (m_type) {
  178. case Type::Empty:
  179. case Type::Accessor:
  180. ASSERT_NOT_REACHED();
  181. return {};
  182. case Type::Undefined:
  183. return js_nan();
  184. case Type::Null:
  185. return Value(0);
  186. case Type::Boolean:
  187. return Value(m_value.as_bool ? 1 : 0);
  188. case Type::Number:
  189. return Value(m_value.as_double);
  190. case Type::String: {
  191. auto string = as_string().string().trim_whitespace();
  192. if (string.is_empty())
  193. return Value(0);
  194. if (string == "Infinity" || string == "+Infinity")
  195. return js_infinity();
  196. if (string == "-Infinity")
  197. return js_negative_infinity();
  198. char* endptr;
  199. auto parsed_double = strtod(string.characters(), &endptr);
  200. if (*endptr)
  201. return js_nan();
  202. return Value(parsed_double);
  203. }
  204. case Type::Symbol:
  205. interpreter.throw_exception<TypeError>("Can't convert symbol to number");
  206. return {};
  207. case Type::Object:
  208. auto primitive = m_value.as_object->to_primitive(Object::PreferredType::Number);
  209. if (interpreter.exception())
  210. return {};
  211. return primitive.to_number(interpreter);
  212. }
  213. ASSERT_NOT_REACHED();
  214. }
  215. i32 Value::as_i32() const
  216. {
  217. return static_cast<i32>(as_double());
  218. }
  219. size_t Value::as_size_t() const
  220. {
  221. ASSERT(as_double() >= 0);
  222. return min((double)as_i32(), MAX_ARRAY_LIKE_INDEX);
  223. }
  224. double Value::to_double(Interpreter& interpreter) const
  225. {
  226. auto number = to_number(interpreter);
  227. if (interpreter.exception())
  228. return 0;
  229. return number.as_double();
  230. }
  231. i32 Value::to_i32(Interpreter& interpreter) const
  232. {
  233. auto number = to_number(interpreter);
  234. if (interpreter.exception())
  235. return 0;
  236. if (number.is_nan())
  237. return 0;
  238. // FIXME: What about infinity though - that's UB...
  239. // Maybe NumericLimits<i32>::max() for +Infinity and NumericLimits<i32>::min() for -Infinity?
  240. return number.as_i32();
  241. }
  242. size_t Value::to_size_t(Interpreter& interpreter) const
  243. {
  244. if (is_empty())
  245. return 0;
  246. auto number = to_number(interpreter);
  247. if (interpreter.exception())
  248. return 0;
  249. if (number.is_nan())
  250. return 0;
  251. if (number.as_double() <= 0)
  252. return 0;
  253. return number.as_size_t();
  254. }
  255. Value greater_than(Interpreter& interpreter, Value lhs, Value rhs)
  256. {
  257. auto lhs_number = lhs.to_number(interpreter);
  258. if (interpreter.exception())
  259. return {};
  260. auto rhs_number = rhs.to_number(interpreter);
  261. if (interpreter.exception())
  262. return {};
  263. return Value(lhs_number.as_double() > rhs_number.as_double());
  264. }
  265. Value greater_than_equals(Interpreter& interpreter, Value lhs, Value rhs)
  266. {
  267. auto lhs_number = lhs.to_number(interpreter);
  268. if (interpreter.exception())
  269. return {};
  270. auto rhs_number = rhs.to_number(interpreter);
  271. if (interpreter.exception())
  272. return {};
  273. return Value(lhs_number.as_double() >= rhs_number.as_double());
  274. }
  275. Value less_than(Interpreter& interpreter, Value lhs, Value rhs)
  276. {
  277. auto lhs_number = lhs.to_number(interpreter);
  278. if (interpreter.exception())
  279. return {};
  280. auto rhs_number = rhs.to_number(interpreter);
  281. if (interpreter.exception())
  282. return {};
  283. return Value(lhs_number.as_double() < rhs_number.as_double());
  284. }
  285. Value less_than_equals(Interpreter& interpreter, Value lhs, Value rhs)
  286. {
  287. auto lhs_number = lhs.to_number(interpreter);
  288. if (interpreter.exception())
  289. return {};
  290. auto rhs_number = rhs.to_number(interpreter);
  291. if (interpreter.exception())
  292. return {};
  293. return Value(lhs_number.as_double() <= rhs_number.as_double());
  294. }
  295. Value bitwise_and(Interpreter& interpreter, Value lhs, Value rhs)
  296. {
  297. auto lhs_number = lhs.to_number(interpreter);
  298. if (interpreter.exception())
  299. return {};
  300. auto rhs_number = rhs.to_number(interpreter);
  301. if (interpreter.exception())
  302. return {};
  303. return Value((i32)lhs_number.as_double() & (i32)rhs_number.as_double());
  304. }
  305. Value bitwise_or(Interpreter& interpreter, Value lhs, Value rhs)
  306. {
  307. bool lhs_invalid = lhs.is_undefined() || lhs.is_null() || lhs.is_nan() || lhs.is_infinity();
  308. bool rhs_invalid = rhs.is_undefined() || rhs.is_null() || rhs.is_nan() || rhs.is_infinity();
  309. if (lhs_invalid && rhs_invalid)
  310. return Value(0);
  311. if (lhs_invalid || rhs_invalid)
  312. return lhs_invalid ? rhs.to_number(interpreter) : lhs.to_number(interpreter);
  313. if (!rhs.is_number() && !lhs.is_number())
  314. return Value(0);
  315. auto lhs_number = lhs.to_number(interpreter);
  316. if (interpreter.exception())
  317. return {};
  318. auto rhs_number = rhs.to_number(interpreter);
  319. if (interpreter.exception())
  320. return {};
  321. return Value((i32)lhs_number.as_double() | (i32)rhs_number.as_double());
  322. }
  323. Value bitwise_xor(Interpreter& interpreter, Value lhs, Value rhs)
  324. {
  325. auto lhs_number = lhs.to_number(interpreter);
  326. if (interpreter.exception())
  327. return {};
  328. auto rhs_number = rhs.to_number(interpreter);
  329. if (interpreter.exception())
  330. return {};
  331. return Value((i32)lhs_number.as_double() ^ (i32)rhs_number.as_double());
  332. }
  333. Value bitwise_not(Interpreter& interpreter, Value lhs)
  334. {
  335. auto lhs_number = lhs.to_number(interpreter);
  336. if (interpreter.exception())
  337. return {};
  338. return Value(~(i32)lhs_number.as_double());
  339. }
  340. Value unary_plus(Interpreter& interpreter, Value lhs)
  341. {
  342. return lhs.to_number(interpreter);
  343. }
  344. Value unary_minus(Interpreter& interpreter, Value lhs)
  345. {
  346. auto lhs_number = lhs.to_number(interpreter);
  347. if (interpreter.exception())
  348. return {};
  349. if (lhs_number.is_nan())
  350. return js_nan();
  351. return Value(-lhs_number.as_double());
  352. }
  353. Value left_shift(Interpreter& interpreter, Value lhs, Value rhs)
  354. {
  355. auto lhs_number = lhs.to_number(interpreter);
  356. if (interpreter.exception())
  357. return {};
  358. if (!lhs_number.is_finite_number())
  359. return Value(0);
  360. auto rhs_number = rhs.to_number(interpreter);
  361. if (interpreter.exception())
  362. return {};
  363. if (!rhs_number.is_finite_number())
  364. return lhs_number;
  365. return Value((i32)lhs_number.as_double() << (i32)rhs_number.as_double());
  366. }
  367. Value right_shift(Interpreter& interpreter, Value lhs, Value rhs)
  368. {
  369. auto lhs_number = lhs.to_number(interpreter);
  370. if (interpreter.exception())
  371. return {};
  372. if (!lhs_number.is_finite_number())
  373. return Value(0);
  374. auto rhs_number = rhs.to_number(interpreter);
  375. if (interpreter.exception())
  376. return {};
  377. if (!rhs_number.is_finite_number())
  378. return lhs_number;
  379. return Value((i32)lhs_number.as_double() >> (i32)rhs_number.as_double());
  380. }
  381. Value unsigned_right_shift(Interpreter& interpreter, Value lhs, Value rhs)
  382. {
  383. auto lhs_number = lhs.to_number(interpreter);
  384. if (interpreter.exception())
  385. return {};
  386. if (!lhs_number.is_finite_number())
  387. return Value(0);
  388. auto rhs_number = rhs.to_number(interpreter);
  389. if (interpreter.exception())
  390. return {};
  391. if (!rhs_number.is_finite_number())
  392. return lhs_number;
  393. return Value((unsigned)lhs_number.as_double() >> (i32)rhs_number.as_double());
  394. }
  395. Value add(Interpreter& interpreter, Value lhs, Value rhs)
  396. {
  397. auto lhs_primitive = lhs.to_primitive(interpreter);
  398. if (interpreter.exception())
  399. return {};
  400. auto rhs_primitive = rhs.to_primitive(interpreter);
  401. if (interpreter.exception())
  402. return {};
  403. if (lhs_primitive.is_string() || rhs_primitive.is_string()) {
  404. auto lhs_string = lhs_primitive.to_string(interpreter);
  405. if (interpreter.exception())
  406. return {};
  407. auto rhs_string = rhs_primitive.to_string(interpreter);
  408. if (interpreter.exception())
  409. return {};
  410. StringBuilder builder(lhs_string.length() + rhs_string.length());
  411. builder.append(lhs_string);
  412. builder.append(rhs_string);
  413. return js_string(interpreter, builder.to_string());
  414. }
  415. auto lhs_number = lhs_primitive.to_number(interpreter);
  416. if (interpreter.exception())
  417. return {};
  418. auto rhs_number = rhs_primitive.to_number(interpreter);
  419. if (interpreter.exception())
  420. return {};
  421. return Value(lhs_number.as_double() + rhs_number.as_double());
  422. }
  423. Value sub(Interpreter& interpreter, Value lhs, Value rhs)
  424. {
  425. auto lhs_number = lhs.to_number(interpreter);
  426. if (interpreter.exception())
  427. return {};
  428. auto rhs_number = rhs.to_number(interpreter);
  429. if (interpreter.exception())
  430. return {};
  431. return Value(lhs_number.as_double() - rhs_number.as_double());
  432. }
  433. Value mul(Interpreter& interpreter, Value lhs, Value rhs)
  434. {
  435. auto lhs_number = lhs.to_number(interpreter);
  436. if (interpreter.exception())
  437. return {};
  438. auto rhs_number = rhs.to_number(interpreter);
  439. if (interpreter.exception())
  440. return {};
  441. return Value(lhs_number.as_double() * rhs_number.as_double());
  442. }
  443. Value div(Interpreter& interpreter, Value lhs, Value rhs)
  444. {
  445. auto lhs_number = lhs.to_number(interpreter);
  446. if (interpreter.exception())
  447. return {};
  448. auto rhs_number = rhs.to_number(interpreter);
  449. if (interpreter.exception())
  450. return {};
  451. return Value(lhs_number.as_double() / rhs_number.as_double());
  452. }
  453. Value mod(Interpreter& interpreter, Value lhs, Value rhs)
  454. {
  455. auto lhs_number = lhs.to_number(interpreter);
  456. if (interpreter.exception())
  457. return {};
  458. auto rhs_number = rhs.to_number(interpreter);
  459. if (interpreter.exception())
  460. return {};
  461. if (lhs_number.is_nan() || rhs_number.is_nan())
  462. return js_nan();
  463. auto index = lhs_number.as_double();
  464. auto period = rhs_number.as_double();
  465. auto trunc = (double)(i32)(index / period);
  466. return Value(index - trunc * period);
  467. }
  468. Value exp(Interpreter& interpreter, Value lhs, Value rhs)
  469. {
  470. auto lhs_number = lhs.to_number(interpreter);
  471. if (interpreter.exception())
  472. return {};
  473. auto rhs_number = rhs.to_number(interpreter);
  474. if (interpreter.exception())
  475. return {};
  476. return Value(pow(lhs_number.as_double(), rhs_number.as_double()));
  477. }
  478. Value in(Interpreter& interpreter, Value lhs, Value rhs)
  479. {
  480. if (!rhs.is_object())
  481. return interpreter.throw_exception<TypeError>("'in' operator must be used on object");
  482. auto lhs_string = lhs.to_string(interpreter);
  483. if (interpreter.exception())
  484. return {};
  485. return Value(!rhs.as_object().get(lhs_string).is_empty());
  486. }
  487. Value instance_of(Interpreter&, Value lhs, Value rhs)
  488. {
  489. if (!lhs.is_object() || !rhs.is_object())
  490. return Value(false);
  491. auto constructor_prototype_property = rhs.as_object().get("prototype");
  492. if (!constructor_prototype_property.is_object())
  493. return Value(false);
  494. return Value(lhs.as_object().has_prototype(&constructor_prototype_property.as_object()));
  495. }
  496. const LogStream& operator<<(const LogStream& stream, const Value& value)
  497. {
  498. return stream << (value.is_empty() ? "<empty>" : value.to_string_without_side_effects());
  499. }
  500. bool same_value(Interpreter& interpreter, Value lhs, Value rhs)
  501. {
  502. if (lhs.type() != rhs.type())
  503. return false;
  504. if (lhs.is_number()) {
  505. if (lhs.is_nan() && rhs.is_nan())
  506. return true;
  507. if (lhs.is_positive_zero() && rhs.is_negative_zero())
  508. return false;
  509. if (lhs.is_negative_zero() && rhs.is_positive_zero())
  510. return false;
  511. return lhs.as_double() == rhs.as_double();
  512. }
  513. return same_value_non_numeric(interpreter, lhs, rhs);
  514. }
  515. bool same_value_zero(Interpreter& interpreter, Value lhs, Value rhs)
  516. {
  517. if (lhs.type() != rhs.type())
  518. return false;
  519. if (lhs.is_number()) {
  520. if (lhs.is_nan() && rhs.is_nan())
  521. return true;
  522. if ((lhs.is_positive_zero() || lhs.is_negative_zero()) && (rhs.is_positive_zero() || rhs.is_negative_zero()))
  523. return true;
  524. return lhs.as_double() == rhs.as_double();
  525. }
  526. return same_value_non_numeric(interpreter, lhs, rhs);
  527. }
  528. bool same_value_non_numeric(Interpreter&, Value lhs, Value rhs)
  529. {
  530. ASSERT(!lhs.is_number());
  531. ASSERT(lhs.type() == rhs.type());
  532. switch (lhs.type()) {
  533. case Value::Type::Empty:
  534. ASSERT_NOT_REACHED();
  535. case Value::Type::Undefined:
  536. case Value::Type::Null:
  537. return true;
  538. case Value::Type::String:
  539. return lhs.as_string().string() == rhs.as_string().string();
  540. case Value::Type::Symbol:
  541. return &lhs.as_symbol() == &rhs.as_symbol();
  542. case Value::Type::Boolean:
  543. return lhs.as_bool() == rhs.as_bool();
  544. case Value::Type::Object:
  545. return &lhs.as_object() == &rhs.as_object();
  546. default:
  547. ASSERT_NOT_REACHED();
  548. }
  549. }
  550. bool strict_eq(Interpreter& interpreter, Value lhs, Value rhs)
  551. {
  552. if (lhs.type() != rhs.type())
  553. return false;
  554. if (lhs.is_number()) {
  555. if (lhs.is_nan() || rhs.is_nan())
  556. return false;
  557. if (lhs.as_double() == rhs.as_double())
  558. return true;
  559. if ((lhs.is_positive_zero() || lhs.is_negative_zero()) && (rhs.is_positive_zero() || rhs.is_negative_zero()))
  560. return true;
  561. return false;
  562. }
  563. return same_value_non_numeric(interpreter, lhs, rhs);
  564. }
  565. bool abstract_eq(Interpreter& interpreter, Value lhs, Value rhs)
  566. {
  567. if (lhs.type() == rhs.type())
  568. return strict_eq(interpreter, lhs, rhs);
  569. if ((lhs.is_undefined() || lhs.is_null()) && (rhs.is_undefined() || rhs.is_null()))
  570. return true;
  571. if (lhs.is_number() && rhs.is_string())
  572. return abstract_eq(interpreter, lhs, rhs.to_number(interpreter));
  573. if (lhs.is_string() && rhs.is_number())
  574. return abstract_eq(interpreter, lhs.to_number(interpreter), rhs);
  575. if (lhs.is_boolean())
  576. return abstract_eq(interpreter, lhs.to_number(interpreter), rhs);
  577. if (rhs.is_boolean())
  578. return abstract_eq(interpreter, lhs, rhs.to_number(interpreter));
  579. if ((lhs.is_string() || lhs.is_number() || lhs.is_symbol()) && rhs.is_object())
  580. return abstract_eq(interpreter, lhs, rhs.to_primitive(interpreter));
  581. if (lhs.is_object() && (rhs.is_string() || rhs.is_number() || rhs.is_symbol()))
  582. return abstract_eq(interpreter, lhs.to_primitive(interpreter), rhs);
  583. return false;
  584. }
  585. }