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
/* Operations used to implement multiple Intl.* classes. */
8
9
#include "builtin/intl/CommonFunctions.h"
10
11
#include "mozilla/Assertions.h"
12
#include "mozilla/TextUtils.h"
13
14
#include <algorithm>
15
16
#include "jsfriendapi.h" // for GetErrorMessage, JSMSG_INTERNAL_INTL_ERROR
17
18
#include "gc/GCEnum.h"
19
#include "gc/Zone.h"
20
#include "gc/ZoneAllocator.h"
21
#include "js/Value.h"
22
#include "vm/JSContext.h"
23
#include "vm/JSObject.h"
24
#include "vm/SelfHosting.h"
25
#include "vm/Stack.h"
26
27
#include "vm/JSObject-inl.h"
28
29
bool js::intl::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
FixedInvokeArgs<3> args(cx);
34
35
args[0].setObject(*obj);
36
args[1].set(locales);
37
args[2].set(options);
38
39
RootedValue ignored(cx);
40
if (!CallSelfHostedFunction(cx, initializer, JS::NullHandleValue, args,
41
&ignored)) {
42
return false;
43
}
44
45
MOZ_ASSERT(ignored.isUndefined(),
46
"Unexpected return value from non-legacy Intl object initializer");
47
return true;
48
}
49
50
bool js::intl::LegacyInitializeObject(JSContext* cx, JS::Handle<JSObject*> obj,
51
JS::Handle<PropertyName*> initializer,
52
JS::Handle<JS::Value> thisValue,
53
JS::Handle<JS::Value> locales,
54
JS::Handle<JS::Value> options,
55
DateTimeFormatOptions dtfOptions,
56
JS::MutableHandle<JS::Value> result) {
57
FixedInvokeArgs<5> args(cx);
58
59
args[0].setObject(*obj);
60
args[1].set(thisValue);
61
args[2].set(locales);
62
args[3].set(options);
63
args[4].setBoolean(dtfOptions == DateTimeFormatOptions::EnableMozExtensions);
64
65
if (!CallSelfHostedFunction(cx, initializer, NullHandleValue, args, result)) {
66
return false;
67
}
68
69
MOZ_ASSERT(result.isObject(),
70
"Legacy Intl object initializer must return an object");
71
return true;
72
}
73
74
JSObject* js::intl::GetInternalsObject(JSContext* cx,
75
JS::Handle<JSObject*> obj) {
76
FixedInvokeArgs<1> args(cx);
77
78
args[0].setObject(*obj);
79
80
RootedValue v(cx);
81
if (!js::CallSelfHostedFunction(cx, cx->names().getInternals, NullHandleValue,
82
args, &v)) {
83
return nullptr;
84
}
85
86
return &v.toObject();
87
}
88
89
void js::intl::ReportInternalError(JSContext* cx) {
90
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
91
JSMSG_INTERNAL_INTL_ERROR);
92
}
93
94
const js::intl::OldStyleLanguageTagMapping
95
js::intl::oldStyleLanguageTagMappings[] = {
96
{"pa-PK", "pa-Arab-PK"}, {"zh-CN", "zh-Hans-CN"},
97
{"zh-HK", "zh-Hant-HK"}, {"zh-SG", "zh-Hans-SG"},
98
{"zh-TW", "zh-Hant-TW"},
99
};
100
101
js::UniqueChars js::intl::EncodeLocale(JSContext* cx, JSString* locale) {
102
MOZ_ASSERT(locale->length() > 0);
103
104
js::UniqueChars chars = EncodeAscii(cx, locale);
105
106
#ifdef DEBUG
107
// Ensure the returned value contains only valid BCP 47 characters.
108
// (Lambdas can't be placed inside MOZ_ASSERT, so move the checks in an
109
// #ifdef block.)
110
if (chars) {
111
auto alnumOrDash = [](char c) {
112
return mozilla::IsAsciiAlphanumeric(c) || c == '-';
113
};
114
MOZ_ASSERT(mozilla::IsAsciiAlpha(chars[0]));
115
MOZ_ASSERT(
116
std::all_of(chars.get(), chars.get() + locale->length(), alnumOrDash));
117
}
118
#endif
119
120
return chars;
121
}
122
123
void js::intl::AddICUCellMemory(JSObject* obj, size_t nbytes) {
124
// Account the (estimated) number of bytes allocated by an ICU object against
125
// the JSObject's zone.
126
AddCellMemory(obj, nbytes, MemoryUse::ICUObject);
127
128
// Manually trigger malloc zone GCs in case there's memory pressure and
129
// collecting any unreachable Intl objects could free ICU allocated memory.
130
//
131
// (ICU allocations use the system memory allocator, so we can't rely on
132
// ZoneAllocPolicy to call |maybeMallocTriggerZoneGC|.)
133
obj->zone()->maybeMallocTriggerZoneGC();
134
}
135
136
void js::intl::RemoveICUCellMemory(JSFreeOp* fop, JSObject* obj,
137
size_t nbytes) {
138
fop->removeCellMemory(obj, nbytes, MemoryUse::ICUObject);
139
}