Conversions.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  2. * vim: set ts=8 sts=4 et sw=4 tw=99:
  3. * This Source Code Form is subject to the terms of the Mozilla Public
  4. * License, v. 2.0. If a copy of the MPL was not distributed with this
  5. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6. /* ECMAScript conversion operations. */
  7. #ifndef js_Conversions_h
  8. #define js_Conversions_h
  9. #include "mozilla/Casting.h"
  10. #include "mozilla/FloatingPoint.h"
  11. #include "mozilla/TypeTraits.h"
  12. #include <math.h>
  13. #include "jspubtd.h"
  14. #include "js/RootingAPI.h"
  15. #include "js/Value.h"
  16. struct JSContext;
  17. namespace js {
  18. /* DO NOT CALL THIS. Use JS::ToBoolean. */
  19. extern JS_PUBLIC_API(bool)
  20. ToBooleanSlow(JS::HandleValue v);
  21. /* DO NOT CALL THIS. Use JS::ToNumber. */
  22. extern JS_PUBLIC_API(bool)
  23. ToNumberSlow(JSContext* cx, JS::HandleValue v, double* dp);
  24. /* DO NOT CALL THIS. Use JS::ToInt8. */
  25. extern JS_PUBLIC_API(bool)
  26. ToInt8Slow(JSContext *cx, JS::HandleValue v, int8_t *out);
  27. /* DO NOT CALL THIS. Use JS::ToUint8. */
  28. extern JS_PUBLIC_API(bool)
  29. ToUint8Slow(JSContext *cx, JS::HandleValue v, uint8_t *out);
  30. /* DO NOT CALL THIS. Use JS::ToInt16. */
  31. extern JS_PUBLIC_API(bool)
  32. ToInt16Slow(JSContext *cx, JS::HandleValue v, int16_t *out);
  33. /* DO NOT CALL THIS. Use JS::ToInt32. */
  34. extern JS_PUBLIC_API(bool)
  35. ToInt32Slow(JSContext* cx, JS::HandleValue v, int32_t* out);
  36. /* DO NOT CALL THIS. Use JS::ToUint32. */
  37. extern JS_PUBLIC_API(bool)
  38. ToUint32Slow(JSContext* cx, JS::HandleValue v, uint32_t* out);
  39. /* DO NOT CALL THIS. Use JS::ToUint16. */
  40. extern JS_PUBLIC_API(bool)
  41. ToUint16Slow(JSContext* cx, JS::HandleValue v, uint16_t* out);
  42. /* DO NOT CALL THIS. Use JS::ToInt64. */
  43. extern JS_PUBLIC_API(bool)
  44. ToInt64Slow(JSContext* cx, JS::HandleValue v, int64_t* out);
  45. /* DO NOT CALL THIS. Use JS::ToUint64. */
  46. extern JS_PUBLIC_API(bool)
  47. ToUint64Slow(JSContext* cx, JS::HandleValue v, uint64_t* out);
  48. /* DO NOT CALL THIS. Use JS::ToString. */
  49. extern JS_PUBLIC_API(JSString*)
  50. ToStringSlow(JSContext* cx, JS::HandleValue v);
  51. /* DO NOT CALL THIS. Use JS::ToObject. */
  52. extern JS_PUBLIC_API(JSObject*)
  53. ToObjectSlow(JSContext* cx, JS::HandleValue v, bool reportScanStack);
  54. } // namespace js
  55. namespace JS {
  56. namespace detail {
  57. #ifdef JS_DEBUG
  58. /**
  59. * Assert that we're not doing GC on cx, that we're in a request as
  60. * needed, and that the compartments for cx and v are correct.
  61. * Also check that GC would be safe at this point.
  62. */
  63. extern JS_PUBLIC_API(void)
  64. AssertArgumentsAreSane(JSContext* cx, HandleValue v);
  65. #else
  66. inline void AssertArgumentsAreSane(JSContext* cx, HandleValue v)
  67. {}
  68. #endif /* JS_DEBUG */
  69. } // namespace detail
  70. /**
  71. * ES6 draft 20141224, 7.1.1, second algorithm.
  72. *
  73. * Most users shouldn't call this -- use JS::ToBoolean, ToNumber, or ToString
  74. * instead. This will typically only be called from custom convert hooks that
  75. * wish to fall back to the ES6 default conversion behavior shared by most
  76. * objects in JS, codified as OrdinaryToPrimitive.
  77. */
  78. extern JS_PUBLIC_API(bool)
  79. OrdinaryToPrimitive(JSContext* cx, HandleObject obj, JSType type, MutableHandleValue vp);
  80. /* ES6 draft 20141224, 7.1.2. */
  81. MOZ_ALWAYS_INLINE bool
  82. ToBoolean(HandleValue v)
  83. {
  84. if (v.isBoolean())
  85. return v.toBoolean();
  86. if (v.isInt32())
  87. return v.toInt32() != 0;
  88. if (v.isNullOrUndefined())
  89. return false;
  90. if (v.isDouble()) {
  91. double d = v.toDouble();
  92. return !mozilla::IsNaN(d) && d != 0;
  93. }
  94. if (v.isSymbol())
  95. return true;
  96. /* The slow path handles strings and objects. */
  97. return js::ToBooleanSlow(v);
  98. }
  99. /* ES6 draft 20141224, 7.1.3. */
  100. MOZ_ALWAYS_INLINE bool
  101. ToNumber(JSContext* cx, HandleValue v, double* out)
  102. {
  103. detail::AssertArgumentsAreSane(cx, v);
  104. if (v.isNumber()) {
  105. *out = v.toNumber();
  106. return true;
  107. }
  108. return js::ToNumberSlow(cx, v, out);
  109. }
  110. /* ES6 draft 20141224, ToInteger (specialized for doubles). */
  111. inline double
  112. ToInteger(double d)
  113. {
  114. if (d == 0)
  115. return d;
  116. if (!mozilla::IsFinite(d)) {
  117. if (mozilla::IsNaN(d))
  118. return 0;
  119. return d;
  120. }
  121. return d < 0 ? ceil(d) : floor(d);
  122. }
  123. /* ES6 draft 20141224, 7.1.5. */
  124. MOZ_ALWAYS_INLINE bool
  125. ToInt32(JSContext* cx, JS::HandleValue v, int32_t* out)
  126. {
  127. detail::AssertArgumentsAreSane(cx, v);
  128. if (v.isInt32()) {
  129. *out = v.toInt32();
  130. return true;
  131. }
  132. return js::ToInt32Slow(cx, v, out);
  133. }
  134. /* ES6 draft 20141224, 7.1.6. */
  135. MOZ_ALWAYS_INLINE bool
  136. ToUint32(JSContext* cx, HandleValue v, uint32_t* out)
  137. {
  138. detail::AssertArgumentsAreSane(cx, v);
  139. if (v.isInt32()) {
  140. *out = uint32_t(v.toInt32());
  141. return true;
  142. }
  143. return js::ToUint32Slow(cx, v, out);
  144. }
  145. /* ES6 draft 20141224, 7.1.7. */
  146. MOZ_ALWAYS_INLINE bool
  147. ToInt16(JSContext *cx, JS::HandleValue v, int16_t *out)
  148. {
  149. detail::AssertArgumentsAreSane(cx, v);
  150. if (v.isInt32()) {
  151. *out = int16_t(v.toInt32());
  152. return true;
  153. }
  154. return js::ToInt16Slow(cx, v, out);
  155. }
  156. /* ES6 draft 20141224, 7.1.8. */
  157. MOZ_ALWAYS_INLINE bool
  158. ToUint16(JSContext* cx, HandleValue v, uint16_t* out)
  159. {
  160. detail::AssertArgumentsAreSane(cx, v);
  161. if (v.isInt32()) {
  162. *out = uint16_t(v.toInt32());
  163. return true;
  164. }
  165. return js::ToUint16Slow(cx, v, out);
  166. }
  167. /* ES6 draft 20141224, 7.1.9 */
  168. MOZ_ALWAYS_INLINE bool
  169. ToInt8(JSContext *cx, JS::HandleValue v, int8_t *out)
  170. {
  171. detail::AssertArgumentsAreSane(cx, v);
  172. if (v.isInt32()) {
  173. *out = int8_t(v.toInt32());
  174. return true;
  175. }
  176. return js::ToInt8Slow(cx, v, out);
  177. }
  178. /* ES6 ECMA-262, 7.1.10 */
  179. MOZ_ALWAYS_INLINE bool
  180. ToUint8(JSContext *cx, JS::HandleValue v, uint8_t *out)
  181. {
  182. detail::AssertArgumentsAreSane(cx, v);
  183. if (v.isInt32()) {
  184. *out = uint8_t(v.toInt32());
  185. return true;
  186. }
  187. return js::ToUint8Slow(cx, v, out);
  188. }
  189. /*
  190. * Non-standard, with behavior similar to that of ToInt32, except in its
  191. * producing an int64_t.
  192. */
  193. MOZ_ALWAYS_INLINE bool
  194. ToInt64(JSContext* cx, HandleValue v, int64_t* out)
  195. {
  196. detail::AssertArgumentsAreSane(cx, v);
  197. if (v.isInt32()) {
  198. *out = int64_t(v.toInt32());
  199. return true;
  200. }
  201. return js::ToInt64Slow(cx, v, out);
  202. }
  203. /*
  204. * Non-standard, with behavior similar to that of ToUint32, except in its
  205. * producing a uint64_t.
  206. */
  207. MOZ_ALWAYS_INLINE bool
  208. ToUint64(JSContext* cx, HandleValue v, uint64_t* out)
  209. {
  210. detail::AssertArgumentsAreSane(cx, v);
  211. if (v.isInt32()) {
  212. *out = uint64_t(v.toInt32());
  213. return true;
  214. }
  215. return js::ToUint64Slow(cx, v, out);
  216. }
  217. /* ES6 draft 20141224, 7.1.12. */
  218. MOZ_ALWAYS_INLINE JSString*
  219. ToString(JSContext* cx, HandleValue v)
  220. {
  221. detail::AssertArgumentsAreSane(cx, v);
  222. if (v.isString())
  223. return v.toString();
  224. return js::ToStringSlow(cx, v);
  225. }
  226. /* ES6 draft 20141224, 7.1.13. */
  227. inline JSObject*
  228. ToObject(JSContext* cx, HandleValue v)
  229. {
  230. detail::AssertArgumentsAreSane(cx, v);
  231. if (v.isObject())
  232. return &v.toObject();
  233. return js::ToObjectSlow(cx, v, false);
  234. }
  235. namespace detail {
  236. /*
  237. * Convert a double value to ResultType (an unsigned integral type) using
  238. * ECMAScript-style semantics (that is, in like manner to how ECMAScript's
  239. * ToInt32 converts to int32_t).
  240. *
  241. * If d is infinite or NaN, return 0.
  242. * Otherwise compute d2 = sign(d) * floor(abs(d)), and return the ResultType
  243. * value congruent to d2 mod 2**(bit width of ResultType).
  244. *
  245. * The algorithm below is inspired by that found in
  246. * <http://trac.webkit.org/changeset/67825/trunk/JavaScriptCore/runtime/JSValue.cpp>
  247. * but has been generalized to all integer widths.
  248. */
  249. template<typename ResultType>
  250. inline ResultType
  251. ToUintWidth(double d)
  252. {
  253. static_assert(mozilla::IsUnsigned<ResultType>::value,
  254. "ResultType must be an unsigned type");
  255. uint64_t bits = mozilla::BitwiseCast<uint64_t>(d);
  256. unsigned DoubleExponentShift = mozilla::FloatingPoint<double>::kExponentShift;
  257. // Extract the exponent component. (Be careful here! It's not technically
  258. // the exponent in NaN, infinities, and subnormals.)
  259. int_fast16_t exp =
  260. int_fast16_t((bits & mozilla::FloatingPoint<double>::kExponentBits) >> DoubleExponentShift) -
  261. int_fast16_t(mozilla::FloatingPoint<double>::kExponentBias);
  262. // If the exponent's less than zero, abs(d) < 1, so the result is 0. (This
  263. // also handles subnormals.)
  264. if (exp < 0)
  265. return 0;
  266. uint_fast16_t exponent = mozilla::AssertedCast<uint_fast16_t>(exp);
  267. // If the exponent is greater than or equal to the bits of precision of a
  268. // double plus ResultType's width, the number is either infinite, NaN, or
  269. // too large to have lower-order bits in the congruent value. (Example:
  270. // 2**84 is exactly representable as a double. The next exact double is
  271. // 2**84 + 2**32. Thus if ResultType is int32_t, an exponent >= 84 implies
  272. // floor(abs(d)) == 0 mod 2**32.) Return 0 in all these cases.
  273. const size_t ResultWidth = CHAR_BIT * sizeof(ResultType);
  274. if (exponent >= DoubleExponentShift + ResultWidth)
  275. return 0;
  276. // The significand contains the bits that will determine the final result.
  277. // Shift those bits left or right, according to the exponent, to their
  278. // locations in the unsigned binary representation of floor(abs(d)).
  279. static_assert(sizeof(ResultType) <= sizeof(uint64_t),
  280. "Left-shifting below would lose upper bits");
  281. ResultType result = (exponent > DoubleExponentShift)
  282. ? ResultType(bits << (exponent - DoubleExponentShift))
  283. : ResultType(bits >> (DoubleExponentShift - exponent));
  284. // Two further complications remain. First, |result| may contain bogus
  285. // sign/exponent bits. Second, IEEE-754 numbers' significands (excluding
  286. // subnormals, but we already handled those) have an implicit leading 1
  287. // which may affect the final result.
  288. //
  289. // It may appear that there's complexity here depending on how ResultWidth
  290. // and DoubleExponentShift relate, but it turns out there's not.
  291. //
  292. // Assume ResultWidth < DoubleExponentShift:
  293. // Only right-shifts leave bogus bits in |result|. For this to happen,
  294. // we must right-shift by > |DoubleExponentShift - ResultWidth|, implying
  295. // |exponent < ResultWidth|.
  296. // The implicit leading bit only matters if it appears in the final
  297. // result -- if |2**exponent mod 2**ResultWidth != 0|. This implies
  298. // |exponent < ResultWidth|.
  299. // Otherwise assume ResultWidth >= DoubleExponentShift:
  300. // Any left-shift less than |ResultWidth - DoubleExponentShift| leaves
  301. // bogus bits in |result|. This implies |exponent < ResultWidth|. Any
  302. // right-shift less than |ResultWidth| does too, which implies
  303. // |DoubleExponentShift - ResultWidth < exponent|. By assumption, then,
  304. // |exponent| is negative, but we excluded that above. So bogus bits
  305. // need only |exponent < ResultWidth|.
  306. // The implicit leading bit matters identically to the other case, so
  307. // again, |exponent < ResultWidth|.
  308. if (exponent < ResultWidth) {
  309. ResultType implicitOne = ResultType(1) << exponent;
  310. result &= implicitOne - 1; // remove bogus bits
  311. result += implicitOne; // add the implicit bit
  312. }
  313. // Compute the congruent value in the signed range.
  314. return (bits & mozilla::FloatingPoint<double>::kSignBit) ? ~result + 1 : result;
  315. }
  316. template<typename ResultType>
  317. inline ResultType
  318. ToIntWidth(double d)
  319. {
  320. static_assert(mozilla::IsSigned<ResultType>::value,
  321. "ResultType must be a signed type");
  322. const ResultType MaxValue = (1ULL << (CHAR_BIT * sizeof(ResultType) - 1)) - 1;
  323. const ResultType MinValue = -MaxValue - 1;
  324. typedef typename mozilla::MakeUnsigned<ResultType>::Type UnsignedResult;
  325. UnsignedResult u = ToUintWidth<UnsignedResult>(d);
  326. if (u <= UnsignedResult(MaxValue))
  327. return static_cast<ResultType>(u);
  328. return (MinValue + static_cast<ResultType>(u - MaxValue)) - 1;
  329. }
  330. } // namespace detail
  331. /* ES5 9.5 ToInt32 (specialized for doubles). */
  332. inline int32_t
  333. ToInt32(double d)
  334. {
  335. // clang crashes compiling this when targeting arm:
  336. // https://llvm.org/bugs/show_bug.cgi?id=22974
  337. #if defined (__arm__) && defined (__GNUC__) && !defined(__clang__)
  338. int32_t i;
  339. uint32_t tmp0;
  340. uint32_t tmp1;
  341. uint32_t tmp2;
  342. asm (
  343. // We use a pure integer solution here. In the 'softfp' ABI, the argument
  344. // will start in r0 and r1, and VFP can't do all of the necessary ECMA
  345. // conversions by itself so some integer code will be required anyway. A
  346. // hybrid solution is faster on A9, but this pure integer solution is
  347. // notably faster for A8.
  348. // %0 is the result register, and may alias either of the %[QR]1 registers.
  349. // %Q4 holds the lower part of the mantissa.
  350. // %R4 holds the sign, exponent, and the upper part of the mantissa.
  351. // %1, %2 and %3 are used as temporary values.
  352. // Extract the exponent.
  353. " mov %1, %R4, LSR #20\n"
  354. " bic %1, %1, #(1 << 11)\n" // Clear the sign.
  355. // Set the implicit top bit of the mantissa. This clobbers a bit of the
  356. // exponent, but we have already extracted that.
  357. " orr %R4, %R4, #(1 << 20)\n"
  358. // Special Cases
  359. // We should return zero in the following special cases:
  360. // - Exponent is 0x000 - 1023: +/-0 or subnormal.
  361. // - Exponent is 0x7ff - 1023: +/-INFINITY or NaN
  362. // - This case is implicitly handled by the standard code path anyway,
  363. // as shifting the mantissa up by the exponent will result in '0'.
  364. //
  365. // The result is composed of the mantissa, prepended with '1' and
  366. // bit-shifted left by the (decoded) exponent. Note that because the r1[20]
  367. // is the bit with value '1', r1 is effectively already shifted (left) by
  368. // 20 bits, and r0 is already shifted by 52 bits.
  369. // Adjust the exponent to remove the encoding offset. If the decoded
  370. // exponent is negative, quickly bail out with '0' as such values round to
  371. // zero anyway. This also catches +/-0 and subnormals.
  372. " sub %1, %1, #0xff\n"
  373. " subs %1, %1, #0x300\n"
  374. " bmi 8f\n"
  375. // %1 = (decoded) exponent >= 0
  376. // %R4 = upper mantissa and sign
  377. // ---- Lower Mantissa ----
  378. " subs %3, %1, #52\n" // Calculate exp-52
  379. " bmi 1f\n"
  380. // Shift r0 left by exp-52.
  381. // Ensure that we don't overflow ARM's 8-bit shift operand range.
  382. // We need to handle anything up to an 11-bit value here as we know that
  383. // 52 <= exp <= 1024 (0x400). Any shift beyond 31 bits results in zero
  384. // anyway, so as long as we don't touch the bottom 5 bits, we can use
  385. // a logical OR to push long shifts into the 32 <= (exp&0xff) <= 255 range.
  386. " bic %2, %3, #0xff\n"
  387. " orr %3, %3, %2, LSR #3\n"
  388. // We can now perform a straight shift, avoiding the need for any
  389. // conditional instructions or extra branches.
  390. " mov %Q4, %Q4, LSL %3\n"
  391. " b 2f\n"
  392. "1:\n" // Shift r0 right by 52-exp.
  393. // We know that 0 <= exp < 52, and we can shift up to 255 bits so 52-exp
  394. // will always be a valid shift and we can sk%3 the range check for this case.
  395. " rsb %3, %1, #52\n"
  396. " mov %Q4, %Q4, LSR %3\n"
  397. // %1 = (decoded) exponent
  398. // %R4 = upper mantissa and sign
  399. // %Q4 = partially-converted integer
  400. "2:\n"
  401. // ---- Upper Mantissa ----
  402. // This is much the same as the lower mantissa, with a few different
  403. // boundary checks and some masking to hide the exponent & sign bit in the
  404. // upper word.
  405. // Note that the upper mantissa is pre-shifted by 20 in %R4, but we shift
  406. // it left more to remove the sign and exponent so it is effectively
  407. // pre-shifted by 31 bits.
  408. " subs %3, %1, #31\n" // Calculate exp-31
  409. " mov %1, %R4, LSL #11\n" // Re-use %1 as a temporary register.
  410. " bmi 3f\n"
  411. // Shift %R4 left by exp-31.
  412. // Avoid overflowing the 8-bit shift range, as before.
  413. " bic %2, %3, #0xff\n"
  414. " orr %3, %3, %2, LSR #3\n"
  415. // Perform the shift.
  416. " mov %2, %1, LSL %3\n"
  417. " b 4f\n"
  418. "3:\n" // Shift r1 right by 31-exp.
  419. // We know that 0 <= exp < 31, and we can shift up to 255 bits so 31-exp
  420. // will always be a valid shift and we can skip the range check for this case.
  421. " rsb %3, %3, #0\n" // Calculate 31-exp from -(exp-31)
  422. " mov %2, %1, LSR %3\n" // Thumb-2 can't do "LSR %3" in "orr".
  423. // %Q4 = partially-converted integer (lower)
  424. // %R4 = upper mantissa and sign
  425. // %2 = partially-converted integer (upper)
  426. "4:\n"
  427. // Combine the converted parts.
  428. " orr %Q4, %Q4, %2\n"
  429. // Negate the result if we have to, and move it to %0 in the process. To
  430. // avoid conditionals, we can do this by inverting on %R4[31], then adding
  431. // %R4[31]>>31.
  432. " eor %Q4, %Q4, %R4, ASR #31\n"
  433. " add %0, %Q4, %R4, LSR #31\n"
  434. " b 9f\n"
  435. "8:\n"
  436. // +/-INFINITY, +/-0, subnormals, NaNs, and anything else out-of-range that
  437. // will result in a conversion of '0'.
  438. " mov %0, #0\n"
  439. "9:\n"
  440. : "=r" (i), "=&r" (tmp0), "=&r" (tmp1), "=&r" (tmp2), "=&r" (d)
  441. : "4" (d)
  442. : "cc"
  443. );
  444. return i;
  445. #else
  446. return detail::ToIntWidth<int32_t>(d);
  447. #endif
  448. }
  449. /* ES5 9.6 (specialized for doubles). */
  450. inline uint32_t
  451. ToUint32(double d)
  452. {
  453. return detail::ToUintWidth<uint32_t>(d);
  454. }
  455. /* WEBIDL 4.2.4 */
  456. inline int8_t
  457. ToInt8(double d)
  458. {
  459. return detail::ToIntWidth<int8_t>(d);
  460. }
  461. /* ECMA-262 7.1.10 ToUInt8() specialized for doubles. */
  462. inline int8_t
  463. ToUint8(double d)
  464. {
  465. return detail::ToUintWidth<uint8_t>(d);
  466. }
  467. /* WEBIDL 4.2.6 */
  468. inline int16_t
  469. ToInt16(double d)
  470. {
  471. return detail::ToIntWidth<int16_t>(d);
  472. }
  473. inline uint16_t
  474. ToUint16(double d)
  475. {
  476. return detail::ToUintWidth<uint16_t>(d);
  477. }
  478. /* WEBIDL 4.2.10 */
  479. inline int64_t
  480. ToInt64(double d)
  481. {
  482. return detail::ToIntWidth<int64_t>(d);
  483. }
  484. /* WEBIDL 4.2.11 */
  485. inline uint64_t
  486. ToUint64(double d)
  487. {
  488. return detail::ToUintWidth<uint64_t>(d);
  489. }
  490. } // namespace JS
  491. #endif /* js_Conversions_h */