Source code

Revision control

Other Tools

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
* 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
#ifndef builtin_intl_CommonFunctions_h
8
#define builtin_intl_CommonFunctions_h
9
10
#include "mozilla/Assertions.h"
11
#include "mozilla/TypeTraits.h"
12
13
#include <stddef.h>
14
#include <stdint.h>
15
#include <string.h>
16
17
#include "js/RootingAPI.h"
18
#include "js/Vector.h"
19
#include "unicode/utypes.h"
20
#include "vm/StringType.h"
21
22
namespace js {
23
24
namespace intl {
25
26
/**
27
* Initialize a new Intl.* object using the named self-hosted function.
28
*/
29
extern bool InitializeObject(JSContext* cx, JS::Handle<JSObject*> obj,
30
JS::Handle<PropertyName*> initializer,
31
JS::Handle<JS::Value> locales,
32
JS::Handle<JS::Value> options);
33
34
enum class DateTimeFormatOptions {
35
Standard,
36
EnableMozExtensions,
37
};
38
39
/**
40
* Initialize an existing object as an Intl.* object using the named
41
* self-hosted function. This is only for a few old Intl.* constructors, for
42
* legacy reasons -- new ones should use the function above instead.
43
*/
44
extern bool LegacyInitializeObject(JSContext* cx, JS::Handle<JSObject*> obj,
45
JS::Handle<PropertyName*> initializer,
46
JS::Handle<JS::Value> thisValue,
47
JS::Handle<JS::Value> locales,
48
JS::Handle<JS::Value> options,
49
DateTimeFormatOptions dtfOptions,
50
JS::MutableHandle<JS::Value> result);
51
52
/**
53
* Returns the object holding the internal properties for obj.
54
*/
55
extern JSObject* GetInternalsObject(JSContext* cx, JS::Handle<JSObject*> obj);
56
57
/** Report an Intl internal error not directly tied to a spec step. */
58
extern void ReportInternalError(JSContext* cx);
59
60
static inline bool StringsAreEqual(const char* s1, const char* s2) {
61
return !strcmp(s1, s2);
62
}
63
64
/**
65
* The last-ditch locale is used if none of the available locales satisfies a
66
* request. "en-GB" is used based on the assumptions that English is the most
67
* common second language, that both en-GB and en-US are normally available in
68
* an implementation, and that en-GB is more representative of the English used
69
* in other locales.
70
*/
71
static inline const char* LastDitchLocale() { return "en-GB"; }
72
73
/**
74
* Certain old, commonly-used language tags that lack a script, are expected to
75
* nonetheless imply one. This object maps these old-style tags to modern
76
* equivalents.
77
*/
78
struct OldStyleLanguageTagMapping {
79
const char* const oldStyle;
80
const char* const modernStyle;
81
82
// Provide a constructor to catch missing initializers in the mappings array.
83
constexpr OldStyleLanguageTagMapping(const char* oldStyle,
84
const char* modernStyle)
85
: oldStyle(oldStyle), modernStyle(modernStyle) {}
86
};
87
88
extern const OldStyleLanguageTagMapping oldStyleLanguageTagMappings[5];
89
90
static inline const char* IcuLocale(const char* locale) {
91
if (StringsAreEqual(locale, "und")) {
92
return ""; // ICU root locale
93
}
94
95
return locale;
96
}
97
98
extern UniqueChars EncodeLocale(JSContext* cx, JSString* locale);
99
100
// Starting with ICU 59, UChar defaults to char16_t.
101
static_assert(
102
mozilla::IsSame<UChar, char16_t>::value,
103
"SpiderMonkey doesn't support redefining UChar to a different type");
104
105
// The inline capacity we use for a Vector<char16_t>. Use this to ensure that
106
// our uses of ICU string functions, below and elsewhere, will try to fill the
107
// buffer's entire inline capacity before growing it and heap-allocating.
108
constexpr size_t INITIAL_CHAR_BUFFER_SIZE = 32;
109
110
template <typename ICUStringFunction, typename CharT, size_t InlineCapacity>
111
static int32_t CallICU(JSContext* cx, const ICUStringFunction& strFn,
112
Vector<CharT, InlineCapacity>& chars) {
113
MOZ_ASSERT(chars.length() >= InlineCapacity);
114
115
UErrorCode status = U_ZERO_ERROR;
116
int32_t size = strFn(chars.begin(), chars.length(), &status);
117
if (status == U_BUFFER_OVERFLOW_ERROR) {
118
MOZ_ASSERT(size >= 0);
119
if (!chars.resize(size_t(size))) {
120
return -1;
121
}
122
status = U_ZERO_ERROR;
123
strFn(chars.begin(), size, &status);
124
}
125
if (U_FAILURE(status)) {
126
ReportInternalError(cx);
127
return -1;
128
}
129
130
MOZ_ASSERT(size >= 0);
131
return size;
132
}
133
134
template <typename ICUStringFunction>
135
static JSString* CallICU(JSContext* cx, const ICUStringFunction& strFn) {
136
Vector<char16_t, INITIAL_CHAR_BUFFER_SIZE> chars(cx);
137
MOZ_ALWAYS_TRUE(chars.resize(INITIAL_CHAR_BUFFER_SIZE));
138
139
int32_t size = CallICU(cx, strFn, chars);
140
if (size < 0) {
141
return nullptr;
142
}
143
144
return NewStringCopyN<CanGC>(cx, chars.begin(), size_t(size));
145
}
146
147
void AddICUCellMemory(JSObject* obj, size_t nbytes);
148
149
void RemoveICUCellMemory(JSFreeOp* fop, JSObject* obj, size_t nbytes);
150
151
} // namespace intl
152
153
} // namespace js
154
155
#endif /* builtin_intl_CommonFunctions_h */