1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  * vim: set ts=8 sts=2 et sw=2 tw=80:
3  */
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 
8 #include "jsnum.h"
9 
10 #include "jsapi-tests/tests.h"
11 #include "vm/JSContext.h"
12 #include "vm/Realm.h"
13 
14 #include "vm/StringType-inl.h"
15 
16 static const struct TestPair {
17   uint32_t num;
18   const char* expected;
19 } tests[] = {
20     {0, "0"},
21     {1, "1"},
22     {2, "2"},
23     {9, "9"},
24     {10, "10"},
25     {15, "15"},
26     {16, "16"},
27     {17, "17"},
28     {99, "99"},
29     {100, "100"},
30     {255, "255"},
31     {256, "256"},
32     {257, "257"},
33     {999, "999"},
34     {1000, "1000"},
35     {4095, "4095"},
36     {4096, "4096"},
37     {9999, "9999"},
38     {1073741823, "1073741823"},
39     {1073741824, "1073741824"},
40     {1073741825, "1073741825"},
41     {2147483647, "2147483647"},
42     {2147483648u, "2147483648"},
43     {2147483649u, "2147483649"},
44     {4294967294u, "4294967294"},
45 };
46 
BEGIN_TEST(testIndexToString)47 BEGIN_TEST(testIndexToString) {
48   for (const auto& test : tests) {
49     uint32_t u = test.num;
50     JSString* str = js::IndexToString(cx, u);
51     CHECK(str);
52 
53     if (!js::StaticStrings::hasUint(u)) {
54       CHECK(cx->realm()->dtoaCache.lookup(10, u) == str);
55     }
56 
57     bool match = false;
58     CHECK(JS_StringEqualsAscii(cx, str, test.expected, &match));
59     CHECK(match);
60   }
61 
62   return true;
63 }
64 END_TEST(testIndexToString)
65 
BEGIN_TEST(testStringIsIndex)66 BEGIN_TEST(testStringIsIndex) {
67   for (const auto& test : tests) {
68     uint32_t u = test.num;
69     JSLinearString* str = js::IndexToString(cx, u);
70     CHECK(str);
71 
72     uint32_t n;
73     CHECK(str->isIndex(&n));
74     CHECK(u == n);
75   }
76 
77   return true;
78 }
79 END_TEST(testStringIsIndex)
80 
BEGIN_TEST(testStringToPropertyName)81 BEGIN_TEST(testStringToPropertyName) {
82   uint32_t index;
83 
84   static const char16_t hiChars[] = {'h', 'i'};
85   JSLinearString* hiStr = NewString(cx, hiChars);
86   CHECK(hiStr);
87   CHECK(!hiStr->isIndex(&index));
88   CHECK(hiStr->toPropertyName(cx) != nullptr);
89 
90   static const char16_t maxChars[] = {'4', '2', '9', '4', '9',
91                                       '6', '7', '2', '9', '4'};
92   JSLinearString* maxStr = NewString(cx, maxChars);
93   CHECK(maxStr);
94   CHECK(maxStr->isIndex(&index));
95   CHECK(index == UINT32_MAX - 1);
96 
97   static const char16_t maxPlusOneChars[] = {'4', '2', '9', '4', '9',
98                                              '6', '7', '2', '9', '5'};
99   JSLinearString* maxPlusOneStr = NewString(cx, maxPlusOneChars);
100   CHECK(maxPlusOneStr);
101   CHECK(!maxPlusOneStr->isIndex(&index));
102   CHECK(maxPlusOneStr->toPropertyName(cx) != nullptr);
103 
104   static const char16_t maxNonUint32Chars[] = {'4', '2', '9', '4', '9',
105                                                '6', '7', '2', '9', '6'};
106   JSLinearString* maxNonUint32Str = NewString(cx, maxNonUint32Chars);
107   CHECK(maxNonUint32Str);
108   CHECK(!maxNonUint32Str->isIndex(&index));
109   CHECK(maxNonUint32Str->toPropertyName(cx) != nullptr);
110 
111   return true;
112 }
113 
114 template <size_t N>
NewString(JSContext * cx,const char16_t (& chars)[N])115 static JSLinearString* NewString(JSContext* cx, const char16_t (&chars)[N]) {
116   return js::NewStringCopyN<js::CanGC>(cx, chars, N);
117 }
118 
119 END_TEST(testStringToPropertyName)
120