1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef builtin_intl_CommonFunctions_h
#define builtin_intl_CommonFunctions_h
#include "mozilla/Assertions.h"
#include "mozilla/TypeTraits.h"
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "builtin/intl/ICUStubs.h"
#include "js/RootingAPI.h"
#include "js/Vector.h"
#include "vm/StringType.h"
namespace js {
namespace intl {
/**
* Initialize a new Intl.* object using the named self-hosted function.
*/
extern bool InitializeObject(JSContext* cx, JS::Handle<JSObject*> obj,
JS::Handle<PropertyName*> initializer,
JS::Handle<JS::Value> locales,
JS::Handle<JS::Value> options);
enum class DateTimeFormatOptions {
Standard,
EnableMozExtensions,
};
/**
* Initialize an existing object as an Intl.* object using the named
* self-hosted function. This is only for a few old Intl.* constructors, for
* legacy reasons -- new ones should use the function above instead.
*/
extern bool LegacyInitializeObject(JSContext* cx, JS::Handle<JSObject*> obj,
JS::Handle<PropertyName*> initializer,
JS::Handle<JS::Value> thisValue,
JS::Handle<JS::Value> locales,
JS::Handle<JS::Value> options,
DateTimeFormatOptions dtfOptions,
JS::MutableHandle<JS::Value> result);
/**
* Returns the object holding the internal properties for obj.
*/
extern JSObject* GetInternalsObject(JSContext* cx, JS::Handle<JSObject*> obj);
/** Report an Intl internal error not directly tied to a spec step. */
extern void ReportInternalError(JSContext* cx);
static inline bool StringsAreEqual(const char* s1, const char* s2) {
return !strcmp(s1, s2);
}
static inline const char* IcuLocale(const char* locale) {
if (StringsAreEqual(locale, "und")) {
return ""; // ICU root locale
}
return locale;
}
extern UniqueChars EncodeLocale(JSContext* cx, JSString* locale);
// Starting with ICU 59, UChar defaults to char16_t.
static_assert(
mozilla::IsSame<UChar, char16_t>::value,
"SpiderMonkey doesn't support redefining UChar to a different type");
// The inline capacity we use for a Vector<char16_t>. Use this to ensure that
// our uses of ICU string functions, below and elsewhere, will try to fill the
// buffer's entire inline capacity before growing it and heap-allocating.
constexpr size_t INITIAL_CHAR_BUFFER_SIZE = 32;
template <typename ICUStringFunction, size_t InlineCapacity>
static int32_t CallICU(JSContext* cx, const ICUStringFunction& strFn,
Vector<char16_t, InlineCapacity>& chars) {
MOZ_ASSERT(chars.length() >= InlineCapacity);
UErrorCode status = U_ZERO_ERROR;
int32_t size = strFn(chars.begin(), chars.length(), &status);
if (status == U_BUFFER_OVERFLOW_ERROR) {
MOZ_ASSERT(size >= 0);
if (!chars.resize(size_t(size))) {
return -1;
}
status = U_ZERO_ERROR;
strFn(chars.begin(), size, &status);
}
if (U_FAILURE(status)) {
ReportInternalError(cx);
return -1;
}
MOZ_ASSERT(size >= 0);
return size;
}
template <typename ICUStringFunction>
static JSString* CallICU(JSContext* cx, const ICUStringFunction& strFn) {
Vector<char16_t, INITIAL_CHAR_BUFFER_SIZE> chars(cx);
MOZ_ALWAYS_TRUE(chars.resize(INITIAL_CHAR_BUFFER_SIZE));
int32_t size = CallICU(cx, strFn, chars);
if (size < 0) {
return nullptr;
}
return NewStringCopyN<CanGC>(cx, chars.begin(), size_t(size));
}
// CountAvailable and GetAvailable describe the signatures used for ICU API
// to determine available locales for various functionality.
using CountAvailable = int32_t (*)();
using GetAvailable = const char* (*)(int32_t localeIndex);
/**
* Return an object whose own property names are the locales indicated as
* available by |countAvailable| that provides an overall count, and by
* |getAvailable| that when called passing a number less than that count,
* returns the corresponding locale as a borrowed string. For example:
*
* RootedValue v(cx);
* if (!GetAvailableLocales(cx, unum_countAvailable, unum_getAvailable, &v)) {
* return false;
* }
*/
extern bool GetAvailableLocales(JSContext* cx, CountAvailable countAvailable,
GetAvailable getAvailable,
JS::MutableHandle<JS::Value> result);
} // namespace intl
} // namespace js
#endif /* builtin_intl_CommonFunctions_h */