1326454 - Make TokenStream report OOM immediately.

master
Fedor 2019-09-05 20:05:26 +03:00
parent 91a06d9871
commit 5f8341bf16
5 changed files with 171 additions and 71 deletions

View File

@ -8,6 +8,7 @@
#include "frontend/TokenStream.h" #include "frontend/TokenStream.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/IntegerTypeTraits.h" #include "mozilla/IntegerTypeTraits.h"
#include "mozilla/PodOperations.h" #include "mozilla/PodOperations.h"
@ -33,6 +34,7 @@
using namespace js; using namespace js;
using namespace js::frontend; using namespace js::frontend;
using mozilla::ArrayLength;
using mozilla::Maybe; using mozilla::Maybe;
using mozilla::PodAssign; using mozilla::PodAssign;
using mozilla::PodCopy; using mozilla::PodCopy;
@ -223,8 +225,13 @@ TokenStream::SourceCoords::add(uint32_t lineNum, uint32_t lineStartOffset)
// only if lineStartOffsets_.append succeeds, to keep sentinel. // only if lineStartOffsets_.append succeeds, to keep sentinel.
// Otherwise return false to tell TokenStream about OOM. // Otherwise return false to tell TokenStream about OOM.
uint32_t maxPtr = MAX_PTR; uint32_t maxPtr = MAX_PTR;
if (!lineStartOffsets_.append(maxPtr)) if (!lineStartOffsets_.append(maxPtr)) {
static_assert(mozilla::IsSame<decltype(lineStartOffsets_.allocPolicy()),
TempAllocPolicy&>::value,
"this function's caller depends on it reporting an "
"error on failure, as TempAllocPolicy ensures");
return false; return false;
}
lineStartOffsets_[lineIndex] = lineStartOffset; lineStartOffsets_[lineIndex] = lineStartOffset;
} else { } else {
@ -554,8 +561,9 @@ TokenStream::advance(size_t position)
MOZ_MAKE_MEM_UNDEFINED(&cur->type, sizeof(cur->type)); MOZ_MAKE_MEM_UNDEFINED(&cur->type, sizeof(cur->type));
lookahead = 0; lookahead = 0;
if (flags.hitOOM) if (flags.hitOOM) {
return reportError(JSMSG_OUT_OF_MEMORY); return false;
}
return true; return true;
} }
@ -775,7 +783,7 @@ TokenStream::reportErrorNoOffset(unsigned errorNumber, ...)
} }
bool bool
TokenStream::reportWarning(unsigned errorNumber, ...) TokenStream::warning(unsigned errorNumber, ...)
{ {
va_list args; va_list args;
va_start(args, errorNumber); va_start(args, errorNumber);
@ -806,6 +814,32 @@ TokenStream::reportAsmJSError(uint32_t offset, unsigned errorNumber, ...)
va_end(args); va_end(args);
} }
void
TokenStream::error(unsigned errorNumber, ...)
{
va_list args;
va_start(args, errorNumber);
#ifdef DEBUG
bool result =
#endif
reportCompileErrorNumberVA(currentToken().pos.begin, JSREPORT_ERROR, errorNumber, args);
MOZ_ASSERT(!result, "reporting an error returned true?");
va_end(args);
}
void
TokenStream::errorAt(uint32_t offset, unsigned errorNumber, ...)
{
va_list args;
va_start(args, errorNumber);
#ifdef DEBUG
bool result =
#endif
reportCompileErrorNumberVA(offset, JSREPORT_ERROR, errorNumber, args);
MOZ_ASSERT(!result, "reporting an error returned true?");
va_end(args);
}
// We have encountered a '\': check for a Unicode escape sequence after it. // We have encountered a '\': check for a Unicode escape sequence after it.
// Return the length of the escape sequence and the character code point (by // Return the length of the escape sequence and the character code point (by
// value) if we found a Unicode escape sequence. Otherwise, return 0. In both // value) if we found a Unicode escape sequence. Otherwise, return 0. In both
@ -934,34 +968,49 @@ TokenStream::getDirectives(bool isMultiline, bool shouldWarnDeprecated)
bool bool
TokenStream::getDirective(bool isMultiline, bool shouldWarnDeprecated, TokenStream::getDirective(bool isMultiline, bool shouldWarnDeprecated,
const char* directive, int directiveLength, const char* directive, uint8_t directiveLength,
const char* errorMsgPragma, const char* errorMsgPragma,
UniqueTwoByteChars* destination) UniqueTwoByteChars* destination)
{ {
MOZ_ASSERT(directiveLength <= 18); MOZ_ASSERT(directiveLength <= 18);
char16_t peeked[18]; char16_t peeked[18];
int32_t c;
if (peekChars(directiveLength, peeked) && CharsMatch(peeked, directive)) { if (peekChars(directiveLength, peeked) && CharsMatch(peeked, directive)) {
if (shouldWarnDeprecated && if (shouldWarnDeprecated) {
!reportWarning(JSMSG_DEPRECATED_PRAGMA, errorMsgPragma)) if (!warning(JSMSG_DEPRECATED_PRAGMA, errorMsgPragma))
return false; return false;
}
skipChars(directiveLength); skipChars(directiveLength);
tokenbuf.clear(); tokenbuf.clear();
while ((c = peekChar()) && c != EOF && !unicode::IsSpaceOrBOM2(c)) { do {
getChar(); int32_t c;
if (!peekChar(&c))
return false;
if (c == EOF || unicode::IsSpaceOrBOM2(c))
break;
consumeKnownChar(c);
// Debugging directives can occur in both single- and multi-line // Debugging directives can occur in both single- and multi-line
// comments. If we're currently inside a multi-line comment, we also // comments. If we're currently inside a multi-line comment, we also
// need to recognize multi-line comment terminators. // need to recognize multi-line comment terminators.
if (isMultiline && c == '*' && peekChar() == '/') { if (isMultiline && c == '*') {
ungetChar('*'); int32_t c2;
break; if (!peekChar(&c2))
return false;
if (c2 == '/') {
ungetChar('*');
break;
}
} }
if (!tokenbuf.append(c)) if (!tokenbuf.append(c))
return false; return false;
} } while (true);
if (tokenbuf.empty()) { if (tokenbuf.empty()) {
// The directive's URL was missing, but this is not quite an // The directive's URL was missing, but this is not quite an
@ -993,7 +1042,10 @@ TokenStream::getDisplayURL(bool isMultiline, bool shouldWarnDeprecated)
// developer would like to refer to the source as from the source's actual // developer would like to refer to the source as from the source's actual
// URL. // URL.
return getDirective(isMultiline, shouldWarnDeprecated, " sourceURL=", 11, static const char sourceURLDirective[] = " sourceURL=";
constexpr uint8_t sourceURLDirectiveLength = ArrayLength(sourceURLDirective) - 1;
return getDirective(isMultiline, shouldWarnDeprecated,
sourceURLDirective, sourceURLDirectiveLength,
"sourceURL", &displayURL_); "sourceURL", &displayURL_);
} }
@ -1003,7 +1055,10 @@ TokenStream::getSourceMappingURL(bool isMultiline, bool shouldWarnDeprecated)
// Match comments of the form "//# sourceMappingURL=<url>" or // Match comments of the form "//# sourceMappingURL=<url>" or
// "/\* //# sourceMappingURL=<url> *\/" // "/\* //# sourceMappingURL=<url> *\/"
return getDirective(isMultiline, shouldWarnDeprecated, " sourceMappingURL=", 18, static const char sourceMappingURLDirective[] = " sourceMappingURL=";
constexpr uint8_t sourceMappingURLDirectiveLength = ArrayLength(sourceMappingURLDirective) - 1;
return getDirective(isMultiline, shouldWarnDeprecated,
sourceMappingURLDirective, sourceMappingURLDirectiveLength,
"sourceMappingURL", &sourceMapURL_); "sourceMappingURL", &sourceMapURL_);
} }
@ -1119,8 +1174,10 @@ TokenStream::checkForKeyword(const KeywordInfo* kw, TokenKind* ttp)
return true; return true;
} }
if (kw->tokentype == TOK_RESERVED) if (kw->tokentype == TOK_RESERVED) {
return reportError(JSMSG_RESERVED_ID, kw->chars); error(JSMSG_RESERVED_ID, kw->chars);
return false;
}
if (kw->tokentype == TOK_STRICT_RESERVED) if (kw->tokentype == TOK_STRICT_RESERVED)
return reportStrictModeError(JSMSG_RESERVED_ID, kw->chars); return reportStrictModeError(JSMSG_RESERVED_ID, kw->chars);
@ -1538,10 +1595,11 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
// grammar. We might not always be so permissive, so we warn // grammar. We might not always be so permissive, so we warn
// about it. // about it.
if (c >= '8') { if (c >= '8') {
if (!reportWarning(JSMSG_BAD_OCTAL, c == '8' ? "08" : "09")) { if (!warning(JSMSG_BAD_OCTAL, c == '8' ? "08" : "09"))
goto error; goto error;
}
goto decimal; // use the decimal scanner for the rest of the number // Use the decimal scanner for the rest of the number.
goto decimal;
} }
c = getCharIgnoreEOL(); c = getCharIgnoreEOL();
} }
@ -1690,7 +1748,8 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
case '/': case '/':
// Look for a single-line comment. // Look for a single-line comment.
if (matchChar('/')) { if (matchChar('/')) {
c = peekChar(); if (!peekChar(&c))
goto error;
if (c == '@' || c == '#') { if (c == '@' || c == '#') {
bool shouldWarn = getChar() == '@'; bool shouldWarn = getChar() == '@';
if (!getDirectives(false, shouldWarn)) if (!getDirectives(false, shouldWarn))
@ -1757,7 +1816,8 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
RegExpFlag reflags = NoFlags; RegExpFlag reflags = NoFlags;
unsigned length = tokenbuf.length() + 1; unsigned length = tokenbuf.length() + 1;
while (true) { while (true) {
c = peekChar(); if (!peekChar(&c))
goto error;
if (c == 'g' && !(reflags & GlobalFlag)) if (c == 'g' && !(reflags & GlobalFlag))
reflags = RegExpFlag(reflags | GlobalFlag); reflags = RegExpFlag(reflags | GlobalFlag);
else if (c == 'i' && !(reflags & IgnoreCaseFlag)) else if (c == 'i' && !(reflags & IgnoreCaseFlag))
@ -1774,7 +1834,8 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
length++; length++;
} }
c = peekChar(); if (!peekChar(&c))
goto error;
if (JS7_ISLET(c)) { if (JS7_ISLET(c)) {
char buf[2] = { '\0', '\0' }; char buf[2] = { '\0', '\0' };
tp->pos.begin += length + 1; tp->pos.begin += length + 1;
@ -1797,8 +1858,13 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
case '-': case '-':
if (matchChar('-')) { if (matchChar('-')) {
if (peekChar() == '>' && !flags.isDirtyLine) int32_t c2;
if (!peekChar(&c2))
goto error;
if (c2 == '>' && !flags.isDirtyLine)
goto skipline; goto skipline;
tp->type = TOK_DEC; tp->type = TOK_DEC;
} else { } else {
tp->type = matchChar('=') ? TOK_SUBASSIGN : TOK_SUB; tp->type = matchChar('=') ? TOK_SUBASSIGN : TOK_SUB;
@ -1814,8 +1880,9 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
MOZ_CRASH("should have jumped to |out| or |error|"); MOZ_CRASH("should have jumped to |out| or |error|");
out: out:
if (flags.hitOOM) if (flags.hitOOM) {
return reportError(JSMSG_OUT_OF_MEMORY); return false;
}
flags.isDirtyLine = true; flags.isDirtyLine = true;
tp->pos.end = userbuf.offset(); tp->pos.end = userbuf.offset();
@ -1831,8 +1898,9 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
return true; return true;
error: error:
if (flags.hitOOM) if (flags.hitOOM) {
return reportError(JSMSG_OUT_OF_MEMORY); return false;
}
flags.isDirtyLine = true; flags.isDirtyLine = true;
tp->pos.end = userbuf.offset(); tp->pos.end = userbuf.offset();
@ -1850,32 +1918,50 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
} }
bool bool
TokenStream::getBracedUnicode(uint32_t* cp) TokenStream::matchBracedUnicode(bool* matched, uint32_t* cp)
{ {
int32_t c;
if (!peekChar(&c))
return false;
if (c != '{') {
*matched = false;
return true;
}
consumeKnownChar('{'); consumeKnownChar('{');
uint32_t start = userbuf.offset();
bool first = true; bool first = true;
int32_t c;
uint32_t code = 0; uint32_t code = 0;
while (true) { do {
c = getCharIgnoreEOL(); int32_t c = getCharIgnoreEOL();
if (c == EOF) if (c == EOF) {
error(JSMSG_MALFORMED_ESCAPE, "Unicode");
return false; return false;
}
if (c == '}') { if (c == '}') {
if (first) if (first) {
error(JSMSG_MALFORMED_ESCAPE, "Unicode");
return false; return false;
}
break; break;
} }
if (!JS7_ISHEX(c)) if (!JS7_ISHEX(c)) {
error(JSMSG_MALFORMED_ESCAPE, "Unicode");
return false; return false;
}
code = (code << 4) | JS7_UNHEX(c); code = (code << 4) | JS7_UNHEX(c);
if (code > unicode::NonBMPMax) if (code > unicode::NonBMPMax) {
errorAt(start, JSMSG_UNICODE_OVERFLOW, "escape sequence");
return false; return false;
}
first = false; first = false;
} } while (true);
*matched = true;
*cp = code; *cp = code;
return true; return true;
} }
@ -1897,7 +1983,7 @@ TokenStream::getStringOrTemplateToken(int untilChar, Token** tp)
while ((c = getCharIgnoreEOL()) != untilChar) { while ((c = getCharIgnoreEOL()) != untilChar) {
if (c == EOF) { if (c == EOF) {
ungetCharIgnoreEOL(c); ungetCharIgnoreEOL(c);
reportError(JSMSG_UNTERMINATED_STRING); error(JSMSG_UNTERMINATED_STRING);
return false; return false;
} }
@ -1917,12 +2003,11 @@ TokenStream::getStringOrTemplateToken(int untilChar, Token** tp)
// Unicode character specification. // Unicode character specification.
case 'u': { case 'u': {
if (peekChar() == '{') { bool matched;
uint32_t code; uint32_t code;
if (!getBracedUnicode(&code)) { if (!matchBracedUnicode(&matched, &code))
reportError(JSMSG_MALFORMED_ESCAPE, "Unicode"); return false;
return false; if (matched) {
}
MOZ_ASSERT(code <= unicode::NonBMPMax); MOZ_ASSERT(code <= unicode::NonBMPMax);
if (code < unicode::NonBMPMin) { if (code < unicode::NonBMPMin) {
@ -1945,7 +2030,7 @@ TokenStream::getStringOrTemplateToken(int untilChar, Token** tp)
c = (c << 4) + JS7_UNHEX(cp[3]); c = (c << 4) + JS7_UNHEX(cp[3]);
skipChars(4); skipChars(4);
} else { } else {
reportError(JSMSG_MALFORMED_ESCAPE, "Unicode"); error(JSMSG_MALFORMED_ESCAPE, "Unicode");
return false; return false;
} }
break; break;
@ -1958,7 +2043,7 @@ TokenStream::getStringOrTemplateToken(int untilChar, Token** tp)
c = (JS7_UNHEX(cp[0]) << 4) + JS7_UNHEX(cp[1]); c = (JS7_UNHEX(cp[0]) << 4) + JS7_UNHEX(cp[1]);
skipChars(2); skipChars(2);
} else { } else {
reportError(JSMSG_MALFORMED_ESCAPE, "hexadecimal"); error(JSMSG_MALFORMED_ESCAPE, "hexadecimal");
return false; return false;
} }
break; break;
@ -1969,12 +2054,13 @@ TokenStream::getStringOrTemplateToken(int untilChar, Token** tp)
if (JS7_ISOCT(c)) { if (JS7_ISOCT(c)) {
int32_t val = JS7_UNOCT(c); int32_t val = JS7_UNOCT(c);
c = peekChar(); if (!peekChar(&c))
return false;
// Strict mode code allows only \0, then a non-digit. // Strict mode code allows only \0, then a non-digit.
if (val != 0 || JS7_ISDEC(c)) { if (val != 0 || JS7_ISDEC(c)) {
if (parsingTemplate) { if (parsingTemplate) {
reportError(JSMSG_DEPRECATED_OCTAL); error(JSMSG_DEPRECATED_OCTAL);
return false; return false;
} }
if (!reportStrictModeError(JSMSG_DEPRECATED_OCTAL)) if (!reportStrictModeError(JSMSG_DEPRECATED_OCTAL))
@ -1985,7 +2071,8 @@ TokenStream::getStringOrTemplateToken(int untilChar, Token** tp)
if (JS7_ISOCT(c)) { if (JS7_ISOCT(c)) {
val = 8 * val + JS7_UNOCT(c); val = 8 * val + JS7_UNOCT(c);
getChar(); getChar();
c = peekChar(); if (!peekChar(&c))
return false;
if (JS7_ISOCT(c)) { if (JS7_ISOCT(c)) {
int32_t save = val; int32_t save = val;
val = 8 * val + JS7_UNOCT(c); val = 8 * val + JS7_UNOCT(c);
@ -2003,7 +2090,7 @@ TokenStream::getStringOrTemplateToken(int untilChar, Token** tp)
} else if (TokenBuf::isRawEOLChar(c)) { } else if (TokenBuf::isRawEOLChar(c)) {
if (!parsingTemplate) { if (!parsingTemplate) {
ungetCharIgnoreEOL(c); ungetCharIgnoreEOL(c);
reportError(JSMSG_UNTERMINATED_STRING); error(JSMSG_UNTERMINATED_STRING);
return false; return false;
} }
if (c == '\r') { if (c == '\r') {

View File

@ -364,13 +364,21 @@ class MOZ_STACK_CLASS TokenStream
// TokenStream-specific error reporters. // TokenStream-specific error reporters.
bool reportError(unsigned errorNumber, ...); bool reportError(unsigned errorNumber, ...);
bool reportErrorNoOffset(unsigned errorNumber, ...); bool reportErrorNoOffset(unsigned errorNumber, ...);
bool reportWarning(unsigned errorNumber, ...);
// Report the given error at the current offset.
void error(unsigned errorNumber, ...);
// Report the given error at the given offset.
void errorAt(uint32_t offset, unsigned errorNumber, ...);
// Warn at the current offset.
MOZ_MUST_USE bool warning(unsigned errorNumber, ...);
static const uint32_t NoOffset = UINT32_MAX; static const uint32_t NoOffset = UINT32_MAX;
// General-purpose error reporters. You should avoid calling these // General-purpose error reporters. You should avoid calling these
// directly, and instead use the more succinct alternatives (e.g. // directly, and instead use the more succinct alternatives (error(),
// reportError()) in TokenStream, Parser, and BytecodeEmitter. // warning(), &c.) in TokenStream, Parser, and BytecodeEmitter.
bool reportCompileErrorNumberVA(uint32_t offset, unsigned flags, unsigned errorNumber, bool reportCompileErrorNumberVA(uint32_t offset, unsigned flags, unsigned errorNumber,
va_list args); va_list args);
bool reportStrictModeErrorNumberVA(uint32_t offset, bool strictMode, unsigned errorNumber, bool reportStrictModeErrorNumberVA(uint32_t offset, bool strictMode, unsigned errorNumber,
@ -946,7 +954,7 @@ class MOZ_STACK_CLASS TokenStream
MOZ_MUST_USE bool getTokenInternal(TokenKind* ttp, Modifier modifier); MOZ_MUST_USE bool getTokenInternal(TokenKind* ttp, Modifier modifier);
MOZ_MUST_USE bool getBracedUnicode(uint32_t* code); MOZ_MUST_USE bool matchBracedUnicode(bool* matched, uint32_t* code);
MOZ_MUST_USE bool getStringOrTemplateToken(int untilChar, Token** tp); MOZ_MUST_USE bool getStringOrTemplateToken(int untilChar, Token** tp);
int32_t getChar(); int32_t getChar();
@ -963,7 +971,7 @@ class MOZ_STACK_CLASS TokenStream
MOZ_MUST_USE bool getDirectives(bool isMultiline, bool shouldWarnDeprecated); MOZ_MUST_USE bool getDirectives(bool isMultiline, bool shouldWarnDeprecated);
MOZ_MUST_USE bool getDirective(bool isMultiline, bool shouldWarnDeprecated, MOZ_MUST_USE bool getDirective(bool isMultiline, bool shouldWarnDeprecated,
const char* directive, int directiveLength, const char* directive, uint8_t directiveLength,
const char* errorMsgPragma, const char* errorMsgPragma,
UniquePtr<char16_t[], JS::FreePolicy>* destination); UniquePtr<char16_t[], JS::FreePolicy>* destination);
MOZ_MUST_USE bool getDisplayURL(bool isMultiline, bool shouldWarnDeprecated); MOZ_MUST_USE bool getDisplayURL(bool isMultiline, bool shouldWarnDeprecated);
@ -981,20 +989,25 @@ class MOZ_STACK_CLASS TokenStream
MOZ_ASSERT(c == expect); MOZ_ASSERT(c == expect);
} }
int32_t peekChar() { MOZ_MUST_USE bool peekChar(int32_t* c) {
int32_t c = getChar(); *c = getChar();
ungetChar(c); ungetChar(*c);
return c; return true;
} }
void skipChars(int n) { void skipChars(uint8_t n) {
while (--n >= 0) while (n-- > 0) {
getChar(); MOZ_ASSERT(userbuf.hasRawChars());
mozilla::DebugOnly<int32_t> c = getCharIgnoreEOL();
MOZ_ASSERT(c != '\n');
}
} }
void skipCharsIgnoreEOL(int n) { void skipCharsIgnoreEOL(uint8_t n) {
while (--n >= 0) while (n-- > 0) {
MOZ_ASSERT(userbuf.hasRawChars());
getCharIgnoreEOL(); getCharIgnoreEOL();
}
} }
void updateLineInfoForEOL(); void updateLineInfoForEOL();

View File

@ -243,10 +243,10 @@ RegExpParser<CharT>::RegExpParser(frontend::TokenStream& ts, LifoAlloc* alloc,
template <typename CharT> template <typename CharT>
RegExpTree* RegExpTree*
RegExpParser<CharT>::ReportError(unsigned errorNumber) RegExpParser<CharT>::ReportError(unsigned errorNumber, const char* param /* = nullptr */)
{ {
gc::AutoSuppressGC suppressGC(ts.context()); gc::AutoSuppressGC suppressGC(ts.context());
ts.reportError(errorNumber); ts.reportError(errorNumber, param);
return nullptr; return nullptr;
} }
@ -350,7 +350,7 @@ RegExpParser<CharT>::ParseBracedHexEscape(widechar* value)
} }
code = (code << 4) | d; code = (code << 4) | d;
if (code > unicode::NonBMPMax) { if (code > unicode::NonBMPMax) {
ReportError(JSMSG_UNICODE_OVERFLOW); ReportError(JSMSG_UNICODE_OVERFLOW, "regular expression");
return false; return false;
} }
Advance(); Advance();

View File

@ -211,7 +211,7 @@ class RegExpParser
bool ParseBackReferenceIndex(int* index_out); bool ParseBackReferenceIndex(int* index_out);
bool ParseClassAtom(char16_t* char_class, widechar *value); bool ParseClassAtom(char16_t* char_class, widechar *value);
RegExpTree* ReportError(unsigned errorNumber); RegExpTree* ReportError(unsigned errorNumber, const char* param = nullptr);
void Advance(); void Advance();
void Advance(int dist) { void Advance(int dist) {
next_pos_ += dist - 1; next_pos_ += dist - 1;

View File

@ -502,7 +502,7 @@ MSG_DEF(JSMSG_RANGE_WITH_CLASS_ESCAPE, 0, JSEXN_SYNTAXERR, "character class esca
MSG_DEF(JSMSG_RAW_BRACE_IN_REGEP, 0, JSEXN_SYNTAXERR, "raw brace is not allowed in regular expression with unicode flag") MSG_DEF(JSMSG_RAW_BRACE_IN_REGEP, 0, JSEXN_SYNTAXERR, "raw brace is not allowed in regular expression with unicode flag")
MSG_DEF(JSMSG_RAW_BRACKET_IN_REGEP, 0, JSEXN_SYNTAXERR, "raw bracket is not allowed in regular expression with unicode flag") MSG_DEF(JSMSG_RAW_BRACKET_IN_REGEP, 0, JSEXN_SYNTAXERR, "raw bracket is not allowed in regular expression with unicode flag")
MSG_DEF(JSMSG_TOO_MANY_PARENS, 0, JSEXN_INTERNALERR, "too many parentheses in regular expression") MSG_DEF(JSMSG_TOO_MANY_PARENS, 0, JSEXN_INTERNALERR, "too many parentheses in regular expression")
MSG_DEF(JSMSG_UNICODE_OVERFLOW, 0, JSEXN_SYNTAXERR, "unicode codepoint should not be greater than 0x10FFFF in regular expression") MSG_DEF(JSMSG_UNICODE_OVERFLOW, 1, JSEXN_SYNTAXERR, "Unicode codepoint must not be greater than 0x10FFFF in {0}")
MSG_DEF(JSMSG_UNMATCHED_RIGHT_PAREN, 0, JSEXN_SYNTAXERR, "unmatched ) in regular expression") MSG_DEF(JSMSG_UNMATCHED_RIGHT_PAREN, 0, JSEXN_SYNTAXERR, "unmatched ) in regular expression")
MSG_DEF(JSMSG_UNTERM_CLASS, 0, JSEXN_SYNTAXERR, "unterminated character class") MSG_DEF(JSMSG_UNTERM_CLASS, 0, JSEXN_SYNTAXERR, "unterminated character class")