зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1379983 - Part 3: Remove goto statements from Unescape function and some other clean-ups. r=jandem
--HG-- extra : rebase_source : ff238fd152fd2c67857f1c255ec49615f4e4bfa1
This commit is contained in:
Родитель
9a3eb95fa0
Коммит
a108ef2f00
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "jsstr.h"
|
||||
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Casting.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
|
@ -387,39 +388,15 @@ template <typename CharT>
|
|||
static bool
|
||||
Unescape(StringBuffer& sb, const mozilla::Range<const CharT> chars)
|
||||
{
|
||||
/*
|
||||
* NB: use signed integers for length/index to allow simple length
|
||||
* comparisons without unsigned-underflow hazards.
|
||||
*/
|
||||
static_assert(JSString::MAX_LENGTH <= INT_MAX, "String length must fit in a signed integer");
|
||||
int length = AssertedCast<int>(chars.length());
|
||||
// Step 2.
|
||||
uint32_t length = chars.length();
|
||||
|
||||
/*
|
||||
* Note that the spec algorithm has been optimized to avoid building
|
||||
* a string in the case where no escapes are present.
|
||||
*/
|
||||
|
||||
/* Step 4. */
|
||||
int k = 0;
|
||||
bool building = false;
|
||||
|
||||
/* Step 5. */
|
||||
while (k < length) {
|
||||
/* Step 6. */
|
||||
char16_t c = chars[k];
|
||||
|
||||
/* Step 7. */
|
||||
if (c != '%')
|
||||
goto step_18;
|
||||
|
||||
/* Step 8. */
|
||||
if (k > length - 6)
|
||||
goto step_14;
|
||||
|
||||
/* Step 9. */
|
||||
if (chars[k + 1] != 'u')
|
||||
goto step_14;
|
||||
|
||||
#define ENSURE_BUILDING \
|
||||
do { \
|
||||
if (!building) { \
|
||||
|
@ -430,29 +407,38 @@ Unescape(StringBuffer& sb, const mozilla::Range<const CharT> chars)
|
|||
} \
|
||||
} while(false);
|
||||
|
||||
/* Step 10-13. */
|
||||
if (Unhex4(chars.begin() + k + 2, &c)) {
|
||||
ENSURE_BUILDING;
|
||||
k += 5;
|
||||
goto step_18;
|
||||
// Step 4.
|
||||
uint32_t k = 0;
|
||||
|
||||
// Step 5.
|
||||
while (k < length) {
|
||||
// Step 5.a.
|
||||
char16_t c = chars[k];
|
||||
|
||||
// Step 5.b.
|
||||
if (c == '%') {
|
||||
static_assert(JSString::MAX_LENGTH < UINT32_MAX - 6,
|
||||
"String length is not near UINT32_MAX");
|
||||
|
||||
// Steps 5.b.i-ii.
|
||||
if (k + 6 <= length && chars[k + 1] == 'u') {
|
||||
if (Unhex4(chars.begin() + k + 2, &c)) {
|
||||
ENSURE_BUILDING
|
||||
k += 5;
|
||||
}
|
||||
} else if (k + 3 <= length) {
|
||||
if (Unhex2(chars.begin() + k + 1, &c)) {
|
||||
ENSURE_BUILDING
|
||||
k += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
step_14:
|
||||
/* Step 14. */
|
||||
if (k > length - 3)
|
||||
goto step_18;
|
||||
|
||||
/* Step 15-17. */
|
||||
if (Unhex2(chars.begin() + k + 1, &c)) {
|
||||
ENSURE_BUILDING;
|
||||
k += 2;
|
||||
}
|
||||
|
||||
step_18:
|
||||
// Step 5.c.
|
||||
if (building && !sb.append(c))
|
||||
return false;
|
||||
|
||||
/* Step 19. */
|
||||
// Step 5.d.
|
||||
k += 1;
|
||||
}
|
||||
|
||||
|
@ -460,22 +446,24 @@ Unescape(StringBuffer& sb, const mozilla::Range<const CharT> chars)
|
|||
#undef ENSURE_BUILDING
|
||||
}
|
||||
|
||||
/* ES5 B.2.2 */
|
||||
// ES2018 draft rev f83aa38282c2a60c6916ebc410bfdf105a0f6a54
|
||||
// B.2.1.2 unescape ( string )
|
||||
static bool
|
||||
str_unescape(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
/* Step 1. */
|
||||
// Step 1.
|
||||
RootedLinearString str(cx, ArgToRootedString(cx, args, 0));
|
||||
if (!str)
|
||||
return false;
|
||||
|
||||
/* Step 3. */
|
||||
// Step 3.
|
||||
StringBuffer sb(cx);
|
||||
if (str->hasTwoByteChars() && !sb.ensureTwoByteChars())
|
||||
return false;
|
||||
|
||||
// Steps 2, 4-5.
|
||||
if (str->hasLatin1Chars()) {
|
||||
AutoCheckCannotGC nogc;
|
||||
if (!Unescape(sb, str->latin1Range(nogc)))
|
||||
|
@ -486,6 +474,7 @@ str_unescape(JSContext* cx, unsigned argc, Value* vp)
|
|||
return false;
|
||||
}
|
||||
|
||||
// Step 6.
|
||||
JSLinearString* result;
|
||||
if (!sb.empty()) {
|
||||
result = sb.finishString();
|
||||
|
@ -3300,7 +3289,7 @@ CodeUnitToString(JSContext* cx, uint16_t ucode, MutableHandleValue rval)
|
|||
}
|
||||
|
||||
char16_t c = char16_t(ucode);
|
||||
JSString* str = NewStringCopyN<CanGC>(cx, &c, 1);
|
||||
JSString* str = NewStringCopyNDontDeflate<CanGC>(cx, &c, 1);
|
||||
if (!str)
|
||||
return false;
|
||||
|
||||
|
@ -3330,7 +3319,7 @@ ToCodePoint(JSContext* cx, HandleValue code, uint32_t* codePoint)
|
|||
// String.fromCodePoint, Steps 5.c-d.
|
||||
if (JS::ToInteger(nextCP) != nextCP || nextCP < 0 || nextCP > unicode::NonBMPMax) {
|
||||
ToCStringBuf cbuf;
|
||||
if (char* numStr = NumberToCString(cx, &cbuf, nextCP))
|
||||
if (const char* numStr = NumberToCString(cx, &cbuf, nextCP))
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NOT_A_CODEPOINT, numStr);
|
||||
return false;
|
||||
}
|
||||
|
@ -3415,7 +3404,7 @@ js::str_fromCodePoint(JSContext* cx, unsigned argc, Value* vp)
|
|||
// Steps 1-2 (omitted).
|
||||
|
||||
// Step 3.
|
||||
static_assert(ARGS_LENGTH_MAX < std::numeric_limits<size_t>::max() / 2,
|
||||
static_assert(ARGS_LENGTH_MAX < std::numeric_limits<decltype(args.length())>::max() / 2,
|
||||
"|args.length() * 2 + 1| does not overflow");
|
||||
char16_t* elements = cx->pod_malloc<char16_t>(args.length() * 2 + 1);
|
||||
if (!elements)
|
||||
|
@ -3649,10 +3638,9 @@ js::ValueToSource(JSContext* cx, HandleValue v)
|
|||
if (v.isPrimitive()) {
|
||||
/* Special case to preserve negative zero, _contra_ toString. */
|
||||
if (v.isDouble() && IsNegativeZero(v.toDouble())) {
|
||||
/* NB: _ucNstr rather than _ucstr to indicate non-terminated. */
|
||||
static const char16_t js_negzero_ucNstr[] = {'-', '0'};
|
||||
static const Latin1Char negativeZero[] = {'-', '0'};
|
||||
|
||||
return NewStringCopyN<CanGC>(cx, js_negzero_ucNstr, 2);
|
||||
return NewStringCopyN<CanGC>(cx, negativeZero, mozilla::ArrayLength(negativeZero));
|
||||
}
|
||||
return ToString<CanGC>(cx, v);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче