JSCJSValueInlines.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813
  1. /*
  2. * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. * 1. Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * 2. Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. *
  13. * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
  14. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  15. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  16. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
  17. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  18. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  19. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  20. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  21. * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  23. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. #ifndef JSValueInlines_h
  26. #define JSValueInlines_h
  27. #include "InternalFunction.h"
  28. #include "JSCJSValue.h"
  29. #include "JSCellInlines.h"
  30. #include "JSFunction.h"
  31. namespace JSC {
  32. ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const
  33. {
  34. if (isInt32())
  35. return asInt32();
  36. return JSC::toInt32(toNumber(exec));
  37. }
  38. inline uint32_t JSValue::toUInt32(ExecState* exec) const
  39. {
  40. // See comment on JSC::toUInt32, above.
  41. return toInt32(exec);
  42. }
  43. inline bool JSValue::isUInt32() const
  44. {
  45. return isInt32() && asInt32() >= 0;
  46. }
  47. inline uint32_t JSValue::asUInt32() const
  48. {
  49. ASSERT(isUInt32());
  50. return asInt32();
  51. }
  52. inline double JSValue::asNumber() const
  53. {
  54. ASSERT(isNumber());
  55. return isInt32() ? asInt32() : asDouble();
  56. }
  57. inline JSValue jsNaN()
  58. {
  59. return JSValue(QNaN);
  60. }
  61. inline JSValue::JSValue(char i)
  62. {
  63. *this = JSValue(static_cast<int32_t>(i));
  64. }
  65. inline JSValue::JSValue(unsigned char i)
  66. {
  67. *this = JSValue(static_cast<int32_t>(i));
  68. }
  69. inline JSValue::JSValue(short i)
  70. {
  71. *this = JSValue(static_cast<int32_t>(i));
  72. }
  73. inline JSValue::JSValue(unsigned short i)
  74. {
  75. *this = JSValue(static_cast<int32_t>(i));
  76. }
  77. inline JSValue::JSValue(unsigned i)
  78. {
  79. if (static_cast<int32_t>(i) < 0) {
  80. *this = JSValue(EncodeAsDouble, static_cast<double>(i));
  81. return;
  82. }
  83. *this = JSValue(static_cast<int32_t>(i));
  84. }
  85. inline JSValue::JSValue(long i)
  86. {
  87. if (static_cast<int32_t>(i) != i) {
  88. *this = JSValue(EncodeAsDouble, static_cast<double>(i));
  89. return;
  90. }
  91. *this = JSValue(static_cast<int32_t>(i));
  92. }
  93. inline JSValue::JSValue(unsigned long i)
  94. {
  95. if (static_cast<uint32_t>(i) != i) {
  96. *this = JSValue(EncodeAsDouble, static_cast<double>(i));
  97. return;
  98. }
  99. *this = JSValue(static_cast<uint32_t>(i));
  100. }
  101. inline JSValue::JSValue(long long i)
  102. {
  103. if (static_cast<int32_t>(i) != i) {
  104. *this = JSValue(EncodeAsDouble, static_cast<double>(i));
  105. return;
  106. }
  107. *this = JSValue(static_cast<int32_t>(i));
  108. }
  109. inline JSValue::JSValue(unsigned long long i)
  110. {
  111. if (static_cast<uint32_t>(i) != i) {
  112. *this = JSValue(EncodeAsDouble, static_cast<double>(i));
  113. return;
  114. }
  115. *this = JSValue(static_cast<uint32_t>(i));
  116. }
  117. inline JSValue::JSValue(double d)
  118. {
  119. const int32_t asInt32 = static_cast<int32_t>(d);
  120. if (asInt32 != d || (!asInt32 && std::signbit(d))) { // true for -0.0
  121. *this = JSValue(EncodeAsDouble, d);
  122. return;
  123. }
  124. *this = JSValue(static_cast<int32_t>(d));
  125. }
  126. inline EncodedJSValue JSValue::encode(JSValue value)
  127. {
  128. return value.u.asInt64;
  129. }
  130. inline JSValue JSValue::decode(EncodedJSValue encodedJSValue)
  131. {
  132. JSValue v;
  133. v.u.asInt64 = encodedJSValue;
  134. return v;
  135. }
  136. #if USE(JSVALUE32_64)
  137. inline JSValue::JSValue()
  138. {
  139. u.asBits.tag = EmptyValueTag;
  140. u.asBits.payload = 0;
  141. }
  142. inline JSValue::JSValue(JSNullTag)
  143. {
  144. u.asBits.tag = NullTag;
  145. u.asBits.payload = 0;
  146. }
  147. inline JSValue::JSValue(JSUndefinedTag)
  148. {
  149. u.asBits.tag = UndefinedTag;
  150. u.asBits.payload = 0;
  151. }
  152. inline JSValue::JSValue(JSTrueTag)
  153. {
  154. u.asBits.tag = BooleanTag;
  155. u.asBits.payload = 1;
  156. }
  157. inline JSValue::JSValue(JSFalseTag)
  158. {
  159. u.asBits.tag = BooleanTag;
  160. u.asBits.payload = 0;
  161. }
  162. inline JSValue::JSValue(HashTableDeletedValueTag)
  163. {
  164. u.asBits.tag = DeletedValueTag;
  165. u.asBits.payload = 0;
  166. }
  167. inline JSValue::JSValue(JSCell* ptr)
  168. {
  169. if (ptr)
  170. u.asBits.tag = CellTag;
  171. else
  172. u.asBits.tag = EmptyValueTag;
  173. u.asBits.payload = reinterpret_cast<int32_t>(ptr);
  174. }
  175. inline JSValue::JSValue(const JSCell* ptr)
  176. {
  177. if (ptr)
  178. u.asBits.tag = CellTag;
  179. else
  180. u.asBits.tag = EmptyValueTag;
  181. u.asBits.payload = reinterpret_cast<int32_t>(const_cast<JSCell*>(ptr));
  182. }
  183. inline JSValue::operator bool() const
  184. {
  185. ASSERT(tag() != DeletedValueTag);
  186. return tag() != EmptyValueTag;
  187. }
  188. inline bool JSValue::operator==(const JSValue& other) const
  189. {
  190. return u.asInt64 == other.u.asInt64;
  191. }
  192. inline bool JSValue::operator!=(const JSValue& other) const
  193. {
  194. return u.asInt64 != other.u.asInt64;
  195. }
  196. inline bool JSValue::isEmpty() const
  197. {
  198. return tag() == EmptyValueTag;
  199. }
  200. inline bool JSValue::isUndefined() const
  201. {
  202. return tag() == UndefinedTag;
  203. }
  204. inline bool JSValue::isNull() const
  205. {
  206. return tag() == NullTag;
  207. }
  208. inline bool JSValue::isUndefinedOrNull() const
  209. {
  210. return isUndefined() || isNull();
  211. }
  212. inline bool JSValue::isCell() const
  213. {
  214. return tag() == CellTag;
  215. }
  216. inline bool JSValue::isInt32() const
  217. {
  218. return tag() == Int32Tag;
  219. }
  220. inline bool JSValue::isDouble() const
  221. {
  222. return tag() < LowestTag;
  223. }
  224. inline bool JSValue::isTrue() const
  225. {
  226. return tag() == BooleanTag && payload();
  227. }
  228. inline bool JSValue::isFalse() const
  229. {
  230. return tag() == BooleanTag && !payload();
  231. }
  232. inline uint32_t JSValue::tag() const
  233. {
  234. return u.asBits.tag;
  235. }
  236. inline int32_t JSValue::payload() const
  237. {
  238. return u.asBits.payload;
  239. }
  240. inline int32_t JSValue::asInt32() const
  241. {
  242. ASSERT(isInt32());
  243. return u.asBits.payload;
  244. }
  245. inline double JSValue::asDouble() const
  246. {
  247. ASSERT(isDouble());
  248. return u.asDouble;
  249. }
  250. ALWAYS_INLINE JSCell* JSValue::asCell() const
  251. {
  252. ASSERT(isCell());
  253. return reinterpret_cast<JSCell*>(u.asBits.payload);
  254. }
  255. ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d)
  256. {
  257. u.asDouble = d;
  258. }
  259. inline JSValue::JSValue(int i)
  260. {
  261. u.asBits.tag = Int32Tag;
  262. u.asBits.payload = i;
  263. }
  264. #if ENABLE(LLINT_C_LOOP)
  265. inline JSValue::JSValue(int32_t tag, int32_t payload)
  266. {
  267. u.asBits.tag = tag;
  268. u.asBits.payload = payload;
  269. }
  270. #endif
  271. inline bool JSValue::isNumber() const
  272. {
  273. return isInt32() || isDouble();
  274. }
  275. inline bool JSValue::isBoolean() const
  276. {
  277. return isTrue() || isFalse();
  278. }
  279. inline bool JSValue::asBoolean() const
  280. {
  281. ASSERT(isBoolean());
  282. return payload();
  283. }
  284. #else // !USE(JSVALUE32_64) i.e. USE(JSVALUE64)
  285. // 0x0 can never occur naturally because it has a tag of 00, indicating a pointer value, but a payload of 0x0, which is in the (invalid) zero page.
  286. inline JSValue::JSValue()
  287. {
  288. u.asInt64 = ValueEmpty;
  289. }
  290. // 0x4 can never occur naturally because it has a tag of 00, indicating a pointer value, but a payload of 0x4, which is in the (invalid) zero page.
  291. inline JSValue::JSValue(HashTableDeletedValueTag)
  292. {
  293. u.asInt64 = ValueDeleted;
  294. }
  295. inline JSValue::JSValue(JSCell* ptr)
  296. {
  297. u.asInt64 = reinterpret_cast<uintptr_t>(ptr);
  298. }
  299. inline JSValue::JSValue(const JSCell* ptr)
  300. {
  301. u.asInt64 = reinterpret_cast<uintptr_t>(const_cast<JSCell*>(ptr));
  302. }
  303. inline JSValue::operator bool() const
  304. {
  305. return u.asInt64;
  306. }
  307. inline bool JSValue::operator==(const JSValue& other) const
  308. {
  309. return u.asInt64 == other.u.asInt64;
  310. }
  311. inline bool JSValue::operator!=(const JSValue& other) const
  312. {
  313. return u.asInt64 != other.u.asInt64;
  314. }
  315. inline bool JSValue::isEmpty() const
  316. {
  317. return u.asInt64 == ValueEmpty;
  318. }
  319. inline bool JSValue::isUndefined() const
  320. {
  321. return asValue() == JSValue(JSUndefined);
  322. }
  323. inline bool JSValue::isNull() const
  324. {
  325. return asValue() == JSValue(JSNull);
  326. }
  327. inline bool JSValue::isTrue() const
  328. {
  329. return asValue() == JSValue(JSTrue);
  330. }
  331. inline bool JSValue::isFalse() const
  332. {
  333. return asValue() == JSValue(JSFalse);
  334. }
  335. inline bool JSValue::asBoolean() const
  336. {
  337. ASSERT(isBoolean());
  338. return asValue() == JSValue(JSTrue);
  339. }
  340. inline int32_t JSValue::asInt32() const
  341. {
  342. ASSERT(isInt32());
  343. return static_cast<int32_t>(u.asInt64);
  344. }
  345. inline bool JSValue::isDouble() const
  346. {
  347. return isNumber() && !isInt32();
  348. }
  349. inline JSValue::JSValue(JSNullTag)
  350. {
  351. u.asInt64 = ValueNull;
  352. }
  353. inline JSValue::JSValue(JSUndefinedTag)
  354. {
  355. u.asInt64 = ValueUndefined;
  356. }
  357. inline JSValue::JSValue(JSTrueTag)
  358. {
  359. u.asInt64 = ValueTrue;
  360. }
  361. inline JSValue::JSValue(JSFalseTag)
  362. {
  363. u.asInt64 = ValueFalse;
  364. }
  365. inline bool JSValue::isUndefinedOrNull() const
  366. {
  367. // Undefined and null share the same value, bar the 'undefined' bit in the extended tag.
  368. return (u.asInt64 & ~TagBitUndefined) == ValueNull;
  369. }
  370. inline bool JSValue::isBoolean() const
  371. {
  372. return (u.asInt64 & ~1) == ValueFalse;
  373. }
  374. inline bool JSValue::isCell() const
  375. {
  376. return !(u.asInt64 & TagMask);
  377. }
  378. inline bool JSValue::isInt32() const
  379. {
  380. return (u.asInt64 & TagTypeNumber) == TagTypeNumber;
  381. }
  382. inline int64_t reinterpretDoubleToInt64(double value)
  383. {
  384. return bitwise_cast<int64_t>(value);
  385. }
  386. inline double reinterpretInt64ToDouble(int64_t value)
  387. {
  388. return bitwise_cast<double>(value);
  389. }
  390. ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, double d)
  391. {
  392. u.asInt64 = reinterpretDoubleToInt64(d) + DoubleEncodeOffset;
  393. }
  394. inline JSValue::JSValue(int i)
  395. {
  396. u.asInt64 = TagTypeNumber | static_cast<uint32_t>(i);
  397. }
  398. inline double JSValue::asDouble() const
  399. {
  400. ASSERT(isDouble());
  401. return reinterpretInt64ToDouble(u.asInt64 - DoubleEncodeOffset);
  402. }
  403. inline bool JSValue::isNumber() const
  404. {
  405. return u.asInt64 & TagTypeNumber;
  406. }
  407. ALWAYS_INLINE JSCell* JSValue::asCell() const
  408. {
  409. ASSERT(isCell());
  410. return u.ptr;
  411. }
  412. #endif // USE(JSVALUE64)
  413. inline bool JSValue::isString() const
  414. {
  415. return isCell() && asCell()->isString();
  416. }
  417. inline bool JSValue::isPrimitive() const
  418. {
  419. return !isCell() || asCell()->isString();
  420. }
  421. inline bool JSValue::isGetterSetter() const
  422. {
  423. return isCell() && asCell()->isGetterSetter();
  424. }
  425. inline bool JSValue::isObject() const
  426. {
  427. return isCell() && asCell()->isObject();
  428. }
  429. inline bool JSValue::getString(ExecState* exec, String& s) const
  430. {
  431. return isCell() && asCell()->getString(exec, s);
  432. }
  433. inline String JSValue::getString(ExecState* exec) const
  434. {
  435. return isCell() ? asCell()->getString(exec) : String();
  436. }
  437. template <typename Base> String HandleConverter<Base, Unknown>::getString(ExecState* exec) const
  438. {
  439. return jsValue().getString(exec);
  440. }
  441. inline JSObject* JSValue::getObject() const
  442. {
  443. return isCell() ? asCell()->getObject() : 0;
  444. }
  445. ALWAYS_INLINE bool JSValue::getUInt32(uint32_t& v) const
  446. {
  447. if (isInt32()) {
  448. int32_t i = asInt32();
  449. v = static_cast<uint32_t>(i);
  450. return i >= 0;
  451. }
  452. if (isDouble()) {
  453. double d = asDouble();
  454. v = static_cast<uint32_t>(d);
  455. return v == d;
  456. }
  457. return false;
  458. }
  459. inline JSValue JSValue::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const
  460. {
  461. return isCell() ? asCell()->toPrimitive(exec, preferredType) : asValue();
  462. }
  463. inline bool JSValue::getPrimitiveNumber(ExecState* exec, double& number, JSValue& value)
  464. {
  465. if (isInt32()) {
  466. number = asInt32();
  467. value = *this;
  468. return true;
  469. }
  470. if (isDouble()) {
  471. number = asDouble();
  472. value = *this;
  473. return true;
  474. }
  475. if (isCell())
  476. return asCell()->getPrimitiveNumber(exec, number, value);
  477. if (isTrue()) {
  478. number = 1.0;
  479. value = *this;
  480. return true;
  481. }
  482. if (isFalse() || isNull()) {
  483. number = 0.0;
  484. value = *this;
  485. return true;
  486. }
  487. ASSERT(isUndefined());
  488. number = QNaN;
  489. value = *this;
  490. return true;
  491. }
  492. ALWAYS_INLINE double JSValue::toNumber(ExecState* exec) const
  493. {
  494. if (isInt32())
  495. return asInt32();
  496. if (isDouble())
  497. return asDouble();
  498. return toNumberSlowCase(exec);
  499. }
  500. inline JSObject* JSValue::toObject(ExecState* exec) const
  501. {
  502. return isCell() ? asCell()->toObject(exec, exec->lexicalGlobalObject()) : toObjectSlowCase(exec, exec->lexicalGlobalObject());
  503. }
  504. inline JSObject* JSValue::toObject(ExecState* exec, JSGlobalObject* globalObject) const
  505. {
  506. return isCell() ? asCell()->toObject(exec, globalObject) : toObjectSlowCase(exec, globalObject);
  507. }
  508. inline bool JSValue::isFunction() const
  509. {
  510. DEFINE_STATIC_CLASSINFO(JSFunction);
  511. DEFINE_STATIC_CLASSINFO(InternalFunction);
  512. return isCell() && (asCell()->inherits(sJSFunctionClassInfo) || asCell()->inherits(sInternalFunctionClassInfo));
  513. }
  514. // this method is here to be after the inline declaration of JSCell::inherits
  515. inline bool JSValue::inherits(const ClassInfo* classInfo) const
  516. {
  517. return isCell() && asCell()->inherits(classInfo);
  518. }
  519. inline JSObject* JSValue::toThisObject(ExecState* exec) const
  520. {
  521. return isCell() ? asCell()->methodTable()->toThisObject(asCell(), exec) : toThisObjectSlowCase(exec);
  522. }
  523. inline JSValue JSValue::get(ExecState* exec, PropertyName propertyName) const
  524. {
  525. PropertySlot slot(asValue());
  526. return get(exec, propertyName, slot);
  527. }
  528. inline JSValue JSValue::get(ExecState* exec, PropertyName propertyName, PropertySlot& slot) const
  529. {
  530. if (UNLIKELY(!isCell())) {
  531. JSObject* prototype = synthesizePrototype(exec);
  532. if (!prototype->getPropertySlot(exec, propertyName, slot))
  533. return jsUndefined();
  534. return slot.getValue(exec, propertyName);
  535. }
  536. JSCell* cell = asCell();
  537. while (true) {
  538. if (cell->fastGetOwnPropertySlot(exec, propertyName, slot))
  539. return slot.getValue(exec, propertyName);
  540. JSValue prototype = asObject(cell)->prototype();
  541. if (!prototype.isObject())
  542. return jsUndefined();
  543. cell = asObject(prototype);
  544. }
  545. }
  546. inline JSValue JSValue::get(ExecState* exec, unsigned propertyName) const
  547. {
  548. PropertySlot slot(asValue());
  549. return get(exec, propertyName, slot);
  550. }
  551. inline JSValue JSValue::get(ExecState* exec, unsigned propertyName, PropertySlot& slot) const
  552. {
  553. if (UNLIKELY(!isCell())) {
  554. JSObject* prototype = synthesizePrototype(exec);
  555. if (!prototype->getPropertySlot(exec, propertyName, slot))
  556. return jsUndefined();
  557. return slot.getValue(exec, propertyName);
  558. }
  559. JSCell* cell = const_cast<JSCell*>(asCell());
  560. while (true) {
  561. if (cell->methodTable()->getOwnPropertySlotByIndex(cell, exec, propertyName, slot))
  562. return slot.getValue(exec, propertyName);
  563. JSValue prototype = asObject(cell)->prototype();
  564. if (!prototype.isObject())
  565. return jsUndefined();
  566. cell = prototype.asCell();
  567. }
  568. }
  569. inline void JSValue::put(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
  570. {
  571. if (UNLIKELY(!isCell())) {
  572. putToPrimitive(exec, propertyName, value, slot);
  573. return;
  574. }
  575. asCell()->methodTable()->put(asCell(), exec, propertyName, value, slot);
  576. }
  577. inline void JSValue::putByIndex(ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow)
  578. {
  579. if (UNLIKELY(!isCell())) {
  580. putToPrimitiveByIndex(exec, propertyName, value, shouldThrow);
  581. return;
  582. }
  583. asCell()->methodTable()->putByIndex(asCell(), exec, propertyName, value, shouldThrow);
  584. }
  585. inline JSValue JSValue::structureOrUndefined() const
  586. {
  587. if (isCell())
  588. return JSValue(asCell()->structure());
  589. return jsUndefined();
  590. }
  591. // ECMA 11.9.3
  592. inline bool JSValue::equal(ExecState* exec, JSValue v1, JSValue v2)
  593. {
  594. if (v1.isInt32() && v2.isInt32())
  595. return v1 == v2;
  596. return equalSlowCase(exec, v1, v2);
  597. }
  598. ALWAYS_INLINE bool JSValue::equalSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2)
  599. {
  600. do {
  601. if (v1.isNumber() && v2.isNumber())
  602. return v1.asNumber() == v2.asNumber();
  603. bool s1 = v1.isString();
  604. bool s2 = v2.isString();
  605. if (s1 && s2)
  606. return asString(v1)->value(exec) == asString(v2)->value(exec);
  607. if (v1.isUndefinedOrNull()) {
  608. if (v2.isUndefinedOrNull())
  609. return true;
  610. if (!v2.isCell())
  611. return false;
  612. return v2.asCell()->structure()->masqueradesAsUndefined(exec->lexicalGlobalObject());
  613. }
  614. if (v2.isUndefinedOrNull()) {
  615. if (!v1.isCell())
  616. return false;
  617. return v1.asCell()->structure()->masqueradesAsUndefined(exec->lexicalGlobalObject());
  618. }
  619. if (v1.isObject()) {
  620. if (v2.isObject())
  621. return v1 == v2;
  622. JSValue p1 = v1.toPrimitive(exec);
  623. if (exec->hadException())
  624. return false;
  625. v1 = p1;
  626. if (v1.isInt32() && v2.isInt32())
  627. return v1 == v2;
  628. continue;
  629. }
  630. if (v2.isObject()) {
  631. JSValue p2 = v2.toPrimitive(exec);
  632. if (exec->hadException())
  633. return false;
  634. v2 = p2;
  635. if (v1.isInt32() && v2.isInt32())
  636. return v1 == v2;
  637. continue;
  638. }
  639. if (s1 || s2) {
  640. double d1 = v1.toNumber(exec);
  641. double d2 = v2.toNumber(exec);
  642. return d1 == d2;
  643. }
  644. if (v1.isBoolean()) {
  645. if (v2.isNumber())
  646. return static_cast<double>(v1.asBoolean()) == v2.asNumber();
  647. } else if (v2.isBoolean()) {
  648. if (v1.isNumber())
  649. return v1.asNumber() == static_cast<double>(v2.asBoolean());
  650. }
  651. return v1 == v2;
  652. } while (true);
  653. }
  654. // ECMA 11.9.3
  655. ALWAYS_INLINE bool JSValue::strictEqualSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2)
  656. {
  657. ASSERT(v1.isCell() && v2.isCell());
  658. if (v1.asCell()->isString() && v2.asCell()->isString())
  659. return asString(v1)->value(exec) == asString(v2)->value(exec);
  660. return v1 == v2;
  661. }
  662. inline bool JSValue::strictEqual(ExecState* exec, JSValue v1, JSValue v2)
  663. {
  664. if (v1.isInt32() && v2.isInt32())
  665. return v1 == v2;
  666. if (v1.isNumber() && v2.isNumber())
  667. return v1.asNumber() == v2.asNumber();
  668. if (!v1.isCell() || !v2.isCell())
  669. return v1 == v2;
  670. return strictEqualSlowCaseInline(exec, v1, v2);
  671. }
  672. inline TriState JSValue::pureToBoolean() const
  673. {
  674. if (isInt32())
  675. return asInt32() ? TrueTriState : FalseTriState;
  676. if (isDouble())
  677. return isNotZeroAndOrdered(asDouble()) ? TrueTriState : FalseTriState; // false for NaN
  678. if (isCell())
  679. return asCell()->pureToBoolean();
  680. return isTrue() ? TrueTriState : FalseTriState;
  681. }
  682. } // namespace JSC
  683. #endif // JSValueInlines_h