CommonFunctions.cpp (5525B)
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/intl/ICUError.h" 13 #include "mozilla/TextUtils.h" 14 15 #include <algorithm> 16 17 #include "gc/GCEnum.h" 18 #include "gc/ZoneAllocator.h" 19 #include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_INTERNAL_INTL_ERROR 20 #include "js/Value.h" 21 #include "vm/JSAtomState.h" 22 #include "vm/JSContext.h" 23 #include "vm/JSObject.h" 24 #include "vm/SelfHosting.h" 25 #include "vm/Stack.h" 26 #include "vm/StringType.h" 27 28 #include "gc/GCContext-inl.h" 29 30 bool js::intl::InitializeObject(JSContext* cx, JS::Handle<JSObject*> obj, 31 JS::Handle<PropertyName*> initializer, 32 JS::Handle<JS::Value> locales, 33 JS::Handle<JS::Value> options) { 34 FixedInvokeArgs<3> args(cx); 35 36 args[0].setObject(*obj); 37 args[1].set(locales); 38 args[2].set(options); 39 40 RootedValue ignored(cx); 41 if (!CallSelfHostedFunction(cx, initializer, JS::NullHandleValue, args, 42 &ignored)) { 43 return false; 44 } 45 46 MOZ_ASSERT(ignored.isUndefined(), 47 "Unexpected return value from Intl object initializer"); 48 return true; 49 } 50 51 bool js::intl::InitializeDateTimeFormatObject( 52 JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<JS::Value> thisValue, 53 JS::Handle<JS::Value> locales, JS::Handle<JS::Value> options, 54 JS::Handle<JSString*> required, JS::Handle<JSString*> defaults, 55 JS::Handle<JS::Value> toLocaleStringTimeZone, 56 DateTimeFormatOptions dtfOptions, JS::MutableHandle<JS::Value> result) { 57 Handle<PropertyName*> initializer = cx->names().InitializeDateTimeFormat; 58 59 FixedInvokeArgs<8> args(cx); 60 61 args[0].setObject(*obj); 62 args[1].set(thisValue); 63 args[2].set(locales); 64 args[3].set(options); 65 args[4].setString(required); 66 args[5].setString(defaults); 67 args[6].set(toLocaleStringTimeZone); 68 args[7].setBoolean(dtfOptions == DateTimeFormatOptions::EnableMozExtensions); 69 70 if (!CallSelfHostedFunction(cx, initializer, NullHandleValue, args, result)) { 71 return false; 72 } 73 74 MOZ_ASSERT(result.isObject(), 75 "Intl.DateTimeFormat initializer must return an object"); 76 return true; 77 } 78 79 bool js::intl::InitializeNumberFormatObject( 80 JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<JS::Value> thisValue, 81 JS::Handle<JS::Value> locales, JS::Handle<JS::Value> options, 82 JS::MutableHandle<JS::Value> result) { 83 Handle<PropertyName*> initializer = cx->names().InitializeNumberFormat; 84 85 FixedInvokeArgs<4> args(cx); 86 87 args[0].setObject(*obj); 88 args[1].set(thisValue); 89 args[2].set(locales); 90 args[3].set(options); 91 92 if (!CallSelfHostedFunction(cx, initializer, NullHandleValue, args, result)) { 93 return false; 94 } 95 96 MOZ_ASSERT(result.isObject(), 97 "Intl.NumberFormat initializer must return an object"); 98 return true; 99 } 100 101 JSObject* js::intl::GetInternalsObject(JSContext* cx, 102 JS::Handle<JSObject*> obj) { 103 FixedInvokeArgs<1> args(cx); 104 105 args[0].setObject(*obj); 106 107 RootedValue v(cx); 108 if (!js::CallSelfHostedFunction(cx, cx->names().getInternals, NullHandleValue, 109 args, &v)) { 110 return nullptr; 111 } 112 113 return &v.toObject(); 114 } 115 116 void js::intl::ReportInternalError(JSContext* cx) { 117 JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, 118 JSMSG_INTERNAL_INTL_ERROR); 119 } 120 121 void js::intl::ReportInternalError(JSContext* cx, 122 mozilla::intl::ICUError error) { 123 switch (error) { 124 case mozilla::intl::ICUError::OutOfMemory: 125 ReportOutOfMemory(cx); 126 return; 127 case mozilla::intl::ICUError::InternalError: 128 ReportInternalError(cx); 129 return; 130 case mozilla::intl::ICUError::OverflowError: 131 ReportAllocationOverflow(cx); 132 return; 133 } 134 MOZ_CRASH("Unexpected ICU error"); 135 } 136 137 const js::intl::OldStyleLanguageTagMapping 138 js::intl::oldStyleLanguageTagMappings[] = { 139 {"pa-PK", "pa-Arab-PK"}, {"zh-CN", "zh-Hans-CN"}, 140 {"zh-HK", "zh-Hant-HK"}, {"zh-SG", "zh-Hans-SG"}, 141 {"zh-TW", "zh-Hant-TW"}, 142 }; 143 144 js::UniqueChars js::intl::EncodeLocale(JSContext* cx, JSString* locale) { 145 MOZ_ASSERT(locale->length() > 0); 146 147 js::UniqueChars chars = EncodeAscii(cx, locale); 148 if (!chars) { 149 return nullptr; 150 } 151 152 // Ensure the returned value contains only valid BCP 47 characters. 153 MOZ_ASSERT(mozilla::IsAsciiAlpha(chars[0])); 154 MOZ_ASSERT(std::all_of( 155 chars.get(), chars.get() + locale->length(), 156 [](char c) { return mozilla::IsAsciiAlphanumeric(c) || c == '-'; })); 157 158 return chars; 159 } 160 161 void js::intl::AddICUCellMemory(JSObject* obj, size_t nbytes) { 162 // Account the (estimated) number of bytes allocated by an ICU object against 163 // the JSObject's zone. 164 AddCellMemory(obj, nbytes, MemoryUse::ICUObject); 165 } 166 167 void js::intl::RemoveICUCellMemory(JSObject* obj, size_t nbytes) { 168 RemoveCellMemory(obj, nbytes, MemoryUse::ICUObject); 169 } 170 171 void js::intl::RemoveICUCellMemory(JS::GCContext* gcx, JSObject* obj, 172 size_t nbytes) { 173 gcx->removeCellMemory(obj, nbytes, MemoryUse::ICUObject); 174 }