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