зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to autoland
--HG-- extra : rebase_source : a5345fa7da5587fdc8dc5e1fd160bbaa03ef6214
This commit is contained in:
Коммит
a090750861
|
@ -628,10 +628,10 @@ class ParserAnyCharsAccess
|
|||
{
|
||||
public:
|
||||
using TokenStreamSpecific = typename Parser::TokenStream;
|
||||
using TokenStreamChars = typename TokenStreamSpecific::CharsBase;
|
||||
using GeneralTokenStreamChars = typename TokenStreamSpecific::GeneralCharsBase;
|
||||
|
||||
static inline TokenStreamAnyChars& anyChars(TokenStreamChars* ts);
|
||||
static inline const TokenStreamAnyChars& anyChars(const TokenStreamChars* ts);
|
||||
static inline TokenStreamAnyChars& anyChars(GeneralTokenStreamChars* ts);
|
||||
static inline const TokenStreamAnyChars& anyChars(const GeneralTokenStreamChars* ts);
|
||||
};
|
||||
|
||||
// Specify a value for an ES6 grammar parametrization. We have no enum for
|
||||
|
@ -1518,8 +1518,8 @@ class Parser<FullParseHandler, CharT> final
|
|||
};
|
||||
|
||||
template<class Parser>
|
||||
/* static */ inline TokenStreamAnyChars&
|
||||
ParserAnyCharsAccess<Parser>::anyChars(TokenStreamChars* ts)
|
||||
/* static */ inline const TokenStreamAnyChars&
|
||||
ParserAnyCharsAccess<Parser>::anyChars(const GeneralTokenStreamChars* ts)
|
||||
{
|
||||
// The structure we're walking through looks like this:
|
||||
//
|
||||
|
@ -1529,35 +1529,21 @@ ParserAnyCharsAccess<Parser>::anyChars(TokenStreamChars* ts)
|
|||
// TokenStreamAnyChars anyChars;
|
||||
// ...;
|
||||
// };
|
||||
// struct Parser : ParserBase
|
||||
// struct Parser : <class that ultimately inherits from ParserBase>
|
||||
// {
|
||||
// ...;
|
||||
// TokenStreamSpecific tokenStream;
|
||||
// ...;
|
||||
// };
|
||||
//
|
||||
// We're passed a TokenStreamChars* corresponding to a base class of
|
||||
// Parser::tokenStream. We cast that pointer to a TokenStreamSpecific*,
|
||||
// We're passed a GeneralTokenStreamChars* (this being a base class of
|
||||
// Parser::tokenStream). We cast that pointer to a TokenStreamSpecific*,
|
||||
// then translate that to the enclosing Parser*, then return the |anyChars|
|
||||
// member within.
|
||||
|
||||
auto* tss = static_cast<TokenStreamSpecific*>(ts);
|
||||
|
||||
auto tssAddr = reinterpret_cast<uintptr_t>(tss);
|
||||
|
||||
using ActualTokenStreamType = decltype(static_cast<Parser*>(nullptr)->tokenStream);
|
||||
static_assert(mozilla::IsSame<ActualTokenStreamType, TokenStreamSpecific>::value,
|
||||
"Parser::tokenStream must have type TokenStreamSpecific");
|
||||
|
||||
uintptr_t parserAddr = tssAddr - offsetof(Parser, tokenStream);
|
||||
|
||||
return reinterpret_cast<Parser*>(parserAddr)->anyChars;
|
||||
}
|
||||
|
||||
template<class Parser>
|
||||
/* static */ inline const TokenStreamAnyChars&
|
||||
ParserAnyCharsAccess<Parser>::anyChars(const typename Parser::TokenStream::CharsBase* ts)
|
||||
{
|
||||
static_assert(mozilla::IsBaseOf<GeneralTokenStreamChars,
|
||||
TokenStreamSpecific>::value,
|
||||
"the static_cast<> below assumes a base-class relationship");
|
||||
const auto* tss = static_cast<const TokenStreamSpecific*>(ts);
|
||||
|
||||
auto tssAddr = reinterpret_cast<uintptr_t>(tss);
|
||||
|
@ -1571,6 +1557,16 @@ ParserAnyCharsAccess<Parser>::anyChars(const typename Parser::TokenStream::Chars
|
|||
return reinterpret_cast<const Parser*>(parserAddr)->anyChars;
|
||||
}
|
||||
|
||||
template<class Parser>
|
||||
/* static */ inline TokenStreamAnyChars&
|
||||
ParserAnyCharsAccess<Parser>::anyChars(GeneralTokenStreamChars* ts)
|
||||
{
|
||||
const TokenStreamAnyChars& anyCharsConst =
|
||||
anyChars(const_cast<const GeneralTokenStreamChars*>(ts));
|
||||
|
||||
return const_cast<TokenStreamAnyChars&>(anyCharsConst);
|
||||
}
|
||||
|
||||
template <class ParseHandler, typename CharT>
|
||||
class MOZ_STACK_CLASS AutoAwaitIsKeyword
|
||||
{
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/IntegerTypeTraits.h"
|
||||
#include "mozilla/PodOperations.h"
|
||||
#include "mozilla/ScopeExit.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
|
@ -33,6 +34,7 @@
|
|||
#include "vm/Unicode.h"
|
||||
|
||||
using mozilla::ArrayLength;
|
||||
using mozilla::MakeScopeExit;
|
||||
using mozilla::Maybe;
|
||||
using mozilla::PodArrayZero;
|
||||
using mozilla::PodAssign;
|
||||
|
@ -545,7 +547,7 @@ TokenStreamSpecific<CharT, AnyCharsAccess>::getChar(int32_t* cp)
|
|||
// before it's ungotten.
|
||||
template<typename CharT, class AnyCharsAccess>
|
||||
int32_t
|
||||
TokenStreamSpecific<CharT, AnyCharsAccess>::getCharIgnoreEOL()
|
||||
GeneralTokenStreamChars<CharT, AnyCharsAccess>::getCharIgnoreEOL()
|
||||
{
|
||||
if (MOZ_LIKELY(userbuf.hasRawChars()))
|
||||
return userbuf.getRawChar();
|
||||
|
@ -565,7 +567,7 @@ TokenStreamAnyChars::undoGetChar()
|
|||
|
||||
template<typename CharT, class AnyCharsAccess>
|
||||
void
|
||||
TokenStreamSpecific<CharT, AnyCharsAccess>::ungetChar(int32_t c)
|
||||
GeneralTokenStreamChars<CharT, AnyCharsAccess>::ungetChar(int32_t c)
|
||||
{
|
||||
if (c == EOF)
|
||||
return;
|
||||
|
@ -588,9 +590,9 @@ TokenStreamSpecific<CharT, AnyCharsAccess>::ungetChar(int32_t c)
|
|||
}
|
||||
}
|
||||
|
||||
template<typename CharT, class AnyCharsAccess>
|
||||
template<typename CharT>
|
||||
void
|
||||
TokenStreamSpecific<CharT, AnyCharsAccess>::ungetCharIgnoreEOL(int32_t c)
|
||||
TokenStreamCharsBase<CharT>::ungetCharIgnoreEOL(int32_t c)
|
||||
{
|
||||
if (c == EOF)
|
||||
return;
|
||||
|
@ -599,6 +601,22 @@ TokenStreamSpecific<CharT, AnyCharsAccess>::ungetCharIgnoreEOL(int32_t c)
|
|||
userbuf.ungetRawChar();
|
||||
}
|
||||
|
||||
template<class AnyCharsAccess>
|
||||
void
|
||||
TokenStreamChars<char16_t, AnyCharsAccess>::ungetCodePointIgnoreEOL(uint32_t codePoint)
|
||||
{
|
||||
MOZ_ASSERT(!userbuf.atStart());
|
||||
|
||||
unsigned numUnits = 0;
|
||||
char16_t units[2];
|
||||
unicode::UTF16Encode(codePoint, units, &numUnits);
|
||||
|
||||
MOZ_ASSERT(numUnits == 1 || numUnits == 2);
|
||||
|
||||
while (numUnits-- > 0)
|
||||
ungetCharIgnoreEOL(units[numUnits]);
|
||||
}
|
||||
|
||||
// Return true iff |n| raw characters can be read from this without reading past
|
||||
// EOF or a newline, and copy those characters into |cp| if so. The characters
|
||||
// are not consumed: use skipChars(n) to do so after checking that the consumed
|
||||
|
@ -1271,23 +1289,6 @@ IsTokenSane(Token* tp)
|
|||
}
|
||||
#endif
|
||||
|
||||
template<class AnyCharsAccess>
|
||||
bool
|
||||
TokenStreamChars<char16_t, AnyCharsAccess>::matchTrailForLeadSurrogate(char16_t lead,
|
||||
uint32_t* codePoint)
|
||||
{
|
||||
TokenStreamSpecific* ts = asSpecific();
|
||||
|
||||
int32_t maybeTrail = ts->getCharIgnoreEOL();
|
||||
if (!unicode::IsTrailSurrogate(maybeTrail)) {
|
||||
ts->ungetCharIgnoreEOL(maybeTrail);
|
||||
return false;
|
||||
}
|
||||
|
||||
*codePoint = unicode::UTF16Decode(lead, maybeTrail);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<>
|
||||
MOZ_MUST_USE bool
|
||||
TokenStreamCharsBase<char16_t>::appendMultiUnitCodepointToTokenbuf(uint32_t codepoint)
|
||||
|
@ -1298,26 +1299,49 @@ TokenStreamCharsBase<char16_t>::appendMultiUnitCodepointToTokenbuf(uint32_t code
|
|||
return tokenbuf.append(lead) && tokenbuf.append(trail);
|
||||
}
|
||||
|
||||
template<class AnyCharsAccess>
|
||||
void
|
||||
TokenStreamChars<char16_t, AnyCharsAccess>::matchMultiUnitCodePointSlow(char16_t lead,
|
||||
uint32_t* codePoint)
|
||||
{
|
||||
MOZ_ASSERT(unicode::IsLeadSurrogate(lead),
|
||||
"matchMultiUnitCodepoint should have ensured |lead| is a lead "
|
||||
"surrogate");
|
||||
|
||||
int32_t maybeTrail = getCharIgnoreEOL();
|
||||
if (MOZ_LIKELY(unicode::IsTrailSurrogate(maybeTrail))) {
|
||||
*codePoint = unicode::UTF16Decode(lead, maybeTrail);
|
||||
} else {
|
||||
ungetCharIgnoreEOL(maybeTrail);
|
||||
*codePoint = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename CharT, class AnyCharsAccess>
|
||||
bool
|
||||
TokenStreamSpecific<CharT, AnyCharsAccess>::putIdentInTokenbuf(const CharT* identStart)
|
||||
{
|
||||
const CharT* tmp = userbuf.addressOfNextRawChar();
|
||||
const CharT* const originalAddress = userbuf.addressOfNextRawChar();
|
||||
userbuf.setAddressOfNextRawChar(identStart);
|
||||
|
||||
auto restoreNextRawCharAddress =
|
||||
MakeScopeExit([this, originalAddress]() {
|
||||
this->userbuf.setAddressOfNextRawChar(originalAddress);
|
||||
});
|
||||
|
||||
tokenbuf.clear();
|
||||
for (;;) {
|
||||
int32_t c = getCharIgnoreEOL();
|
||||
|
||||
uint32_t codePoint;
|
||||
if (isMultiUnitCodepoint(c, &codePoint)) {
|
||||
if (!matchMultiUnitCodePoint(c, &codePoint))
|
||||
return false;
|
||||
if (codePoint) {
|
||||
if (!unicode::IsIdentifierPart(codePoint))
|
||||
break;
|
||||
|
||||
if (!appendMultiUnitCodepointToTokenbuf(codePoint)) {
|
||||
userbuf.setAddressOfNextRawChar(tmp);
|
||||
if (!appendMultiUnitCodepointToTokenbuf(codePoint))
|
||||
return false;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
@ -1330,23 +1354,19 @@ TokenStreamSpecific<CharT, AnyCharsAccess>::putIdentInTokenbuf(const CharT* iden
|
|||
if (MOZ_UNLIKELY(unicode::IsSupplementary(qc))) {
|
||||
char16_t lead, trail;
|
||||
unicode::UTF16Encode(qc, &lead, &trail);
|
||||
if (!tokenbuf.append(lead) || !tokenbuf.append(trail)) {
|
||||
userbuf.setAddressOfNextRawChar(tmp);
|
||||
if (!tokenbuf.append(lead) || !tokenbuf.append(trail))
|
||||
return false;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
c = qc;
|
||||
}
|
||||
|
||||
if (!tokenbuf.append(c)) {
|
||||
userbuf.setAddressOfNextRawChar(tmp);
|
||||
if (!tokenbuf.append(c))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
userbuf.setAddressOfNextRawChar(tmp);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1500,13 +1520,17 @@ TokenStreamSpecific<CharT, AnyCharsAccess>::getTokenInternal(TokenKind* ttp, Mod
|
|||
goto identifier;
|
||||
}
|
||||
|
||||
uint32_t codePoint;
|
||||
if (isMultiUnitCodepoint(c, &codePoint) && unicode::IsUnicodeIDStart(codePoint)) {
|
||||
uint32_t codePoint = c;
|
||||
if (!matchMultiUnitCodePoint(c, &codePoint))
|
||||
goto error;
|
||||
if (codePoint && unicode::IsUnicodeIDStart(codePoint)) {
|
||||
hadUnicodeEscape = false;
|
||||
goto identifier;
|
||||
}
|
||||
|
||||
goto badchar;
|
||||
ungetCodePointIgnoreEOL(codePoint);
|
||||
error(JSMSG_ILLEGAL_CHARACTER);
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Get the token kind, based on the first char. The ordering of c1kind
|
||||
|
@ -1558,7 +1582,9 @@ TokenStreamSpecific<CharT, AnyCharsAccess>::getTokenInternal(TokenKind* ttp, Mod
|
|||
break;
|
||||
|
||||
uint32_t codePoint;
|
||||
if (isMultiUnitCodepoint(c, &codePoint)) {
|
||||
if (!matchMultiUnitCodePoint(c, &codePoint))
|
||||
goto error;
|
||||
if (codePoint) {
|
||||
if (!unicode::IsIdentifierPart(codePoint))
|
||||
break;
|
||||
|
||||
|
@ -1647,9 +1673,9 @@ TokenStreamSpecific<CharT, AnyCharsAccess>::getTokenInternal(TokenKind* ttp, Mod
|
|||
}
|
||||
|
||||
uint32_t codePoint;
|
||||
if (isMultiUnitCodepoint(c, &codePoint) &&
|
||||
unicode::IsIdentifierStart(codePoint))
|
||||
{
|
||||
if (!matchMultiUnitCodePoint(c, &codePoint))
|
||||
goto error;
|
||||
if (codePoint && unicode::IsIdentifierStart(codePoint)) {
|
||||
reportError(JSMSG_IDSTART_AFTER_NUMBER);
|
||||
goto error;
|
||||
}
|
||||
|
@ -1772,9 +1798,9 @@ TokenStreamSpecific<CharT, AnyCharsAccess>::getTokenInternal(TokenKind* ttp, Mod
|
|||
}
|
||||
|
||||
uint32_t codePoint;
|
||||
if (isMultiUnitCodepoint(c, &codePoint) &&
|
||||
unicode::IsIdentifierStart(codePoint))
|
||||
{
|
||||
if (!matchMultiUnitCodePoint(c, &codePoint))
|
||||
goto error;
|
||||
if (codePoint && unicode::IsIdentifierStart(codePoint)) {
|
||||
reportError(JSMSG_IDSTART_AFTER_NUMBER);
|
||||
goto error;
|
||||
}
|
||||
|
@ -1839,7 +1865,14 @@ TokenStreamSpecific<CharT, AnyCharsAccess>::getTokenInternal(TokenKind* ttp, Mod
|
|||
hadUnicodeEscape = true;
|
||||
goto identifier;
|
||||
}
|
||||
goto badchar;
|
||||
|
||||
// We could point "into" a mistyped escape, e.g. for "\u{41H}" we could
|
||||
// point at the 'H'. But we don't do that now, so the character after
|
||||
// the '\' isn't necessarily bad, so just point at the start of
|
||||
// the actually-invalid escape.
|
||||
ungetCharIgnoreEOL('\\');
|
||||
error(JSMSG_BAD_ESCAPE);
|
||||
goto error;
|
||||
}
|
||||
|
||||
case '|':
|
||||
|
@ -2056,9 +2089,11 @@ TokenStreamSpecific<CharT, AnyCharsAccess>::getTokenInternal(TokenKind* ttp, Mod
|
|||
}
|
||||
goto out;
|
||||
|
||||
badchar:
|
||||
default:
|
||||
reportError(JSMSG_ILLEGAL_CHARACTER);
|
||||
// We consumed a bad character/code point. Put it back so the error
|
||||
// location is the bad character.
|
||||
ungetCodePointIgnoreEOL(c);
|
||||
error(JSMSG_ILLEGAL_CHARACTER);
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
|
|
@ -73,30 +73,62 @@
|
|||
*
|
||||
* All such functionality lives in TokenStreamCharsBase<CharT>.
|
||||
*
|
||||
* == TokenStreamChars<CharT, AnyCharsAccess> → TokenStreamCharsBase<CharT> ==
|
||||
* == GeneralTokenStreamChars<CharT, AnyCharsAccess> →
|
||||
* TokenStreamCharsBase<CharT> ==
|
||||
*
|
||||
* Some functionality operates at a very low level upon character-type-specific
|
||||
* data, but in distinct ways. For example, "is this character the start of a
|
||||
* multi-character codepoint?" Consider how such functionality would work on
|
||||
* various encodings (hypothetically -- we haven't fully implemented any
|
||||
* particular single-byte encoding support yet):
|
||||
* Some functionality operates differently on different character types, just
|
||||
* as for TokenStreamCharsBase, but additionally requires access to character-
|
||||
* type-agnostic information in TokenStreamAnyChars. For example, getting the
|
||||
* next character performs different steps for different character types and
|
||||
* must access TokenStreamAnyChars to update line break information.
|
||||
*
|
||||
* * For two-byte text, the character must pass |unicode::IsLeadSurrogate|.
|
||||
* * For single-byte Latin-1 text, there are no multi-character codepoints.
|
||||
* * For single-byte UTF-8 text, the answer depends on how many high bits of
|
||||
* the character are set.
|
||||
* Such functionality, if it can be defined using the same algorithm for all
|
||||
* character types, lives in GeneralTokenStreamChars<CharT, AnyCharsAccess>.
|
||||
* The AnyCharsAccess parameter provides a way for a GeneralTokenStreamChars
|
||||
* instance to access its corresponding TokenStreamAnyChars, without inheriting
|
||||
* from it.
|
||||
*
|
||||
* GeneralTokenStreamChars<CharT, AnyCharsAccess> is just functionality, no
|
||||
* actual member data.
|
||||
*
|
||||
* Such functionality all lives in TokenStreamChars<CharT, AnyCharsAccess>, a
|
||||
* declared-but-not-defined template class whose specializations have a common
|
||||
* public interface (plus whatever private helper functions are desirable).
|
||||
*
|
||||
* Why the AnyCharsAccess parameter? Some functionality along these lines
|
||||
* really wants TokenStreamSpecific, below, e.g. to report an error. Providing
|
||||
* this parameter allows TokenStreamChars functions to statically cast to this
|
||||
* presumed superclass to access its functionality.
|
||||
* == TokenStreamChars<CharT, AnyCharsAccess> →
|
||||
* GeneralTokenStreamChars<CharT, AnyCharsAccess> ==
|
||||
*
|
||||
* TokenStreamChars<CharT, AnyCharsAccess> is just functionality, no actual
|
||||
* member data.
|
||||
* Some functionality is like that in GeneralTokenStreamChars, *but* it's
|
||||
* defined entirely differently for different character types.
|
||||
*
|
||||
* For example, consider "match a multi-code unit code point" (hypothetically:
|
||||
* we've only implemented two-byte tokenizing right now):
|
||||
*
|
||||
* * For two-byte text, there must be two code units to get, the leading code
|
||||
* unit must be a UTF-16 lead surrogate, and the trailing code unit must be
|
||||
* a UTF-16 trailing surrogate. (If any of these fail to hold, a next code
|
||||
* unit encodes that code point and is not multi-code unit.)
|
||||
* * For single-byte Latin-1 text, there are no multi-code unit code points.
|
||||
* * For single-byte UTF-8 text, the first code unit must have N > 1 of its
|
||||
* highest bits set (and the next unset), and |N - 1| successive code units
|
||||
* must have their high bit set and next-highest bit unset, *and*
|
||||
* concatenating all unconstrained bits together must not produce a code
|
||||
* point value that could have been encoded in fewer code units.
|
||||
*
|
||||
* This functionality can't be implemented as member functions in
|
||||
* GeneralTokenStreamChars because we'd need to *partially specialize* those
|
||||
* functions -- hold CharT constant while letting AnyCharsAccess vary. But
|
||||
* C++ forbids function template partial specialization like this: either you
|
||||
* fix *all* parameters or you fix none of them.
|
||||
*
|
||||
* Fortunately, C++ *does* allow *class* template partial specialization. So
|
||||
* TokenStreamChars is a template class with one specialization per CharT.
|
||||
* Functions can be defined differently in the different specializations,
|
||||
* because AnyCharsAccess as the only template parameter on member functions
|
||||
* *can* vary.
|
||||
*
|
||||
* All TokenStreamChars<CharT, AnyCharsAccess> specializations, one per CharT,
|
||||
* are just functionality, no actual member data.
|
||||
*
|
||||
* == TokenStreamSpecific<CharT, AnyCharsAccess> →
|
||||
* TokenStreamChars<CharT, AnyCharsAccess>, TokenStreamShared ==
|
||||
|
@ -472,6 +504,7 @@ class TokenStreamAnyChars
|
|||
TokenStreamAnyChars(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
StrictModeGetter* smg);
|
||||
|
||||
template<typename CharT, class AnyCharsAccess> friend class GeneralTokenStreamChars;
|
||||
template<typename CharT, class AnyCharsAccess> friend class TokenStreamSpecific;
|
||||
|
||||
// Accessors.
|
||||
|
@ -780,6 +813,9 @@ class TokenStreamAnyChars
|
|||
template<typename CharT>
|
||||
class TokenStreamCharsBase
|
||||
{
|
||||
protected:
|
||||
void ungetCharIgnoreEOL(int32_t c);
|
||||
|
||||
public:
|
||||
using CharBuffer = Vector<CharT, 32>;
|
||||
|
||||
|
@ -959,43 +995,93 @@ TokenStreamCharsBase<char16_t>::atomizeChars(JSContext* cx, const char16_t* char
|
|||
return AtomizeChars(cx, chars, length);
|
||||
}
|
||||
|
||||
template<typename CharT, class AnyCharsAccess> class TokenStreamChars;
|
||||
|
||||
template<class AnyCharsAccess>
|
||||
class TokenStreamChars<char16_t, AnyCharsAccess>
|
||||
: public TokenStreamCharsBase<char16_t>
|
||||
template<typename CharT, class AnyCharsAccess>
|
||||
class GeneralTokenStreamChars
|
||||
: public TokenStreamCharsBase<CharT>
|
||||
{
|
||||
using Self = TokenStreamChars<char16_t, AnyCharsAccess>;
|
||||
using CharsBase = TokenStreamCharsBase<char16_t>;
|
||||
using CharsSharedBase = TokenStreamCharsBase<CharT>;
|
||||
|
||||
using TokenStreamSpecific = frontend::TokenStreamSpecific<char16_t, AnyCharsAccess>;
|
||||
protected:
|
||||
using typename CharsSharedBase::TokenBuf;
|
||||
|
||||
using CharsSharedBase::userbuf;
|
||||
|
||||
public:
|
||||
using CharsSharedBase::CharsSharedBase;
|
||||
|
||||
TokenStreamAnyChars& anyCharsAccess() {
|
||||
return AnyCharsAccess::anyChars(this);
|
||||
}
|
||||
|
||||
const TokenStreamAnyChars& anyCharsAccess() const {
|
||||
return AnyCharsAccess::anyChars(this);
|
||||
}
|
||||
|
||||
using TokenStreamSpecific = frontend::TokenStreamSpecific<CharT, AnyCharsAccess>;
|
||||
|
||||
TokenStreamSpecific* asSpecific() {
|
||||
static_assert(mozilla::IsBaseOf<Self, TokenStreamSpecific>::value,
|
||||
static_assert(mozilla::IsBaseOf<GeneralTokenStreamChars, TokenStreamSpecific>::value,
|
||||
"static_cast below presumes an inheritance relationship");
|
||||
|
||||
return static_cast<TokenStreamSpecific*>(this);
|
||||
}
|
||||
|
||||
bool matchTrailForLeadSurrogate(char16_t lead, uint32_t* codePoint);
|
||||
int32_t getCharIgnoreEOL();
|
||||
|
||||
public:
|
||||
using CharsBase::CharsBase;
|
||||
void ungetChar(int32_t c);
|
||||
};
|
||||
|
||||
TokenStreamAnyChars& anyChars() {
|
||||
return AnyCharsAccess::anyChars(this);
|
||||
}
|
||||
template<typename CharT, class AnyCharsAccess> class TokenStreamChars;
|
||||
|
||||
const TokenStreamAnyChars& anyChars() const {
|
||||
return AnyCharsAccess::anyChars(this);
|
||||
}
|
||||
template<class AnyCharsAccess>
|
||||
class TokenStreamChars<char16_t, AnyCharsAccess>
|
||||
: public GeneralTokenStreamChars<char16_t, AnyCharsAccess>
|
||||
{
|
||||
private:
|
||||
using Self = TokenStreamChars<char16_t, AnyCharsAccess>;
|
||||
using GeneralCharsBase = GeneralTokenStreamChars<char16_t, AnyCharsAccess>;
|
||||
using CharsSharedBase = TokenStreamCharsBase<char16_t>;
|
||||
|
||||
MOZ_ALWAYS_INLINE bool isMultiUnitCodepoint(char16_t c, uint32_t* codepoint) {
|
||||
using GeneralCharsBase::asSpecific;
|
||||
|
||||
using typename GeneralCharsBase::TokenStreamSpecific;
|
||||
|
||||
void matchMultiUnitCodePointSlow(char16_t lead, uint32_t* codePoint);
|
||||
|
||||
protected:
|
||||
using GeneralCharsBase::anyCharsAccess;
|
||||
using GeneralCharsBase::getCharIgnoreEOL;
|
||||
using CharsSharedBase::ungetCharIgnoreEOL;
|
||||
using GeneralCharsBase::userbuf;
|
||||
|
||||
using GeneralCharsBase::GeneralCharsBase;
|
||||
|
||||
// |c| must be the code unit just gotten. If it and the subsequent code
|
||||
// unit form a valid surrogate pair, get the second code unit, set
|
||||
// |*codePoint| to the code point encoded by the surrogate pair, and return
|
||||
// true. Otherwise do not get a second code unit, set |*codePoint = 0|,
|
||||
// and return true.
|
||||
//
|
||||
// ECMAScript specifically requires that unpaired UTF-16 surrogates be
|
||||
// treated as the corresponding code point and not as an error. See
|
||||
// <https://tc39.github.io/ecma262/#sec-ecmascript-language-types-string-type>.
|
||||
// Therefore this function always returns true. The |bool| return type
|
||||
// exists so that a future UTF-8 |TokenStreamChars| can treat malformed
|
||||
// multi-code unit UTF-8 sequences as errors. (Because ECMAScript only
|
||||
// interprets UTF-16 inputs, the process of translating the UTF-8 to UTF-16
|
||||
// would fail, so no script should execute. Technically, we shouldn't even
|
||||
// be tokenizing -- but it probably isn't realistic to assume every user
|
||||
// correctly passes only valid UTF-8, at least not without better types in
|
||||
// our codebase for strings that by construction only contain valid UTF-8.)
|
||||
MOZ_ALWAYS_INLINE bool matchMultiUnitCodePoint(char16_t c, uint32_t* codePoint) {
|
||||
if (MOZ_LIKELY(!unicode::IsLeadSurrogate(c)))
|
||||
return false;
|
||||
|
||||
return matchTrailForLeadSurrogate(c, codepoint);
|
||||
*codePoint = 0;
|
||||
else
|
||||
matchMultiUnitCodePointSlow(c, codePoint);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ungetCodePointIgnoreEOL(uint32_t codePoint);
|
||||
};
|
||||
|
||||
// TokenStream is the lexical scanner for JavaScript source text.
|
||||
|
@ -1046,6 +1132,7 @@ class MOZ_STACK_CLASS TokenStreamSpecific
|
|||
{
|
||||
public:
|
||||
using CharsBase = TokenStreamChars<CharT, AnyCharsAccess>;
|
||||
using GeneralCharsBase = GeneralTokenStreamChars<CharT, AnyCharsAccess>;
|
||||
using CharsSharedBase = TokenStreamCharsBase<CharT>;
|
||||
|
||||
// Anything inherited through a base class whose type depends upon this
|
||||
|
@ -1063,6 +1150,7 @@ class MOZ_STACK_CLASS TokenStreamSpecific
|
|||
using typename CharsSharedBase::Position;
|
||||
|
||||
public:
|
||||
using GeneralCharsBase::anyCharsAccess;
|
||||
using CharsSharedBase::getTokenbuf;
|
||||
|
||||
private:
|
||||
|
@ -1073,22 +1161,18 @@ class MOZ_STACK_CLASS TokenStreamSpecific
|
|||
using CharsSharedBase::appendMultiUnitCodepointToTokenbuf;
|
||||
using CharsSharedBase::atomizeChars;
|
||||
using CharsSharedBase::copyTokenbufTo;
|
||||
using CharsBase::isMultiUnitCodepoint;
|
||||
using GeneralCharsBase::getCharIgnoreEOL;
|
||||
using CharsBase::matchMultiUnitCodePoint;
|
||||
using CharsSharedBase::tokenbuf;
|
||||
using GeneralCharsBase::ungetChar;
|
||||
using CharsSharedBase::ungetCharIgnoreEOL;
|
||||
using CharsBase::ungetCodePointIgnoreEOL;
|
||||
using CharsSharedBase::userbuf;
|
||||
|
||||
public:
|
||||
TokenStreamSpecific(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
const CharT* base, size_t length);
|
||||
|
||||
TokenStreamAnyChars& anyCharsAccess() {
|
||||
return CharsBase::anyChars();
|
||||
}
|
||||
|
||||
const TokenStreamAnyChars& anyCharsAccess() const {
|
||||
return CharsBase::anyChars();
|
||||
}
|
||||
|
||||
// If there is an invalid escape in a template, report it and return false,
|
||||
// otherwise return true.
|
||||
bool checkForInvalidTemplateEscapeError() {
|
||||
|
@ -1360,10 +1444,7 @@ class MOZ_STACK_CLASS TokenStreamSpecific
|
|||
// and store the character in |*c|. Return false and leave |*c| undefined
|
||||
// on failure.
|
||||
MOZ_MUST_USE bool getChar(int32_t* cp);
|
||||
int32_t getCharIgnoreEOL();
|
||||
|
||||
void ungetChar(int32_t c);
|
||||
void ungetCharIgnoreEOL(int32_t c);
|
||||
Token* newToken(ptrdiff_t adjust);
|
||||
uint32_t peekUnicodeEscape(uint32_t* codePoint);
|
||||
uint32_t peekExtendedUnicodeEscape(uint32_t* codePoint);
|
||||
|
|
|
@ -261,6 +261,7 @@ MSG_DEF(JSMSG_FROM_AFTER_IMPORT_CLAUSE, 0, JSEXN_SYNTAXERR, "missing keyword 'fr
|
|||
MSG_DEF(JSMSG_FROM_AFTER_EXPORT_STAR, 0, JSEXN_SYNTAXERR, "missing keyword 'from' after export *")
|
||||
MSG_DEF(JSMSG_GARBAGE_AFTER_INPUT, 2, JSEXN_SYNTAXERR, "unexpected garbage after {0}, starting with {1}")
|
||||
MSG_DEF(JSMSG_IDSTART_AFTER_NUMBER, 0, JSEXN_SYNTAXERR, "identifier starts immediately after numeric literal")
|
||||
MSG_DEF(JSMSG_BAD_ESCAPE, 0, JSEXN_SYNTAXERR, "invalid escape sequence")
|
||||
MSG_DEF(JSMSG_ILLEGAL_CHARACTER, 0, JSEXN_SYNTAXERR, "illegal character")
|
||||
MSG_DEF(JSMSG_IMPORT_DECL_AT_TOP_LEVEL, 0, JSEXN_SYNTAXERR, "import declarations may only appear at top level of a module")
|
||||
MSG_DEF(JSMSG_OF_AFTER_FOR_LOOP_DECL, 0, JSEXN_SYNTAXERR, "a declaration in the head of a for-of loop can't have an initializer")
|
||||
|
|
|
@ -19,7 +19,7 @@ function test()
|
|||
printBugNumber(BUGNUMBER);
|
||||
printStatus (summary);
|
||||
|
||||
expect = 'SyntaxError: illegal character';
|
||||
expect = 'SyntaxError';
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -29,7 +29,7 @@ function test()
|
|||
}
|
||||
catch(ex)
|
||||
{
|
||||
actual = ex + '';
|
||||
actual = ex.constructor.name;
|
||||
}
|
||||
|
||||
reportCompare(expect, actual, summary);
|
||||
|
|
|
@ -19,7 +19,7 @@ function test()
|
|||
printBugNumber(BUGNUMBER);
|
||||
printStatus (summary);
|
||||
|
||||
expect = 'SyntaxError: illegal character';
|
||||
expect = 'SyntaxError';
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -27,7 +27,7 @@ function test()
|
|||
}
|
||||
catch(ex)
|
||||
{
|
||||
actual = ex + '';
|
||||
actual = ex.constructor.name;
|
||||
}
|
||||
|
||||
reportCompare(expect, actual, summary);
|
||||
|
|
|
@ -2344,23 +2344,24 @@ static const char kChannelPref[] = "app.update.channel";
|
|||
|
||||
// clang-format off
|
||||
static const char kPrefFileHeader[] =
|
||||
"# Mozilla User Preferences"
|
||||
"// Mozilla User Preferences"
|
||||
NS_LINEBREAK
|
||||
NS_LINEBREAK
|
||||
"/* Do not edit this file."
|
||||
"// DO NOT EDIT THIS FILE."
|
||||
NS_LINEBREAK
|
||||
" *"
|
||||
"//"
|
||||
NS_LINEBREAK
|
||||
" * If you make changes to this file while the application is running,"
|
||||
"// If you make changes to this file while the application is running,"
|
||||
NS_LINEBREAK
|
||||
" * the changes will be overwritten when the application exits."
|
||||
"// the changes will be overwritten when the application exits."
|
||||
NS_LINEBREAK
|
||||
" *"
|
||||
"//"
|
||||
NS_LINEBREAK
|
||||
" * To make a manual change to preferences, you can visit the URL "
|
||||
"about:config"
|
||||
"// To change a preference value, you can either:"
|
||||
NS_LINEBREAK
|
||||
" */"
|
||||
"// - modify it via the UI (e.g. via about:config in the browser); or"
|
||||
NS_LINEBREAK
|
||||
"// - set it within a user.js file in your profile."
|
||||
NS_LINEBREAK
|
||||
NS_LINEBREAK;
|
||||
// clang-format on
|
||||
|
|
|
@ -497,48 +497,29 @@ pref("parse.error", true);;
|
|||
//-------------------------------------------------------------------------
|
||||
|
||||
// In all of the following we have a \n, a \r, a \r\n, and then an error, so
|
||||
// the error is on line 4.
|
||||
// the error is on line 4. (Note: these ones don't use raw string literals
|
||||
// because MSVC somehow swallows any \r that appears in them.)
|
||||
|
||||
// XXX: these are temporarily commented out due to differing results on Windows
|
||||
#if 0
|
||||
|
||||
P(R"(
|
||||
|
||||
bad
|
||||
)",
|
||||
P("\n \r \r\n bad",
|
||||
"test:4: prefs parse error: unknown keyword"
|
||||
);
|
||||
|
||||
P(R"(#
|
||||
#
#
|
||||
bad
|
||||
)",
|
||||
P("#\n#\r#\r\n bad",
|
||||
"test:4: prefs parse error: unknown keyword"
|
||||
);
|
||||
|
||||
P(R"(//
|
||||
//
//
|
||||
bad
|
||||
)",
|
||||
P("//\n//\r//\r\n bad",
|
||||
"test:4: prefs parse error: unknown keyword"
|
||||
);
|
||||
|
||||
P(R"(/*
|
||||
|
||||
*/ bad
|
||||
)",
|
||||
P("/*\n \r \r\n*/ bad",
|
||||
"test:4: prefs parse error: unknown keyword"
|
||||
);
|
||||
|
||||
// Note: the escape sequences do *not* affect the line number.
|
||||
P(R"(pref("foo\n
|
||||
\r
foo\r\n
|
||||
foo", bad
|
||||
)",
|
||||
P("pref(\"foo\\n\n foo\\r\r foo\\r\\n\r\n foo\", bad);",
|
||||
"test:4: prefs parse error: unknown keyword"
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
// clang-format on
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ geckoview:
|
|||
instance-size: xlarge
|
||||
loopback-video: true
|
||||
e10s: false
|
||||
target: geckoview_example.apk
|
||||
mozharness:
|
||||
script: android_emulator_unittest.py
|
||||
no-read-buildbot-config: true
|
||||
|
|
|
@ -393,6 +393,15 @@ test_description_schema = Schema({
|
|||
Any(basestring, None),
|
||||
),
|
||||
|
||||
# The target name, specifying the build artifact to be tested.
|
||||
# If None or not specified, a transform sets the target based on OS:
|
||||
# target.dmg (Mac), target.apk (Android), target.tar.bz2 (Linux),
|
||||
# or target.zip (Windows).
|
||||
Optional('target'): optionally_keyed_by(
|
||||
'test-platform',
|
||||
Any(basestring, None),
|
||||
),
|
||||
|
||||
}, required=True)
|
||||
|
||||
|
||||
|
@ -499,17 +508,19 @@ def setup_talos(config, tests):
|
|||
def set_target(config, tests):
|
||||
for test in tests:
|
||||
build_platform = test['build-platform']
|
||||
if build_platform.startswith('macosx'):
|
||||
target = 'target.dmg'
|
||||
elif build_platform.startswith('android'):
|
||||
if 'geckoview' in test['test-name']:
|
||||
target = 'geckoview_example.apk'
|
||||
else:
|
||||
target = None
|
||||
if 'target' in test:
|
||||
resolve_keyed_by(test, 'target', item_name=test['test-name'])
|
||||
target = test['target']
|
||||
if not target:
|
||||
if build_platform.startswith('macosx'):
|
||||
target = 'target.dmg'
|
||||
elif build_platform.startswith('android'):
|
||||
target = 'target.apk'
|
||||
elif build_platform.startswith('win'):
|
||||
target = 'target.zip'
|
||||
else:
|
||||
target = 'target.tar.bz2'
|
||||
elif build_platform.startswith('win'):
|
||||
target = 'target.zip'
|
||||
else:
|
||||
target = 'target.tar.bz2'
|
||||
test['mozharness']['build-artifact-name'] = 'public/build/' + target
|
||||
|
||||
yield test
|
||||
|
|
|
@ -376,6 +376,11 @@ class AndroidEmulatorTest(TestingMixin, EmulatorMixin, BaseScript, MozbaseMixin)
|
|||
self.warning("Failed to take screenshot: %s" % err.strerror)
|
||||
|
||||
def _query_package_name(self):
|
||||
if self.app_name is None:
|
||||
# For convenience, assume geckoview_example when install target
|
||||
# looks like geckoview.
|
||||
if 'geckoview' in self.installer_path:
|
||||
self.app_name = 'org.mozilla.geckoview_example'
|
||||
if self.app_name is None:
|
||||
# Find appname from package-name.txt - assumes download-and-extract
|
||||
# has completed successfully.
|
||||
|
|
|
@ -129,7 +129,7 @@ function limitProperties(name, obj, count, log) {
|
|||
// properties.
|
||||
if (name === "data" && (
|
||||
key === "max_pause" ||
|
||||
key === "num_slices" ||
|
||||
key === "slices" ||
|
||||
key === "slices_list" ||
|
||||
key === "status" ||
|
||||
key === "timestamp" ||
|
||||
|
@ -156,9 +156,6 @@ function limitProperties(name, obj, count, log) {
|
|||
* etc.
|
||||
*/
|
||||
function limitSize(data, log) {
|
||||
// Store the number of slices so we know if we lost any at the end.
|
||||
data.num_slices = data.slices_list.length;
|
||||
|
||||
data.slices_list.sort((a, b) => b.pause - a.pause);
|
||||
|
||||
if (data.slices_list.length > MAX_SLICES) {
|
||||
|
|
|
@ -30,7 +30,7 @@ function run_test() {
|
|||
GCTelemetry.observeRaw(make_gc());
|
||||
// Get it back.
|
||||
assert_num_entries(1, false);
|
||||
Assert.equal(20, Object.keys(get_entry()).length);
|
||||
Assert.equal(19, Object.keys(get_entry()).length);
|
||||
// "true" will cause the entry to be clared.
|
||||
assert_num_entries(1, true);
|
||||
// There are currently no entries.
|
||||
|
@ -49,18 +49,18 @@ function run_test() {
|
|||
|
||||
// Exactly the limit of fields.
|
||||
let my_gc_24 = make_gc();
|
||||
for (let i = 0; i < 4; i++) {
|
||||
for (let i = 0; i < 5; i++) {
|
||||
my_gc_24["new_property_" + i] = "Data";
|
||||
}
|
||||
GCTelemetry.observeRaw(my_gc_24);
|
||||
// Assert that it was recorded but has only 7 fields.
|
||||
// Assert that it was recorded has all 24 fields.
|
||||
Assert.equal(24, Object.keys(get_entry()).length);
|
||||
assert_num_entries(1, true);
|
||||
assert_num_entries(0, false);
|
||||
|
||||
// Exactly too many fields.
|
||||
let my_gc_25 = make_gc();
|
||||
for (let i = 0; i < 5; i++) {
|
||||
for (let i = 0; i < 6; i++) {
|
||||
my_gc_25["new_property_" + i] = "Data";
|
||||
}
|
||||
GCTelemetry.observeRaw(my_gc_25);
|
||||
|
|
Загрузка…
Ссылка в новой задаче