зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1846224 - Add a JavaScript per-realm locale override. r=jandem
Differential Revision: https://phabricator.services.mozilla.com/D184944
This commit is contained in:
Родитель
b1f29a3a3d
Коммит
3fe3a9321d
|
@ -18,6 +18,7 @@
|
||||||
#include "jstypes.h" // JS_PUBLIC_API
|
#include "jstypes.h" // JS_PUBLIC_API
|
||||||
|
|
||||||
#include "js/Class.h" // JSTraceOp
|
#include "js/Class.h" // JSTraceOp
|
||||||
|
#include "js/RefCounted.h"
|
||||||
|
|
||||||
struct JS_PUBLIC_API JSContext;
|
struct JS_PUBLIC_API JSContext;
|
||||||
class JS_PUBLIC_API JSObject;
|
class JS_PUBLIC_API JSObject;
|
||||||
|
@ -60,6 +61,14 @@ enum class WeakRefSpecifier {
|
||||||
EnabledWithoutCleanupSome
|
EnabledWithoutCleanupSome
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct LocaleString : js::RefCounted<LocaleString> {
|
||||||
|
const char* chars_;
|
||||||
|
|
||||||
|
explicit LocaleString(const char* chars) : chars_(chars) {}
|
||||||
|
|
||||||
|
auto chars() const { return chars_; }
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RealmCreationOptions specifies options relevant to creating a new realm, that
|
* RealmCreationOptions specifies options relevant to creating a new realm, that
|
||||||
* are either immutable characteristics of that realm or that are discarded
|
* are either immutable characteristics of that realm or that are discarded
|
||||||
|
@ -259,6 +268,9 @@ class JS_PUBLIC_API RealmCreationOptions {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RefPtr<LocaleString> locale() const { return locale_; }
|
||||||
|
RealmCreationOptions& setLocaleCopyZ(const char* locale);
|
||||||
|
|
||||||
// Always use the fdlibm implementation of math functions instead of the
|
// Always use the fdlibm implementation of math functions instead of the
|
||||||
// platform native libc implementations. Useful for fingerprinting protection
|
// platform native libc implementations. Useful for fingerprinting protection
|
||||||
// and cross-platform consistency.
|
// and cross-platform consistency.
|
||||||
|
@ -282,6 +294,7 @@ class JS_PUBLIC_API RealmCreationOptions {
|
||||||
Zone* zone_;
|
Zone* zone_;
|
||||||
};
|
};
|
||||||
uint64_t profilerRealmID_ = 0;
|
uint64_t profilerRealmID_ = 0;
|
||||||
|
RefPtr<LocaleString> locale_;
|
||||||
WeakRefSpecifier weakRefs_ = WeakRefSpecifier::Disabled;
|
WeakRefSpecifier weakRefs_ = WeakRefSpecifier::Disabled;
|
||||||
bool invisibleToDebugger_ = false;
|
bool invisibleToDebugger_ = false;
|
||||||
bool preserveJitCode_ = false;
|
bool preserveJitCode_ = false;
|
||||||
|
|
|
@ -7813,34 +7813,12 @@ static bool SetDefaultLocale(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args[0].isString() && !args[0].toString()->empty()) {
|
if (args[0].isString() && !args[0].toString()->empty()) {
|
||||||
Rooted<JSLinearString*> str(cx, args[0].toString()->ensureLinear(cx));
|
RootedString str(cx, args[0].toString());
|
||||||
if (!str) {
|
UniqueChars locale = StringToLocale(cx, callee, str);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!StringIsAscii(str)) {
|
|
||||||
ReportUsageErrorASCII(cx, callee,
|
|
||||||
"First argument contains non-ASCII characters");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
UniqueChars locale = JS_EncodeStringToASCII(cx, str);
|
|
||||||
if (!locale) {
|
if (!locale) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool containsOnlyValidBCP47Characters =
|
|
||||||
mozilla::IsAsciiAlpha(locale[0]) &&
|
|
||||||
std::all_of(locale.get(), locale.get() + str->length(), [](auto c) {
|
|
||||||
return mozilla::IsAsciiAlphanumeric(c) || c == '-';
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!containsOnlyValidBCP47Characters) {
|
|
||||||
ReportUsageErrorASCII(cx, callee,
|
|
||||||
"First argument should be a BCP47 language tag");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!JS_SetDefaultLocale(cx->runtime(), locale.get())) {
|
if (!JS_SetDefaultLocale(cx->runtime(), locale.get())) {
|
||||||
ReportOutOfMemory(cx);
|
ReportOutOfMemory(cx);
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "js/RootingAPI.h" // JS::Rooted, JS::Handle
|
#include "js/RootingAPI.h" // JS::Rooted, JS::Handle
|
||||||
#include "js/Utility.h" // JS::UniqueChars
|
#include "js/Utility.h" // JS::UniqueChars
|
||||||
#include "js/Value.h" // JS::Value, JS::StringValue
|
#include "js/Value.h" // JS::Value, JS::StringValue
|
||||||
|
#include "vm/JSContext.h" // JS::ReportUsageErrorASCII
|
||||||
#include "vm/JSScript.h"
|
#include "vm/JSScript.h"
|
||||||
|
|
||||||
bool js::ParseCompileOptions(JSContext* cx, JS::CompileOptions& options,
|
bool js::ParseCompileOptions(JSContext* cx, JS::CompileOptions& options,
|
||||||
|
@ -255,3 +256,36 @@ bool js::ParseDebugMetadata(JSContext* cx, JS::Handle<JSObject*> opts,
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JS::UniqueChars js::StringToLocale(JSContext* cx, JS::Handle<JSObject*> callee,
|
||||||
|
JS::Handle<JSString*> str_) {
|
||||||
|
Rooted<JSLinearString*> str(cx, str_->ensureLinear(cx));
|
||||||
|
if (!str) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!StringIsAscii(str)) {
|
||||||
|
ReportUsageErrorASCII(cx, callee,
|
||||||
|
"First argument contains non-ASCII characters");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
UniqueChars locale = JS_EncodeStringToASCII(cx, str);
|
||||||
|
if (!locale) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool containsOnlyValidBCP47Characters =
|
||||||
|
mozilla::IsAsciiAlpha(locale[0]) &&
|
||||||
|
std::all_of(locale.get(), locale.get() + str->length(), [](auto c) {
|
||||||
|
return mozilla::IsAsciiAlphanumeric(c) || c == '-';
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!containsOnlyValidBCP47Characters) {
|
||||||
|
ReportUsageErrorASCII(cx, callee,
|
||||||
|
"First argument should be a BCP47 language tag");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return locale;
|
||||||
|
}
|
||||||
|
|
|
@ -59,6 +59,10 @@ JSObject* CreateScriptPrivate(JSContext* cx,
|
||||||
JS::MutableHandle<JS::Value> privateValue,
|
JS::MutableHandle<JS::Value> privateValue,
|
||||||
JS::MutableHandle<JSString*> elementAttributeName);
|
JS::MutableHandle<JSString*> elementAttributeName);
|
||||||
|
|
||||||
|
[[nodiscard]] JS::UniqueChars StringToLocale(JSContext* cx,
|
||||||
|
JS::Handle<JSObject*> callee,
|
||||||
|
JS::Handle<JSString*> str_);
|
||||||
|
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
|
||||||
#endif /* builtin_TestingUtility_h */
|
#endif /* builtin_TestingUtility_h */
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
// |jit-test| skip-if: typeof Intl === 'undefined'
|
||||||
|
|
||||||
|
function test(locale, timeZone) {
|
||||||
|
let global = newGlobal({locale, forceUTC: true});
|
||||||
|
|
||||||
|
const constructors = ["Collator", "DateTimeFormat", "ListFormat",
|
||||||
|
"NumberFormat", "PluralRules", "RelativeTimeFormat"];
|
||||||
|
for (const constructor of constructors) {
|
||||||
|
let intl = new global.Intl[constructor];
|
||||||
|
assertEq(intl.resolvedOptions().locale, locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
const date = new global.Date(2012, 0, 10);
|
||||||
|
let tzRE = /\(([^\)]+)\)/;
|
||||||
|
assertEq(tzRE.exec(date)[1], timeZone)
|
||||||
|
}
|
||||||
|
|
||||||
|
test("de-CH", "Koordinierte Weltzeit");
|
||||||
|
test("en", "Coordinated Universal Time");
|
|
@ -1722,6 +1722,24 @@ JS::RealmCreationOptions& JS::RealmCreationOptions::setCoopAndCoepEnabled(
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JS::RealmCreationOptions& JS::RealmCreationOptions::setLocaleCopyZ(
|
||||||
|
const char* locale) {
|
||||||
|
const size_t size = strlen(locale) + 1;
|
||||||
|
|
||||||
|
AutoEnterOOMUnsafeRegion oomUnsafe;
|
||||||
|
char* memoryPtr = js_pod_malloc<char>(sizeof(LocaleString) + size);
|
||||||
|
if (!memoryPtr) {
|
||||||
|
oomUnsafe.crash("RealmCreationOptions::setLocaleCopyZ");
|
||||||
|
}
|
||||||
|
|
||||||
|
char* localePtr = memoryPtr + sizeof(LocaleString);
|
||||||
|
memcpy(localePtr, locale, size);
|
||||||
|
|
||||||
|
locale_ = new (memoryPtr) LocaleString(localePtr);
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
const JS::RealmBehaviors& JS::RealmBehaviorsRef(JS::Realm* realm) {
|
const JS::RealmBehaviors& JS::RealmBehaviorsRef(JS::Realm* realm) {
|
||||||
return realm->behaviors();
|
return realm->behaviors();
|
||||||
}
|
}
|
||||||
|
|
|
@ -156,7 +156,8 @@ class DateTimeHelper {
|
||||||
static double UTC(DateTimeInfo::ForceUTC forceUTC, double t);
|
static double UTC(DateTimeInfo::ForceUTC forceUTC, double t);
|
||||||
static JSString* timeZoneComment(JSContext* cx,
|
static JSString* timeZoneComment(JSContext* cx,
|
||||||
DateTimeInfo::ForceUTC forceUTC,
|
DateTimeInfo::ForceUTC forceUTC,
|
||||||
double utcTime, double localTime);
|
const char* locale, double utcTime,
|
||||||
|
double localTime);
|
||||||
#if !JS_HAS_INTL_API
|
#if !JS_HAS_INTL_API
|
||||||
static size_t formatTime(DateTimeInfo::ForceUTC forceUTC, char* buf,
|
static size_t formatTime(DateTimeInfo::ForceUTC forceUTC, char* buf,
|
||||||
size_t buflen, const char* fmt, double utcTime,
|
size_t buflen, const char* fmt, double utcTime,
|
||||||
|
@ -2944,8 +2945,8 @@ static bool date_toJSON(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
#if JS_HAS_INTL_API
|
#if JS_HAS_INTL_API
|
||||||
JSString* DateTimeHelper::timeZoneComment(JSContext* cx,
|
JSString* DateTimeHelper::timeZoneComment(JSContext* cx,
|
||||||
DateTimeInfo::ForceUTC forceUTC,
|
DateTimeInfo::ForceUTC forceUTC,
|
||||||
double utcTime, double localTime) {
|
const char* locale, double utcTime,
|
||||||
const char* locale = cx->runtime()->getDefaultLocale();
|
double localTime) {
|
||||||
if (!locale) {
|
if (!locale) {
|
||||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
|
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
|
||||||
JSMSG_DEFAULT_LOCALE_ERROR);
|
JSMSG_DEFAULT_LOCALE_ERROR);
|
||||||
|
@ -3018,7 +3019,8 @@ size_t DateTimeHelper::formatTime(DateTimeInfo::ForceUTC forceUTC, char* buf,
|
||||||
|
|
||||||
JSString* DateTimeHelper::timeZoneComment(JSContext* cx,
|
JSString* DateTimeHelper::timeZoneComment(JSContext* cx,
|
||||||
DateTimeInfo::ForceUTC forceUTC,
|
DateTimeInfo::ForceUTC forceUTC,
|
||||||
double utcTime, double localTime) {
|
const char* locale, double utcTime,
|
||||||
|
double localTime) {
|
||||||
char tzbuf[100];
|
char tzbuf[100];
|
||||||
|
|
||||||
size_t tzlen =
|
size_t tzlen =
|
||||||
|
@ -3055,7 +3057,7 @@ JSString* DateTimeHelper::timeZoneComment(JSContext* cx,
|
||||||
enum class FormatSpec { DateTime, Date, Time };
|
enum class FormatSpec { DateTime, Date, Time };
|
||||||
|
|
||||||
static bool FormatDate(JSContext* cx, DateTimeInfo::ForceUTC forceUTC,
|
static bool FormatDate(JSContext* cx, DateTimeInfo::ForceUTC forceUTC,
|
||||||
double utcTime, FormatSpec format,
|
const char* locale, double utcTime, FormatSpec format,
|
||||||
MutableHandleValue rval) {
|
MutableHandleValue rval) {
|
||||||
if (!std::isfinite(utcTime)) {
|
if (!std::isfinite(utcTime)) {
|
||||||
rval.setString(cx->names().Invalid_Date_);
|
rval.setString(cx->names().Invalid_Date_);
|
||||||
|
@ -3091,8 +3093,8 @@ static bool FormatDate(JSContext* cx, DateTimeInfo::ForceUTC forceUTC,
|
||||||
// also means the time zone string may not fit into Latin-1.
|
// also means the time zone string may not fit into Latin-1.
|
||||||
|
|
||||||
// Get a time zone string from the OS or ICU to include as a comment.
|
// Get a time zone string from the OS or ICU to include as a comment.
|
||||||
timeZoneComment =
|
timeZoneComment = DateTimeHelper::timeZoneComment(cx, forceUTC, locale,
|
||||||
DateTimeHelper::timeZoneComment(cx, forceUTC, utcTime, localTime);
|
utcTime, localTime);
|
||||||
if (!timeZoneComment) {
|
if (!timeZoneComment) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -3142,9 +3144,12 @@ static bool FormatDate(JSContext* cx, DateTimeInfo::ForceUTC forceUTC,
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !JS_HAS_INTL_API
|
#if !JS_HAS_INTL_API
|
||||||
static bool ToLocaleFormatHelper(JSContext* cx, DateTimeInfo::ForceUTC forceUTC,
|
static bool ToLocaleFormatHelper(JSContext* cx, DateObject* unwrapped,
|
||||||
double utcTime, const char* format,
|
const char* format, MutableHandleValue rval) {
|
||||||
MutableHandleValue rval) {
|
DateTimeInfo::ForceUTC forceUTC = unwrapped->forceUTC();
|
||||||
|
const char* locale = unwrapped->realm()->getLocale();
|
||||||
|
double utcTime = unwrapped->UTCTime().toNumber();
|
||||||
|
|
||||||
char buf[100];
|
char buf[100];
|
||||||
if (!std::isfinite(utcTime)) {
|
if (!std::isfinite(utcTime)) {
|
||||||
strcpy(buf, "InvalidDate");
|
strcpy(buf, "InvalidDate");
|
||||||
|
@ -3157,7 +3162,8 @@ static bool ToLocaleFormatHelper(JSContext* cx, DateTimeInfo::ForceUTC forceUTC,
|
||||||
|
|
||||||
/* If it failed, default to toString. */
|
/* If it failed, default to toString. */
|
||||||
if (result_len == 0) {
|
if (result_len == 0) {
|
||||||
return FormatDate(cx, forceUTC, utcTime, FormatSpec::DateTime, rval);
|
return FormatDate(cx, forceUTC, locale, utcTime, FormatSpec::DateTime,
|
||||||
|
rval);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hacked check against undesired 2-digit year 00/00/00 form. */
|
/* Hacked check against undesired 2-digit year 00/00/00 form. */
|
||||||
|
@ -3212,9 +3218,7 @@ static bool date_toLocaleString(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
# endif
|
# endif
|
||||||
;
|
;
|
||||||
|
|
||||||
return ToLocaleFormatHelper(cx, unwrapped->forceUTC(),
|
return ToLocaleFormatHelper(cx, unwrapped, format, args.rval());
|
||||||
unwrapped->UTCTime().toNumber(), format,
|
|
||||||
args.rval());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool date_toLocaleDateString(JSContext* cx, unsigned argc, Value* vp) {
|
static bool date_toLocaleDateString(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
|
@ -3240,9 +3244,7 @@ static bool date_toLocaleDateString(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
# endif
|
# endif
|
||||||
;
|
;
|
||||||
|
|
||||||
return ToLocaleFormatHelper(cx, unwrapped->forceUTC(),
|
return ToLocaleFormatHelper(cx, unwrapped, format, args.rval());
|
||||||
unwrapped->UTCTime().toNumber(), format,
|
|
||||||
args.rval());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool date_toLocaleTimeString(JSContext* cx, unsigned argc, Value* vp) {
|
static bool date_toLocaleTimeString(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
|
@ -3256,9 +3258,7 @@ static bool date_toLocaleTimeString(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ToLocaleFormatHelper(cx, unwrapped->forceUTC(),
|
return ToLocaleFormatHelper(cx, unwrapped, "%X", args.rval());
|
||||||
unwrapped->UTCTime().toNumber(), "%X",
|
|
||||||
args.rval());
|
|
||||||
}
|
}
|
||||||
#endif /* !JS_HAS_INTL_API */
|
#endif /* !JS_HAS_INTL_API */
|
||||||
|
|
||||||
|
@ -3272,8 +3272,9 @@ static bool date_toTimeString(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return FormatDate(cx, unwrapped->forceUTC(), unwrapped->UTCTime().toNumber(),
|
return FormatDate(cx, unwrapped->forceUTC(), unwrapped->realm()->getLocale(),
|
||||||
FormatSpec::Time, args.rval());
|
unwrapped->UTCTime().toNumber(), FormatSpec::Time,
|
||||||
|
args.rval());
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool date_toDateString(JSContext* cx, unsigned argc, Value* vp) {
|
static bool date_toDateString(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
|
@ -3286,8 +3287,9 @@ static bool date_toDateString(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return FormatDate(cx, unwrapped->forceUTC(), unwrapped->UTCTime().toNumber(),
|
return FormatDate(cx, unwrapped->forceUTC(), unwrapped->realm()->getLocale(),
|
||||||
FormatSpec::Date, args.rval());
|
unwrapped->UTCTime().toNumber(), FormatSpec::Date,
|
||||||
|
args.rval());
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool date_toSource(JSContext* cx, unsigned argc, Value* vp) {
|
static bool date_toSource(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
|
@ -3323,8 +3325,9 @@ bool date_toString(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return FormatDate(cx, unwrapped->forceUTC(), unwrapped->UTCTime().toNumber(),
|
return FormatDate(cx, unwrapped->forceUTC(), unwrapped->realm()->getLocale(),
|
||||||
FormatSpec::DateTime, args.rval());
|
unwrapped->UTCTime().toNumber(), FormatSpec::DateTime,
|
||||||
|
args.rval());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool js::date_valueOf(JSContext* cx, unsigned argc, Value* vp) {
|
bool js::date_valueOf(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
|
@ -3480,8 +3483,8 @@ static bool NewDateObject(JSContext* cx, const CallArgs& args, ClippedTime t) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ToDateString(JSContext* cx, const CallArgs& args, ClippedTime t) {
|
static bool ToDateString(JSContext* cx, const CallArgs& args, ClippedTime t) {
|
||||||
return FormatDate(cx, ForceUTC(cx->realm()), t.toDouble(),
|
return FormatDate(cx, ForceUTC(cx->realm()), cx->realm()->getLocale(),
|
||||||
FormatSpec::DateTime, args.rval());
|
t.toDouble(), FormatSpec::DateTime, args.rval());
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool DateNoArguments(JSContext* cx, const CallArgs& args) {
|
static bool DateNoArguments(JSContext* cx, const CallArgs& args) {
|
||||||
|
|
|
@ -6776,6 +6776,9 @@ static bool WrapWithProto(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool NewGlobal(JSContext* cx, unsigned argc, Value* vp) {
|
static bool NewGlobal(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
|
RootedObject callee(cx, &args.callee());
|
||||||
|
|
||||||
JS::RealmOptions options;
|
JS::RealmOptions options;
|
||||||
JS::RealmCreationOptions& creationOptions = options.creationOptions();
|
JS::RealmCreationOptions& creationOptions = options.creationOptions();
|
||||||
JS::RealmBehaviors& behaviors = options.behaviors();
|
JS::RealmBehaviors& behaviors = options.behaviors();
|
||||||
|
@ -6794,7 +6797,6 @@ static bool NewGlobal(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
|
|
||||||
JS::AutoHoldPrincipals principals(cx);
|
JS::AutoHoldPrincipals principals(cx);
|
||||||
|
|
||||||
CallArgs args = CallArgsFromVp(argc, vp);
|
|
||||||
if (args.length() == 1 && args[0].isObject()) {
|
if (args.length() == 1 && args[0].isObject()) {
|
||||||
RootedObject opts(cx, &args[0].toObject());
|
RootedObject opts(cx, &args[0].toObject());
|
||||||
RootedValue v(cx);
|
RootedValue v(cx);
|
||||||
|
@ -6914,6 +6916,18 @@ static bool NewGlobal(JSContext* cx, unsigned argc, Value* vp) {
|
||||||
if (v.isBoolean()) {
|
if (v.isBoolean()) {
|
||||||
creationOptions.setAlwaysUseFdlibm(v.toBoolean());
|
creationOptions.setAlwaysUseFdlibm(v.toBoolean());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!JS_GetProperty(cx, opts, "locale", &v)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (v.isString()) {
|
||||||
|
RootedString str(cx, v.toString());
|
||||||
|
UniqueChars locale = StringToLocale(cx, callee, str);
|
||||||
|
if (!locale) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
creationOptions.setLocaleCopyZ(locale.get());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CheckRealmOptions(cx, options, principals.get())) {
|
if (!CheckRealmOptions(cx, options, principals.get())) {
|
||||||
|
|
|
@ -488,6 +488,14 @@ void Realm::clearScriptCounts() { zone()->clearScriptCounts(this); }
|
||||||
|
|
||||||
void Realm::clearScriptLCov() { zone()->clearScriptLCov(this); }
|
void Realm::clearScriptLCov() { zone()->clearScriptLCov(this); }
|
||||||
|
|
||||||
|
const char* Realm::getLocale() const {
|
||||||
|
if (RefPtr<LocaleString> locale = creationOptions_.locale()) {
|
||||||
|
return locale->chars();
|
||||||
|
}
|
||||||
|
|
||||||
|
return runtime_->getDefaultLocale();
|
||||||
|
}
|
||||||
|
|
||||||
void ObjectRealm::addSizeOfExcludingThis(
|
void ObjectRealm::addSizeOfExcludingThis(
|
||||||
mozilla::MallocSizeOf mallocSizeOf, size_t* innerViewsArg,
|
mozilla::MallocSizeOf mallocSizeOf, size_t* innerViewsArg,
|
||||||
size_t* objectMetadataTablesArg,
|
size_t* objectMetadataTablesArg,
|
||||||
|
|
|
@ -673,6 +673,9 @@ class JS::Realm : public JS::shadow::Realm {
|
||||||
|
|
||||||
bool shouldCaptureStackForThrow();
|
bool shouldCaptureStackForThrow();
|
||||||
|
|
||||||
|
// Returns the locale for this realm. (Pointer must NOT be freed!)
|
||||||
|
const char* getLocale() const;
|
||||||
|
|
||||||
// Initializes randomNumberGenerator if needed.
|
// Initializes randomNumberGenerator if needed.
|
||||||
mozilla::non_crypto::XorShift128PlusRNG& getOrCreateRandomNumberGenerator();
|
mozilla::non_crypto::XorShift128PlusRNG& getOrCreateRandomNumberGenerator();
|
||||||
|
|
||||||
|
|
|
@ -1593,7 +1593,7 @@ static bool intrinsic_RuntimeDefaultLocale(JSContext* cx, unsigned argc,
|
||||||
CallArgs args = CallArgsFromVp(argc, vp);
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
MOZ_ASSERT(args.length() == 0);
|
MOZ_ASSERT(args.length() == 0);
|
||||||
|
|
||||||
const char* locale = cx->runtime()->getDefaultLocale();
|
const char* locale = cx->realm()->getLocale();
|
||||||
if (!locale) {
|
if (!locale) {
|
||||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
|
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
|
||||||
JSMSG_DEFAULT_LOCALE_ERROR);
|
JSMSG_DEFAULT_LOCALE_ERROR);
|
||||||
|
@ -1622,7 +1622,7 @@ static bool intrinsic_IsRuntimeDefaultLocale(JSContext* cx, unsigned argc,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* locale = cx->runtime()->getDefaultLocale();
|
const char* locale = cx->realm()->getLocale();
|
||||||
if (!locale) {
|
if (!locale) {
|
||||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
|
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
|
||||||
JSMSG_DEFAULT_LOCALE_ERROR);
|
JSMSG_DEFAULT_LOCALE_ERROR);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче