зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1490609: Add JS_EncodeStringToASCII to CharacterEncoding.h. r=Waldo
This commit is contained in:
Родитель
f3074bfafc
Коммит
c76bfd0158
|
@ -368,4 +368,23 @@ JS_EncodeStringToLatin1(JSContext* cx, JSString* str);
|
||||||
extern JS_PUBLIC_API(JS::UniqueChars)
|
extern JS_PUBLIC_API(JS::UniqueChars)
|
||||||
JS_EncodeStringToUTF8(JSContext* cx, JS::Handle<JSString*> str);
|
JS_EncodeStringToUTF8(JSContext* cx, JS::Handle<JSString*> str);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DEPRECATED
|
||||||
|
*
|
||||||
|
* Same behavior as JS_EncodeStringToLatin1(), but encode into an ASCII string.
|
||||||
|
*
|
||||||
|
* This function asserts in debug mode that the input string contains only
|
||||||
|
* ASCII characters.
|
||||||
|
*
|
||||||
|
* The returned string is also subject to misinterpretation if |str| contains
|
||||||
|
* any nulls (which are faithfully transcribed into the returned string, but
|
||||||
|
* which will implicitly truncate the string if it's passed to functions that
|
||||||
|
* expect null-terminated strings).
|
||||||
|
*
|
||||||
|
* Avoid using this function if possible, because we'll remove it once we can
|
||||||
|
* devise a better API for the task.
|
||||||
|
*/
|
||||||
|
extern JS_PUBLIC_API(JS::UniqueChars)
|
||||||
|
JS_EncodeStringToASCII(JSContext* cx, JSString* str);
|
||||||
|
|
||||||
#endif /* js_CharacterEncoding_h */
|
#endif /* js_CharacterEncoding_h */
|
||||||
|
|
|
@ -5016,7 +5016,17 @@ SetTimeZone(JSContext* cx, unsigned argc, Value* vp)
|
||||||
};
|
};
|
||||||
|
|
||||||
if (args[0].isString() && !args[0].toString()->empty()) {
|
if (args[0].isString() && !args[0].toString()->empty()) {
|
||||||
UniqueChars timeZone = JS_EncodeStringToLatin1(cx, args[0].toString());
|
RootedLinearString str(cx, args[0].toString()->ensureLinear(cx));
|
||||||
|
if (!str) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!StringIsAscii(str)) {
|
||||||
|
ReportUsageErrorASCII(cx, callee, "First argument contains non-ASCII characters");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
UniqueChars timeZone = JS_EncodeStringToASCII(cx, str);
|
||||||
if (!timeZone) {
|
if (!timeZone) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -5081,38 +5091,31 @@ SetDefaultLocale(JSContext* cx, unsigned argc, Value* vp)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args[0].isString() && !args[0].toString()->empty()) {
|
if (args[0].isString() && !args[0].toString()->empty()) {
|
||||||
auto containsOnlyValidBCP47Characters = [](auto* chars, size_t length) {
|
|
||||||
return mozilla::IsAsciiAlpha(chars[0]) &&
|
|
||||||
std::all_of(chars, chars + length, [](auto c) {
|
|
||||||
return mozilla::IsAsciiAlphanumeric(c) || c == '-';
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
RootedLinearString str(cx, args[0].toString()->ensureLinear(cx));
|
RootedLinearString str(cx, args[0].toString()->ensureLinear(cx));
|
||||||
if (!str) {
|
if (!str) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasValidChars;
|
if (!StringIsAscii(str)) {
|
||||||
{
|
ReportUsageErrorASCII(cx, callee, "First argument contains non-ASCII characters");
|
||||||
JS::AutoCheckCannotGC nogc;
|
|
||||||
|
|
||||||
size_t length = str->length();
|
|
||||||
hasValidChars = str->hasLatin1Chars()
|
|
||||||
? containsOnlyValidBCP47Characters(str->latin1Chars(nogc), length)
|
|
||||||
: containsOnlyValidBCP47Characters(str->twoByteChars(nogc), length);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasValidChars) {
|
|
||||||
ReportUsageErrorASCII(cx, callee, "First argument should be BCP47 language tag");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
UniqueChars locale = JS_EncodeStringToLatin1(cx, str);
|
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;
|
||||||
|
|
|
@ -91,27 +91,22 @@ js::intl::ReportInternalError(JSContext* cx)
|
||||||
js::UniqueChars
|
js::UniqueChars
|
||||||
js::intl::EncodeLocale(JSContext* cx, JSString* locale)
|
js::intl::EncodeLocale(JSContext* cx, JSString* locale)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
MOZ_ASSERT(locale->length() > 0);
|
||||||
auto containsOnlyValidBCP47Chars = [](auto* chars, size_t length) {
|
|
||||||
return length > 0 &&
|
|
||||||
mozilla::IsAsciiAlpha(chars[0]) &&
|
|
||||||
std::all_of(chars, chars + length, [](auto c) {
|
|
||||||
return mozilla::IsAsciiAlphanumeric(c) || c == '-';
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
if (JSLinearString* linear = locale->ensureLinear(cx)) {
|
js::UniqueChars chars = EncodeAscii(cx, locale);
|
||||||
JS::AutoCheckCannotGC nogc;
|
|
||||||
MOZ_ASSERT(linear->hasLatin1Chars()
|
#ifdef DEBUG
|
||||||
? containsOnlyValidBCP47Chars(linear->latin1Chars(nogc), linear->length())
|
// Ensure the returned value contains only valid BCP 47 characters.
|
||||||
: containsOnlyValidBCP47Chars(linear->twoByteChars(nogc), linear->length()));
|
// (Lambdas can't be placed inside MOZ_ASSERT, so move the checks in an
|
||||||
} else {
|
// #ifdef block.)
|
||||||
// Ignore OOM when only performing a debug assertion.
|
if (chars) {
|
||||||
cx->recoverFromOutOfMemory();
|
auto alnumOrDash = [](char c) { return mozilla::IsAsciiAlphanumeric(c) || c == '-'; };
|
||||||
|
MOZ_ASSERT(mozilla::IsAsciiAlpha(chars[0]));
|
||||||
|
MOZ_ASSERT(std::all_of(chars.get(), chars.get() + locale->length(), alnumOrDash));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return EncodeLatin1(cx, locale);
|
return chars;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -6267,6 +6267,15 @@ JS_DecodeBytes(JSContext* cx, const char* src, size_t srclen, char16_t* dst, siz
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JS_PUBLIC_API(JS::UniqueChars)
|
||||||
|
JS_EncodeStringToASCII(JSContext* cx, JSString* str)
|
||||||
|
{
|
||||||
|
AssertHeapIsIdle();
|
||||||
|
CHECK_THREAD(cx);
|
||||||
|
|
||||||
|
return js::EncodeAscii(cx, str);
|
||||||
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(JS::UniqueChars)
|
JS_PUBLIC_API(JS::UniqueChars)
|
||||||
JS_EncodeStringToLatin1(JSContext* cx, JSString* str)
|
JS_EncodeStringToLatin1(JSContext* cx, JSString* str)
|
||||||
{
|
{
|
||||||
|
|
|
@ -842,7 +842,7 @@ num_toLocaleString_impl(JSContext* cx, const CallArgs& args)
|
||||||
* Create the string, move back to bytes to make string twiddling
|
* Create the string, move back to bytes to make string twiddling
|
||||||
* a bit easier and so we can insert platform charset seperators.
|
* a bit easier and so we can insert platform charset seperators.
|
||||||
*/
|
*/
|
||||||
UniqueChars numBytes = JS_EncodeStringToLatin1(cx, str);
|
UniqueChars numBytes = EncodeAscii(cx, str);
|
||||||
if (!numBytes) {
|
if (!numBytes) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -187,12 +187,12 @@ GetProxyTrap(JSContext* cx, HandleObject handler, HandlePropertyName name, Mutab
|
||||||
|
|
||||||
// Step 4.
|
// Step 4.
|
||||||
if (!IsCallable(func)) {
|
if (!IsCallable(func)) {
|
||||||
UniqueChars bytes = EncodeLatin1(cx, name);
|
UniqueChars bytes = EncodeAscii(cx, name);
|
||||||
if (!bytes) {
|
if (!bytes) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr, JSMSG_BAD_TRAP, bytes.get());
|
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_BAD_TRAP, bytes.get());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5069,6 +5069,16 @@ class MOZ_STACK_CLASS Debugger::ObjectQuery
|
||||||
"neither undefined nor a string");
|
"neither undefined nor a string");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
JSLinearString* str = cls.toString()->ensureLinear(cx);
|
||||||
|
if (!str) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!StringIsAscii(str)) {
|
||||||
|
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_UNEXPECTED_TYPE,
|
||||||
|
"query object's 'class' property",
|
||||||
|
"not a string containing only ASCII characters");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
className = cls;
|
className = cls;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -5197,7 +5207,7 @@ class MOZ_STACK_CLASS Debugger::ObjectQuery
|
||||||
*/
|
*/
|
||||||
bool prepareQuery() {
|
bool prepareQuery() {
|
||||||
if (className.isString()) {
|
if (className.isString()) {
|
||||||
classNameCString = JS_EncodeStringToLatin1(cx, className.toString());
|
classNameCString = JS_EncodeStringToASCII(cx, className.toString());
|
||||||
if (!classNameCString) {
|
if (!classNameCString) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
#include "mozilla/TypeTraits.h"
|
#include "mozilla/TypeTraits.h"
|
||||||
#include "mozilla/Unused.h"
|
#include "mozilla/Unused.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include "jsfriendapi.h"
|
#include "jsfriendapi.h"
|
||||||
|
|
||||||
#include "frontend/BytecodeCompiler.h"
|
#include "frontend/BytecodeCompiler.h"
|
||||||
|
@ -1038,15 +1040,27 @@ js::CompareAtoms(JSAtom* atom1, JSAtom* atom2)
|
||||||
return CompareStringsImpl(atom1, atom2);
|
return CompareStringsImpl(atom1, atom2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
js::StringIsAscii(JSLinearString* str)
|
||||||
|
{
|
||||||
|
auto containsOnlyAsciiCharacters = [](const auto* chars, size_t length) {
|
||||||
|
return std::all_of(chars, chars + length, [](auto c) {
|
||||||
|
return mozilla::IsAscii(c);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
JS::AutoCheckCannotGC nogc;
|
||||||
|
return str->hasLatin1Chars()
|
||||||
|
? containsOnlyAsciiCharacters(str->latin1Chars(nogc), str->length())
|
||||||
|
: containsOnlyAsciiCharacters(str->twoByteChars(nogc), str->length());
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
js::StringEqualsAscii(JSLinearString* str, const char* asciiBytes)
|
js::StringEqualsAscii(JSLinearString* str, const char* asciiBytes)
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(JS::StringIsASCII(asciiBytes));
|
||||||
|
|
||||||
size_t length = strlen(asciiBytes);
|
size_t length = strlen(asciiBytes);
|
||||||
#ifdef DEBUG
|
|
||||||
for (size_t i = 0; i != length; ++i) {
|
|
||||||
MOZ_ASSERT(unsigned(asciiBytes[i]) <= 127);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (length != str->length()) {
|
if (length != str->length()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -2194,6 +2208,18 @@ js::EncodeLatin1(JSContext* cx, JSString* str)
|
||||||
return UniqueChars(reinterpret_cast<char*>(buf));
|
return UniqueChars(reinterpret_cast<char*>(buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UniqueChars
|
||||||
|
js::EncodeAscii(JSContext* cx, JSString* str)
|
||||||
|
{
|
||||||
|
JSLinearString* linear = str->ensureLinear(cx);
|
||||||
|
if (!linear) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(StringIsAscii(linear));
|
||||||
|
return EncodeLatin1(cx, linear);
|
||||||
|
}
|
||||||
|
|
||||||
UniqueChars
|
UniqueChars
|
||||||
js::IdToPrintableUTF8(JSContext* cx, HandleId id, IdToPrintableBehavior behavior)
|
js::IdToPrintableUTF8(JSContext* cx, HandleId id, IdToPrintableBehavior behavior)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1659,6 +1659,12 @@ CompareStrings(JSContext* cx, JSString* str1, JSString* str2, int32_t* result);
|
||||||
extern int32_t
|
extern int32_t
|
||||||
CompareAtoms(JSAtom* atom1, JSAtom* atom2);
|
CompareAtoms(JSAtom* atom1, JSAtom* atom2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the string contains only ASCII characters.
|
||||||
|
*/
|
||||||
|
extern bool
|
||||||
|
StringIsAscii(JSLinearString* str);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return true if the string matches the given sequence of ASCII bytes.
|
* Return true if the string matches the given sequence of ASCII bytes.
|
||||||
*/
|
*/
|
||||||
|
@ -1688,6 +1694,14 @@ SubstringKernel(JSContext* cx, HandleString str, int32_t beginInt, int32_t lengt
|
||||||
|
|
||||||
/*** Conversions *********************************************************************************/
|
/*** Conversions *********************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert a string to a printable C string.
|
||||||
|
*
|
||||||
|
* Asserts if the input contains any non-ASCII characters.
|
||||||
|
*/
|
||||||
|
UniqueChars
|
||||||
|
EncodeAscii(JSContext* cx, JSString* str);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert a string to a printable C string.
|
* Convert a string to a printable C string.
|
||||||
*/
|
*/
|
||||||
|
|
Загрузка…
Ссылка в новой задаче