1336783 - Remove TokenStream::KeywordIsName.
This commit is contained in:
parent
165084547d
commit
2bb2a37638
|
@ -63,7 +63,7 @@ included_inclnames_to_ignore = set([
|
|||
'devtools/Instruments.h', # we ignore devtools/ in general
|
||||
'double-conversion.h', # strange MFBT case
|
||||
'javascript-trace.h', # generated in $OBJDIR if HAVE_DTRACE is defined
|
||||
'jsautokw.h', # generated in $OBJDIR
|
||||
'frontend/ReservedWordsGenerated.h', # generated in $OBJDIR
|
||||
'jscustomallocator.h', # provided by embedders; allowed to be missing
|
||||
'js-config.h', # generated in $OBJDIR
|
||||
'fdlibm.h', # fdlibm
|
||||
|
@ -99,7 +99,7 @@ included_inclnames_to_ignore = set([
|
|||
# ignore #includes of them when checking #include ordering.
|
||||
oddly_ordered_inclnames = set([
|
||||
'ctypes/typedefs.h', # Included multiple times in the body of ctypes/CTypes.h
|
||||
'jsautokw.h', # Included in the body of frontend/TokenStream.h
|
||||
'frontend/ReservedWordsGenerated.h', # Included in the body of frontend/TokenStream.h
|
||||
'jswin.h', # Must be #included before <psapi.h>
|
||||
'machine/endian.h', # Must be included after <sys/types.h> on BSD
|
||||
'winbase.h', # Must precede other system headers(?)
|
||||
|
|
|
@ -0,0 +1,213 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
import re
|
||||
import sys
|
||||
|
||||
def read_reserved_word_list(filename):
|
||||
macro_pat = re.compile(r"^\s*macro\(([^,]+), *[^,]+, *[^\)]+\)\s*\\?$")
|
||||
|
||||
reserved_word_list = []
|
||||
index = 0
|
||||
with open(filename, 'r') as f:
|
||||
for line in f:
|
||||
m = macro_pat.search(line)
|
||||
if m:
|
||||
reserved_word_list.append((index, m.group(1)))
|
||||
index += 1
|
||||
|
||||
assert(len(reserved_word_list) != 0)
|
||||
|
||||
return reserved_word_list
|
||||
|
||||
def line(opt, s):
|
||||
opt['output'].write('{}{}\n'.format(' ' * opt['indent_level'], s))
|
||||
|
||||
def indent(opt):
|
||||
opt['indent_level'] += 1
|
||||
|
||||
def dedent(opt):
|
||||
opt['indent_level'] -= 1
|
||||
|
||||
def span_and_count_at(reserved_word_list, column):
|
||||
assert(len(reserved_word_list) != 0);
|
||||
|
||||
chars_dict = {}
|
||||
for index, word in reserved_word_list:
|
||||
chars_dict[ord(word[column])] = True
|
||||
|
||||
chars = sorted(chars_dict.keys())
|
||||
return chars[-1] - chars[0] + 1, len(chars)
|
||||
|
||||
def optimal_switch_column(opt, reserved_word_list, columns, unprocessed_columns):
|
||||
assert(len(reserved_word_list) != 0);
|
||||
assert(unprocessed_columns != 0);
|
||||
|
||||
min_count = 0
|
||||
min_span = 0
|
||||
min_count_index = 0
|
||||
min_span_index = 0
|
||||
|
||||
for index in range(0, unprocessed_columns):
|
||||
span, count = span_and_count_at(reserved_word_list, columns[index])
|
||||
assert(span != 0)
|
||||
|
||||
if span == 1:
|
||||
assert(count == 1)
|
||||
return 1, True
|
||||
|
||||
assert(count != 1)
|
||||
if index == 0 or min_span > span:
|
||||
min_span = span
|
||||
min_span_index = index
|
||||
|
||||
if index == 0 or min_count > count:
|
||||
min_count = count
|
||||
min_count_index = index
|
||||
|
||||
if min_count <= opt['use_if_threshold']:
|
||||
return min_count_index, True
|
||||
|
||||
return min_span_index, False
|
||||
|
||||
def split_list_per_column(reserved_word_list, column):
|
||||
assert(len(reserved_word_list) != 0);
|
||||
|
||||
column_dict = {}
|
||||
for item in reserved_word_list:
|
||||
index, word = item
|
||||
per_column = column_dict.setdefault(word[column], [])
|
||||
per_column.append(item)
|
||||
|
||||
return sorted(column_dict.items(), key=lambda (char, word): ord(char))
|
||||
|
||||
def generate_letter_switch(opt, unprocessed_columns, reserved_word_list,
|
||||
columns=None):
|
||||
assert(len(reserved_word_list) != 0);
|
||||
|
||||
if not columns:
|
||||
columns = range(0, unprocessed_columns)
|
||||
|
||||
if len(reserved_word_list) == 1:
|
||||
index, word = reserved_word_list[0]
|
||||
|
||||
if unprocessed_columns == 0:
|
||||
line(opt, 'JSRW_GOT_MATCH({}) /* {} */'.format(index, word))
|
||||
return
|
||||
|
||||
if unprocessed_columns > opt['char_tail_test_threshold']:
|
||||
line(opt, 'JSRW_TEST_GUESS({}) /* {} */'.format(index, word))
|
||||
return
|
||||
|
||||
conds = []
|
||||
for column in columns[0:unprocessed_columns]:
|
||||
quoted = repr(word[column])
|
||||
conds.append('JSRW_AT({})=={}'.format(column, quoted))
|
||||
|
||||
line(opt, 'if ({}) {{'.format(' && '.join(conds)))
|
||||
|
||||
indent(opt)
|
||||
line(opt, 'JSRW_GOT_MATCH({}) /* {} */'.format(index, word))
|
||||
dedent(opt)
|
||||
|
||||
line(opt, '}')
|
||||
line(opt, 'JSRW_NO_MATCH()')
|
||||
return
|
||||
|
||||
assert(unprocessed_columns != 0);
|
||||
|
||||
optimal_column_index, use_if = optimal_switch_column(opt, reserved_word_list,
|
||||
columns,
|
||||
unprocessed_columns)
|
||||
optimal_column = columns[optimal_column_index]
|
||||
|
||||
# Make a copy to avoid breaking passed list.
|
||||
columns = columns[:]
|
||||
columns[optimal_column_index] = columns[unprocessed_columns - 1]
|
||||
|
||||
list_per_column = split_list_per_column(reserved_word_list, optimal_column)
|
||||
|
||||
if not use_if:
|
||||
line(opt, 'switch (JSRW_AT({})) {{'.format(optimal_column))
|
||||
|
||||
for char, reserved_word_list_per_column in list_per_column:
|
||||
quoted = repr(char)
|
||||
if use_if:
|
||||
line(opt, 'if (JSRW_AT({}) == {}) {{'.format(optimal_column,
|
||||
quoted))
|
||||
else:
|
||||
line(opt, ' case {}:'.format(quoted))
|
||||
|
||||
indent(opt)
|
||||
generate_letter_switch(opt, unprocessed_columns - 1,
|
||||
reserved_word_list_per_column, columns)
|
||||
dedent(opt)
|
||||
|
||||
if use_if:
|
||||
line(opt, '}')
|
||||
|
||||
if not use_if:
|
||||
line(opt, '}')
|
||||
|
||||
line(opt, 'JSRW_NO_MATCH()')
|
||||
|
||||
def split_list_per_length(reserved_word_list):
|
||||
assert(len(reserved_word_list) != 0);
|
||||
|
||||
length_dict = {}
|
||||
for item in reserved_word_list:
|
||||
index, word = item
|
||||
per_length = length_dict.setdefault(len(word), [])
|
||||
per_length.append(item)
|
||||
|
||||
return sorted(length_dict.items(), key=lambda (length, word): length)
|
||||
|
||||
def generate_switch(opt, reserved_word_list):
|
||||
assert(len(reserved_word_list) != 0);
|
||||
|
||||
line(opt, '/*')
|
||||
line(opt, ' * Generating switch for the list of {} entries:'.format(len(reserved_word_list)))
|
||||
for index, word in reserved_word_list:
|
||||
line(opt, ' * {}'.format(word))
|
||||
line(opt, ' */')
|
||||
|
||||
list_per_length = split_list_per_length(reserved_word_list)
|
||||
|
||||
use_if = False
|
||||
if len(list_per_length) < opt['use_if_threshold']:
|
||||
use_if = True
|
||||
|
||||
if not use_if:
|
||||
line(opt, 'switch (JSRW_LENGTH()) {')
|
||||
|
||||
for length, reserved_word_list_per_length in list_per_length:
|
||||
if use_if:
|
||||
line(opt, 'if (JSRW_LENGTH() == {}) {{'.format(length))
|
||||
else:
|
||||
line(opt, ' case {}:'.format(length))
|
||||
|
||||
indent(opt)
|
||||
generate_letter_switch(opt, length, reserved_word_list_per_length)
|
||||
dedent(opt)
|
||||
|
||||
if use_if:
|
||||
line(opt, '}')
|
||||
|
||||
if not use_if:
|
||||
line(opt, '}')
|
||||
line(opt, 'JSRW_NO_MATCH()')
|
||||
|
||||
def main(output, reserved_words_h):
|
||||
reserved_word_list = read_reserved_word_list(reserved_words_h)
|
||||
|
||||
opt = {
|
||||
'indent_level': 1,
|
||||
'use_if_threshold': 3,
|
||||
'char_tail_test_threshold': 4,
|
||||
'output': output
|
||||
}
|
||||
generate_switch(opt, reserved_word_list)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.stdout, *sys.argv[1:])
|
File diff suppressed because it is too large
Load Diff
|
@ -734,6 +734,9 @@ class UsedNameTracker
|
|||
}
|
||||
};
|
||||
|
||||
template <typename ParseHandler>
|
||||
class AutoAwaitIsKeyword;
|
||||
|
||||
class ParserBase : public StrictModeGetter
|
||||
{
|
||||
private:
|
||||
|
@ -783,7 +786,13 @@ class ParserBase : public StrictModeGetter
|
|||
/* Unexpected end of input, i.e. TOK_EOF not at top-level. */
|
||||
bool isUnexpectedEOF_:1;
|
||||
|
||||
bool awaitIsKeyword_:1;
|
||||
|
||||
public:
|
||||
bool awaitIsKeyword() const {
|
||||
return awaitIsKeyword_;
|
||||
}
|
||||
|
||||
ParserBase(ExclusiveContext* cx, LifoAlloc& alloc, const ReadOnlyCompileOptions& options,
|
||||
const char16_t* chars, size_t length, bool foldConstants,
|
||||
UsedNameTracker& usedNames, Parser<SyntaxParseHandler>* syntaxParser,
|
||||
|
@ -998,6 +1007,9 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
|
|||
Parser<SyntaxParseHandler>* syntaxParser, LazyScript* lazyOuterFunction);
|
||||
~Parser();
|
||||
|
||||
friend class AutoAwaitIsKeyword<ParseHandler>;
|
||||
void setAwaitIsKeyword(bool isKeyword);
|
||||
|
||||
bool checkOptions();
|
||||
|
||||
// A Parser::Mark is the extension of the LifoAlloc::Mark to the entire
|
||||
|
@ -1047,8 +1059,6 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
|
|||
|
||||
void trace(JSTracer* trc);
|
||||
|
||||
bool checkUnescapedName();
|
||||
|
||||
private:
|
||||
Parser* thisForCtor() { return this; }
|
||||
|
||||
|
@ -1321,17 +1331,22 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
|
|||
Node classDefinition(YieldHandling yieldHandling, ClassContext classContext,
|
||||
DefaultHandling defaultHandling);
|
||||
|
||||
PropertyName* labelOrIdentifierReference(YieldHandling yieldHandling,
|
||||
bool yieldTokenizedAsName);
|
||||
bool checkLabelOrIdentifierReference(HandlePropertyName ident,
|
||||
uint32_t offset,
|
||||
YieldHandling yieldHandling);
|
||||
|
||||
bool checkBindingIdentifier(HandlePropertyName ident,
|
||||
uint32_t offset,
|
||||
YieldHandling yieldHandling);
|
||||
|
||||
PropertyName* labelOrIdentifierReference(YieldHandling yieldHandling);
|
||||
|
||||
PropertyName* labelIdentifier(YieldHandling yieldHandling) {
|
||||
return labelOrIdentifierReference(yieldHandling, false);
|
||||
return labelOrIdentifierReference(yieldHandling);
|
||||
}
|
||||
|
||||
PropertyName* identifierReference(YieldHandling yieldHandling,
|
||||
bool yieldTokenizedAsName = false)
|
||||
{
|
||||
return labelOrIdentifierReference(yieldHandling, yieldTokenizedAsName);
|
||||
PropertyName* identifierReference(YieldHandling yieldHandling) {
|
||||
return labelOrIdentifierReference(yieldHandling);
|
||||
}
|
||||
|
||||
PropertyName* importedBinding() {
|
||||
|
@ -1393,7 +1408,6 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
|
|||
private:
|
||||
bool checkIncDecOperand(Node operand, uint32_t operandOffset);
|
||||
bool checkStrictAssignment(Node lhs);
|
||||
bool checkStrictBinding(PropertyName* name, TokenPos pos);
|
||||
|
||||
bool hasValidSimpleStrictParameterNames();
|
||||
|
||||
|
@ -1455,6 +1469,25 @@ class Parser final : public ParserBase, private JS::AutoGCRooter
|
|||
bool asmJS(Node list);
|
||||
};
|
||||
|
||||
template <typename ParseHandler>
|
||||
class MOZ_STACK_CLASS AutoAwaitIsKeyword
|
||||
{
|
||||
private:
|
||||
Parser<ParseHandler>* parser_;
|
||||
bool oldAwaitIsKeyword_;
|
||||
|
||||
public:
|
||||
AutoAwaitIsKeyword(Parser<ParseHandler>* parser, bool awaitIsKeyword) {
|
||||
parser_ = parser;
|
||||
oldAwaitIsKeyword_ = parser_->awaitIsKeyword_;
|
||||
parser_->setAwaitIsKeyword(awaitIsKeyword);
|
||||
}
|
||||
|
||||
~AutoAwaitIsKeyword() {
|
||||
parser_->setAwaitIsKeyword(oldAwaitIsKeyword_);
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace frontend */
|
||||
} /* namespace js */
|
||||
|
||||
|
|
|
@ -4,15 +4,16 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* A higher-order macro for enumerating keyword tokens. */
|
||||
/* A higher-order macro for enumerating reserved word tokens. */
|
||||
|
||||
#ifndef vm_Keywords_h
|
||||
#define vm_Keywords_h
|
||||
#ifndef vm_ReservedWords_h
|
||||
#define vm_ReservedWords_h
|
||||
|
||||
#define FOR_EACH_JAVASCRIPT_KEYWORD(macro) \
|
||||
#define FOR_EACH_JAVASCRIPT_RESERVED_WORD(macro) \
|
||||
macro(false, false_, TOK_FALSE) \
|
||||
macro(true, true_, TOK_TRUE) \
|
||||
macro(null, null, TOK_NULL) \
|
||||
\
|
||||
/* Keywords. */ \
|
||||
macro(break, break_, TOK_BREAK) \
|
||||
macro(case, case_, TOK_CASE) \
|
||||
|
@ -36,31 +37,45 @@
|
|||
macro(this, this_, TOK_THIS) \
|
||||
macro(throw, throw_, TOK_THROW) \
|
||||
macro(try, try_, TOK_TRY) \
|
||||
macro(typeof, typeof, TOK_TYPEOF) \
|
||||
macro(typeof, typeof_, TOK_TYPEOF) \
|
||||
macro(var, var, TOK_VAR) \
|
||||
macro(void, void_, TOK_VOID) \
|
||||
macro(while, while_, TOK_WHILE) \
|
||||
macro(with, with, TOK_WITH) \
|
||||
macro(import, import, TOK_IMPORT) \
|
||||
macro(export, export, TOK_EXPORT) \
|
||||
macro(export, export_, TOK_EXPORT) \
|
||||
macro(class, class_, TOK_CLASS) \
|
||||
macro(extends, extends, TOK_EXTENDS) \
|
||||
macro(super, super, TOK_SUPER) \
|
||||
/* Reserved keywords. */ \
|
||||
macro(enum, enum_, TOK_RESERVED) \
|
||||
/* Future reserved keywords, but only in strict mode. */ \
|
||||
macro(implements, implements, TOK_STRICT_RESERVED) \
|
||||
macro(interface, interface, TOK_STRICT_RESERVED) \
|
||||
macro(package, package, TOK_STRICT_RESERVED) \
|
||||
macro(private, private_, TOK_STRICT_RESERVED) \
|
||||
macro(protected, protected_, TOK_STRICT_RESERVED) \
|
||||
macro(public, public_, TOK_STRICT_RESERVED) \
|
||||
\
|
||||
/* Future reserved words. */ \
|
||||
macro(enum, enum_, TOK_ENUM) \
|
||||
\
|
||||
/* Future reserved words, but only in strict mode. */ \
|
||||
macro(implements, implements, TOK_IMPLEMENTS) \
|
||||
macro(interface, interface, TOK_INTERFACE) \
|
||||
macro(package, package, TOK_PACKAGE) \
|
||||
macro(private, private_, TOK_PRIVATE) \
|
||||
macro(protected, protected_, TOK_PROTECTED) \
|
||||
macro(public, public_, TOK_PUBLIC) \
|
||||
\
|
||||
/* Contextual keywords. */ \
|
||||
macro(as, as, TOK_AS) \
|
||||
macro(async, async, TOK_ASYNC) \
|
||||
macro(await, await, TOK_AWAIT) \
|
||||
macro(each, each, TOK_EACH) \
|
||||
macro(from, from, TOK_FROM) \
|
||||
macro(get, get, TOK_GET) \
|
||||
macro(let, let, TOK_LET) \
|
||||
macro(of, of, TOK_OF) \
|
||||
macro(set, set, TOK_SET) \
|
||||
macro(static, static_, TOK_STATIC) \
|
||||
macro(target, target, TOK_TARGET) \
|
||||
/* \
|
||||
* Yield is a token inside function*. Outside of a function*, it is a \
|
||||
* future reserved keyword in strict mode, but a keyword in JS1.7 even \
|
||||
* future reserved word in strict mode, but a keyword in JS1.7 even \
|
||||
* when strict. Punt logic to parser. \
|
||||
*/ \
|
||||
macro(yield, yield, TOK_YIELD)
|
||||
|
||||
#endif /* vm_Keywords_h */
|
||||
#endif /* vm_ReservedWords_h */
|
|
@ -81,9 +81,12 @@
|
|||
\
|
||||
macro(REGEXP, "regular expression literal") \
|
||||
macro(TRUE, "boolean literal 'true'") \
|
||||
range(RESERVED_WORD_LITERAL_FIRST, TRUE) \
|
||||
macro(FALSE, "boolean literal 'false'") \
|
||||
macro(NULL, "null literal") \
|
||||
range(RESERVED_WORD_LITERAL_LAST, NULL) \
|
||||
macro(THIS, "keyword 'this'") \
|
||||
range(KEYWORD_FIRST, THIS) \
|
||||
macro(FUNCTION, "keyword 'function'") \
|
||||
macro(IF, "keyword 'if'") \
|
||||
macro(ELSE, "keyword 'else'") \
|
||||
|
@ -106,16 +109,43 @@
|
|||
macro(FINALLY, "keyword 'finally'") \
|
||||
macro(THROW, "keyword 'throw'") \
|
||||
macro(DEBUGGER, "keyword 'debugger'") \
|
||||
macro(YIELD, "keyword 'yield'") \
|
||||
macro(AWAIT, "keyword 'await'") \
|
||||
macro(EXPORT, "keyword 'export'") \
|
||||
macro(IMPORT, "keyword 'import'") \
|
||||
macro(CLASS, "keyword 'class'") \
|
||||
macro(EXTENDS, "keyword 'extends'") \
|
||||
macro(SUPER, "keyword 'super'") \
|
||||
macro(RESERVED, "reserved keyword") \
|
||||
/* reserved keywords in strict mode */ \
|
||||
macro(STRICT_RESERVED, "reserved keyword") \
|
||||
range(KEYWORD_LAST, SUPER) \
|
||||
\
|
||||
/* contextual keywords */ \
|
||||
macro(AS, "'as'") \
|
||||
range(CONTEXTUAL_KEYWORD_FIRST, AS) \
|
||||
macro(ASYNC, "'async'") \
|
||||
macro(AWAIT, "'await'") \
|
||||
macro(EACH, "'each'") \
|
||||
macro(FROM, "'from'") \
|
||||
macro(GET, "'get'") \
|
||||
macro(LET, "'let'") \
|
||||
macro(OF, "'of'") \
|
||||
macro(SET, "'set'") \
|
||||
macro(STATIC, "'static'") \
|
||||
macro(TARGET, "'target'") \
|
||||
macro(YIELD, "'yield'") \
|
||||
range(CONTEXTUAL_KEYWORD_LAST, YIELD) \
|
||||
\
|
||||
/* future reserved words */ \
|
||||
macro(ENUM, "reserved word 'enum'") \
|
||||
range(FUTURE_RESERVED_KEYWORD_FIRST, ENUM) \
|
||||
range(FUTURE_RESERVED_KEYWORD_LAST, ENUM) \
|
||||
\
|
||||
/* reserved words in strict mode */ \
|
||||
macro(IMPLEMENTS, "reserved word 'implements'") \
|
||||
range(STRICT_RESERVED_KEYWORD_FIRST, IMPLEMENTS) \
|
||||
macro(INTERFACE, "reserved word 'interface'") \
|
||||
macro(PACKAGE, "reserved word 'package'") \
|
||||
macro(PRIVATE, "reserved word 'private'") \
|
||||
macro(PROTECTED, "reserved word 'protected'") \
|
||||
macro(PUBLIC, "reserved word 'public'") \
|
||||
range(STRICT_RESERVED_KEYWORD_LAST, PUBLIC) \
|
||||
\
|
||||
/* \
|
||||
* The following token types occupy contiguous ranges to enable easy \
|
||||
|
@ -149,7 +179,9 @@
|
|||
range(RELOP_LAST, GE) \
|
||||
\
|
||||
macro(INSTANCEOF, "keyword 'instanceof'") \
|
||||
range(KEYWORD_BINOP_FIRST, INSTANCEOF) \
|
||||
macro(IN, "keyword 'in'") \
|
||||
range(KEYWORD_BINOP_LAST, IN) \
|
||||
\
|
||||
/* Shift ops, per TokenKindIsShift. */ \
|
||||
macro(LSH, "'<<'") \
|
||||
|
@ -168,7 +200,9 @@
|
|||
\
|
||||
/* Unary operation tokens. */ \
|
||||
macro(TYPEOF, "keyword 'typeof'") \
|
||||
range(KEYWORD_UNOP_FIRST, TYPEOF) \
|
||||
macro(VOID, "keyword 'void'") \
|
||||
range(KEYWORD_UNOP_LAST, VOID) \
|
||||
macro(NOT, "'!'") \
|
||||
macro(BITNOT, "'~'") \
|
||||
\
|
||||
|
@ -239,6 +273,61 @@ TokenKindIsAssignment(TokenKind tt)
|
|||
return TOK_ASSIGNMENT_START <= tt && tt <= TOK_ASSIGNMENT_LAST;
|
||||
}
|
||||
|
||||
inline MOZ_MUST_USE bool
|
||||
TokenKindIsKeyword(TokenKind tt)
|
||||
{
|
||||
return (TOK_KEYWORD_FIRST <= tt && tt <= TOK_KEYWORD_LAST) ||
|
||||
(TOK_KEYWORD_BINOP_FIRST <= tt && tt <= TOK_KEYWORD_BINOP_LAST) ||
|
||||
(TOK_KEYWORD_UNOP_FIRST <= tt && tt <= TOK_KEYWORD_UNOP_LAST);
|
||||
}
|
||||
|
||||
inline MOZ_MUST_USE bool
|
||||
TokenKindIsContextualKeyword(TokenKind tt)
|
||||
{
|
||||
return TOK_CONTEXTUAL_KEYWORD_FIRST <= tt && tt <= TOK_CONTEXTUAL_KEYWORD_LAST;
|
||||
}
|
||||
|
||||
inline MOZ_MUST_USE bool
|
||||
TokenKindIsFutureReservedWord(TokenKind tt)
|
||||
{
|
||||
return TOK_FUTURE_RESERVED_KEYWORD_FIRST <= tt && tt <= TOK_FUTURE_RESERVED_KEYWORD_LAST;
|
||||
}
|
||||
|
||||
inline MOZ_MUST_USE bool
|
||||
TokenKindIsStrictReservedWord(TokenKind tt)
|
||||
{
|
||||
return TOK_STRICT_RESERVED_KEYWORD_FIRST <= tt && tt <= TOK_STRICT_RESERVED_KEYWORD_LAST;
|
||||
}
|
||||
|
||||
inline MOZ_MUST_USE bool
|
||||
TokenKindIsReservedWordLiteral(TokenKind tt)
|
||||
{
|
||||
return TOK_RESERVED_WORD_LITERAL_FIRST <= tt && tt <= TOK_RESERVED_WORD_LITERAL_LAST;
|
||||
}
|
||||
|
||||
inline MOZ_MUST_USE bool
|
||||
TokenKindIsReservedWord(TokenKind tt)
|
||||
{
|
||||
return TokenKindIsKeyword(tt) ||
|
||||
TokenKindIsFutureReservedWord(tt) ||
|
||||
TokenKindIsReservedWordLiteral(tt);
|
||||
}
|
||||
|
||||
inline MOZ_MUST_USE bool
|
||||
TokenKindIsPossibleIdentifier(TokenKind tt)
|
||||
{
|
||||
return tt == TOK_NAME ||
|
||||
TokenKindIsContextualKeyword(tt) ||
|
||||
TokenKindIsStrictReservedWord(tt);
|
||||
}
|
||||
|
||||
inline MOZ_MUST_USE bool
|
||||
TokenKindIsPossibleIdentifierName(TokenKind tt)
|
||||
{
|
||||
return TokenKindIsPossibleIdentifier(tt) ||
|
||||
TokenKindIsReservedWord(tt);
|
||||
}
|
||||
|
||||
} // namespace frontend
|
||||
} // namespace js
|
||||
|
||||
|
|
|
@ -24,10 +24,10 @@
|
|||
#include "jsnum.h"
|
||||
|
||||
#include "frontend/BytecodeCompiler.h"
|
||||
#include "frontend/ReservedWords.h"
|
||||
#include "js/CharacterEncoding.h"
|
||||
#include "js/UniquePtr.h"
|
||||
#include "vm/HelperThreads.h"
|
||||
#include "vm/Keywords.h"
|
||||
#include "vm/StringBuffer.h"
|
||||
#include "vm/Unicode.h"
|
||||
|
||||
|
@ -40,65 +40,65 @@ using mozilla::PodAssign;
|
|||
using mozilla::PodCopy;
|
||||
using mozilla::PodZero;
|
||||
|
||||
struct KeywordInfo {
|
||||
const char* chars; // C string with keyword text
|
||||
struct ReservedWordInfo {
|
||||
const char* chars; // C string with reserved word text
|
||||
TokenKind tokentype;
|
||||
};
|
||||
|
||||
static const KeywordInfo keywords[] = {
|
||||
#define KEYWORD_INFO(keyword, name, type) \
|
||||
{js_##keyword##_str, type},
|
||||
FOR_EACH_JAVASCRIPT_KEYWORD(KEYWORD_INFO)
|
||||
#undef KEYWORD_INFO
|
||||
static const ReservedWordInfo reservedWords[] = {
|
||||
#define RESERVED_WORD_INFO(word, name, type) \
|
||||
{js_##word##_str, type},
|
||||
FOR_EACH_JAVASCRIPT_RESERVED_WORD(RESERVED_WORD_INFO)
|
||||
#undef RESERVED_WORD_INFO
|
||||
};
|
||||
|
||||
// Returns a KeywordInfo for the specified characters, or nullptr if the string
|
||||
// is not a keyword.
|
||||
// Returns a ReservedWordInfo for the specified characters, or nullptr if the
|
||||
// string is not a reserved word.
|
||||
template <typename CharT>
|
||||
static const KeywordInfo*
|
||||
FindKeyword(const CharT* s, size_t length)
|
||||
static const ReservedWordInfo*
|
||||
FindReservedWord(const CharT* s, size_t length)
|
||||
{
|
||||
MOZ_ASSERT(length != 0);
|
||||
|
||||
size_t i;
|
||||
const KeywordInfo* kw;
|
||||
const ReservedWordInfo* rw;
|
||||
const char* chars;
|
||||
|
||||
#define JSKW_LENGTH() length
|
||||
#define JSKW_AT(column) s[column]
|
||||
#define JSKW_GOT_MATCH(index) i = (index); goto got_match;
|
||||
#define JSKW_TEST_GUESS(index) i = (index); goto test_guess;
|
||||
#define JSKW_NO_MATCH() goto no_match;
|
||||
#include "jsautokw.h"
|
||||
#undef JSKW_NO_MATCH
|
||||
#undef JSKW_TEST_GUESS
|
||||
#undef JSKW_GOT_MATCH
|
||||
#undef JSKW_AT
|
||||
#undef JSKW_LENGTH
|
||||
#define JSRW_LENGTH() length
|
||||
#define JSRW_AT(column) s[column]
|
||||
#define JSRW_GOT_MATCH(index) i = (index); goto got_match;
|
||||
#define JSRW_TEST_GUESS(index) i = (index); goto test_guess;
|
||||
#define JSRW_NO_MATCH() goto no_match;
|
||||
#include "frontend/ReservedWordsGenerated.h"
|
||||
#undef JSRW_NO_MATCH
|
||||
#undef JSRW_TEST_GUESS
|
||||
#undef JSRW_GOT_MATCH
|
||||
#undef JSRW_AT
|
||||
#undef JSRW_LENGTH
|
||||
|
||||
got_match:
|
||||
return &keywords[i];
|
||||
return &reservedWords[i];
|
||||
|
||||
test_guess:
|
||||
kw = &keywords[i];
|
||||
chars = kw->chars;
|
||||
rw = &reservedWords[i];
|
||||
chars = rw->chars;
|
||||
do {
|
||||
if (*s++ != (unsigned char)(*chars++))
|
||||
goto no_match;
|
||||
} while (--length != 0);
|
||||
return kw;
|
||||
return rw;
|
||||
|
||||
no_match:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static const KeywordInfo*
|
||||
FindKeyword(JSLinearString* str)
|
||||
static const ReservedWordInfo*
|
||||
FindReservedWord(JSLinearString* str)
|
||||
{
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
return str->hasLatin1Chars()
|
||||
? FindKeyword(str->latin1Chars(nogc), str->length())
|
||||
: FindKeyword(str->twoByteChars(nogc), str->length());
|
||||
? FindReservedWord(str->latin1Chars(nogc), str->length())
|
||||
: FindReservedWord(str->twoByteChars(nogc), str->length());
|
||||
}
|
||||
|
||||
template <typename CharT>
|
||||
|
@ -188,7 +188,68 @@ frontend::IsIdentifier(const char16_t* chars, size_t length)
|
|||
bool
|
||||
frontend::IsKeyword(JSLinearString* str)
|
||||
{
|
||||
return FindKeyword(str) != nullptr;
|
||||
if (const ReservedWordInfo* rw = FindReservedWord(str))
|
||||
return TokenKindIsKeyword(rw->tokentype);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
frontend::IsFutureReservedWord(JSLinearString* str)
|
||||
{
|
||||
if (const ReservedWordInfo* rw = FindReservedWord(str))
|
||||
return TokenKindIsFutureReservedWord(rw->tokentype);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
frontend::IsStrictReservedWord(JSLinearString* str)
|
||||
{
|
||||
if (const ReservedWordInfo* rw = FindReservedWord(str))
|
||||
return TokenKindIsStrictReservedWord(rw->tokentype);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
frontend::IsReservedWordLiteral(JSLinearString* str)
|
||||
{
|
||||
if (const ReservedWordInfo* rw = FindReservedWord(str))
|
||||
return TokenKindIsReservedWordLiteral(rw->tokentype);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const char*
|
||||
frontend::ReservedWordToCharZ(PropertyName* str)
|
||||
{
|
||||
const ReservedWordInfo* rw = FindReservedWord(str);
|
||||
if (rw == nullptr)
|
||||
return nullptr;
|
||||
|
||||
switch (rw->tokentype) {
|
||||
#define EMIT_CASE(word, name, type) case type: return js_##word##_str;
|
||||
FOR_EACH_JAVASCRIPT_RESERVED_WORD(EMIT_CASE)
|
||||
#undef EMIT_CASE
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Not a reserved word PropertyName.");
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PropertyName*
|
||||
TokenStream::reservedWordToPropertyName(TokenKind tt) const
|
||||
{
|
||||
MOZ_ASSERT(tt != TOK_NAME);
|
||||
switch (tt) {
|
||||
#define EMIT_CASE(word, name, type) case type: return cx->names().name;
|
||||
FOR_EACH_JAVASCRIPT_RESERVED_WORD(EMIT_CASE)
|
||||
#undef EMIT_CASE
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Not a reserved word TokenKind.");
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TokenStream::SourceCoords::SourceCoords(ExclusiveContext* cx, uint32_t ln)
|
||||
|
@ -1169,38 +1230,6 @@ TokenStream::putIdentInTokenbuf(const char16_t* identStart)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TokenStream::checkForKeyword(const KeywordInfo* kw, TokenKind* ttp)
|
||||
{
|
||||
if (!awaitIsKeyword && kw->tokentype == TOK_AWAIT) {
|
||||
if (ttp)
|
||||
*ttp = TOK_NAME;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (kw->tokentype == TOK_RESERVED) {
|
||||
error(JSMSG_RESERVED_ID, kw->chars);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (kw->tokentype == TOK_STRICT_RESERVED)
|
||||
return reportStrictModeError(JSMSG_RESERVED_ID, kw->chars);
|
||||
|
||||
// Working keyword.
|
||||
*ttp = kw->tokentype;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TokenStream::checkForKeyword(JSAtom* atom, TokenKind* ttp)
|
||||
{
|
||||
const KeywordInfo* kw = FindKeyword(atom);
|
||||
if (!kw)
|
||||
return true;
|
||||
|
||||
return checkForKeyword(kw, ttp);
|
||||
}
|
||||
|
||||
enum FirstCharKind {
|
||||
// A char16_t has the 'OneChar' kind if it, by itself, constitutes a valid
|
||||
// token that cannot also be a prefix of a longer token. E.g. ';' has the
|
||||
|
@ -1424,36 +1453,18 @@ TokenStream::getTokenInternal(TokenKind* ttp, Modifier modifier)
|
|||
length = userbuf.addressOfNextRawChar() - identStart;
|
||||
}
|
||||
|
||||
// Represent keywords as keyword tokens unless told otherwise.
|
||||
if (modifier != KeywordIsName) {
|
||||
if (const KeywordInfo* kw = FindKeyword(chars, length)) {
|
||||
// That said, keywords can't contain escapes. (Contexts where
|
||||
// keywords are treated as names, that also sometimes treat
|
||||
// keywords as keywords, must manually check this requirement.)
|
||||
// There are two exceptions
|
||||
// 1) StrictReservedWords: These keywords need to be treated as
|
||||
// names in non-strict mode.
|
||||
// 2) yield is also treated as a name if it contains an escape
|
||||
// sequence. The parser must handle this case separately.
|
||||
if (hadUnicodeEscape && !(
|
||||
(kw->tokentype == TOK_STRICT_RESERVED && !strictMode()) ||
|
||||
kw->tokentype == TOK_YIELD))
|
||||
{
|
||||
reportError(JSMSG_ESCAPED_KEYWORD);
|
||||
goto error;
|
||||
}
|
||||
|
||||
tp->type = TOK_NAME;
|
||||
if (!checkForKeyword(kw, &tp->type))
|
||||
goto error;
|
||||
if (tp->type != TOK_NAME && !hadUnicodeEscape)
|
||||
goto out;
|
||||
// Represent reserved words as reserved word tokens.
|
||||
if (!hadUnicodeEscape) {
|
||||
if (const ReservedWordInfo* rw = FindReservedWord(chars, length)) {
|
||||
tp->type = rw->tokentype;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
JSAtom* atom = AtomizeChars(cx, chars, length);
|
||||
if (!atom)
|
||||
if (!atom) {
|
||||
goto error;
|
||||
}
|
||||
tp->type = TOK_NAME;
|
||||
tp->setName(atom->asPropertyName());
|
||||
goto out;
|
||||
|
|
|
@ -26,14 +26,13 @@
|
|||
#include "js/UniquePtr.h"
|
||||
#include "js/Vector.h"
|
||||
#include "vm/RegExpObject.h"
|
||||
#include "vm/String.h"
|
||||
|
||||
struct KeywordInfo;
|
||||
|
||||
namespace js {
|
||||
namespace frontend {
|
||||
|
||||
class AutoAwaitIsKeyword;
|
||||
|
||||
struct TokenPos {
|
||||
uint32_t begin; // Offset of the token's first char.
|
||||
uint32_t end; // Offset of 1 past the token's last char.
|
||||
|
@ -120,9 +119,6 @@ struct Token
|
|||
// TOK_DIV.
|
||||
Operand,
|
||||
|
||||
// Treat keywords as names by returning TOK_NAME.
|
||||
KeywordIsName,
|
||||
|
||||
// Treat subsequent characters as the tail of a template literal, after
|
||||
// a template substitution, beginning with a "}", continuing with zero
|
||||
// or more template literal characters, and ending with either "${" or
|
||||
|
@ -164,10 +160,6 @@ struct Token
|
|||
// If a semicolon is inserted automatically, the next token is already
|
||||
// gotten with None, but we expect Operand.
|
||||
OperandIsNone,
|
||||
|
||||
// If name of method definition is `get` or `set`, the next token is
|
||||
// already gotten with KeywordIsName, but we expect None.
|
||||
NoneIsKeywordIsName,
|
||||
};
|
||||
friend class TokenStream;
|
||||
|
||||
|
@ -224,11 +216,6 @@ struct Token
|
|||
return u.name->JSAtom::asPropertyName(); // poor-man's type verification
|
||||
}
|
||||
|
||||
bool nameContainsEscape() const {
|
||||
PropertyName* n = name();
|
||||
return pos.begin + n->length() != pos.end;
|
||||
}
|
||||
|
||||
JSAtom* atom() const {
|
||||
MOZ_ASSERT(type == TOK_STRING ||
|
||||
type == TOK_TEMPLATE_HEAD ||
|
||||
|
@ -254,10 +241,22 @@ struct Token
|
|||
};
|
||||
|
||||
class CompileError : public JSErrorReport {
|
||||
public:
|
||||
public:
|
||||
void throwError(JSContext* cx);
|
||||
};
|
||||
|
||||
extern const char*
|
||||
ReservedWordToCharZ(PropertyName* str);
|
||||
|
||||
extern MOZ_MUST_USE bool
|
||||
IsFutureReservedWord(JSLinearString* str);
|
||||
|
||||
extern MOZ_MUST_USE bool
|
||||
IsReservedWordLiteral(JSLinearString* str);
|
||||
|
||||
extern MOZ_MUST_USE bool
|
||||
IsStrictReservedWord(JSLinearString* str);
|
||||
|
||||
// Ideally, tokenizing would be entirely independent of context. But the
|
||||
// strict mode flag, which is in SharedContext, affects tokenizing, and
|
||||
// TokenStream needs to see it.
|
||||
|
@ -344,25 +343,26 @@ class MOZ_STACK_CLASS TokenStream
|
|||
JSVersion versionNumber() const { return VersionNumber(options().version); }
|
||||
JSVersion versionWithFlags() const { return options().version; }
|
||||
|
||||
private:
|
||||
PropertyName* reservedWordToPropertyName(TokenKind tt) const;
|
||||
|
||||
public:
|
||||
PropertyName* currentName() const {
|
||||
if (isCurrentTokenType(TOK_YIELD))
|
||||
return cx->names().yield;
|
||||
MOZ_ASSERT(isCurrentTokenType(TOK_NAME));
|
||||
return currentToken().name();
|
||||
if (isCurrentTokenType(TOK_NAME)) {
|
||||
return currentToken().name();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(TokenKindIsPossibleIdentifierName(currentToken().type));
|
||||
return reservedWordToPropertyName(currentToken().type);
|
||||
}
|
||||
|
||||
PropertyName* nextName() const {
|
||||
if (nextToken().type == TOK_YIELD)
|
||||
return cx->names().yield;
|
||||
MOZ_ASSERT(nextToken().type == TOK_NAME);
|
||||
return nextToken().name();
|
||||
}
|
||||
if (nextToken().type != TOK_NAME) {
|
||||
return nextToken().name();
|
||||
}
|
||||
|
||||
bool nextNameContainsEscape() const {
|
||||
if (nextToken().type == TOK_YIELD)
|
||||
return false;
|
||||
MOZ_ASSERT(nextToken().type == TOK_NAME);
|
||||
return nextToken().nameContainsEscape();
|
||||
MOZ_ASSERT(TokenKindIsPossibleIdentifierName(nextToken().type));
|
||||
return reservedWordToPropertyName(nextToken().type);
|
||||
}
|
||||
|
||||
bool isCurrentTokenAssignment() const {
|
||||
|
@ -498,9 +498,6 @@ class MOZ_STACK_CLASS TokenStream
|
|||
{}
|
||||
};
|
||||
|
||||
bool awaitIsKeyword = false;
|
||||
friend class AutoAwaitIsKeyword;
|
||||
|
||||
uint32_t invalidTemplateEscapeOffset = 0;
|
||||
InvalidEscapeType invalidTemplateEscapeType = InvalidEscapeType::None;
|
||||
|
||||
|
@ -508,14 +505,12 @@ class MOZ_STACK_CLASS TokenStream
|
|||
typedef Token::Modifier Modifier;
|
||||
static constexpr Modifier None = Token::None;
|
||||
static constexpr Modifier Operand = Token::Operand;
|
||||
static constexpr Modifier KeywordIsName = Token::KeywordIsName;
|
||||
static constexpr Modifier TemplateTail = Token::TemplateTail;
|
||||
|
||||
typedef Token::ModifierException ModifierException;
|
||||
static constexpr ModifierException NoException = Token::NoException;
|
||||
static constexpr ModifierException NoneIsOperand = Token::NoneIsOperand;
|
||||
static constexpr ModifierException OperandIsNone = Token::OperandIsNone;
|
||||
static constexpr ModifierException NoneIsKeywordIsName = Token::NoneIsKeywordIsName;
|
||||
|
||||
void addModifierException(ModifierException modifierException) {
|
||||
#ifdef DEBUG
|
||||
|
@ -544,10 +539,6 @@ class MOZ_STACK_CLASS TokenStream
|
|||
MOZ_ASSERT(next.type != TOK_DIV && next.type != TOK_REGEXP,
|
||||
"next token requires contextual specifier to be parsed unambiguously");
|
||||
break;
|
||||
case NoneIsKeywordIsName:
|
||||
MOZ_ASSERT(next.modifier == KeywordIsName);
|
||||
MOZ_ASSERT(next.type != TOK_NAME);
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("unexpected modifier exception");
|
||||
}
|
||||
|
@ -574,12 +565,6 @@ class MOZ_STACK_CLASS TokenStream
|
|||
return;
|
||||
}
|
||||
|
||||
if (lookaheadToken.modifierException == NoneIsKeywordIsName) {
|
||||
// getToken() permissibly following getToken(KeywordIsName).
|
||||
if (modifier == None && lookaheadToken.modifier == KeywordIsName)
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT_UNREACHABLE("this token was previously looked up with a "
|
||||
"different modifier, potentially making "
|
||||
"tokenization non-deterministic");
|
||||
|
@ -713,36 +698,6 @@ class MOZ_STACK_CLASS TokenStream
|
|||
MOZ_ALWAYS_TRUE(matched);
|
||||
}
|
||||
|
||||
// Like matchToken(..., TOK_NAME) but further matching the name token only
|
||||
// if it has the given characters, without containing escape sequences.
|
||||
// If the name token has the given characters yet *does* contain an escape,
|
||||
// a syntax error will be reported.
|
||||
//
|
||||
// This latter behavior makes this method unsuitable for use in any context
|
||||
// where ASI might occur. In such places, an escaped "contextual keyword"
|
||||
// on a new line is the start of an ExpressionStatement, not a continuation
|
||||
// of a StatementListItem (or ImportDeclaration or ExportDeclaration, in
|
||||
// modules).
|
||||
MOZ_MUST_USE bool matchContextualKeyword(bool* matchedp, Handle<PropertyName*> keyword,
|
||||
Modifier modifier = None)
|
||||
{
|
||||
TokenKind token;
|
||||
if (!getToken(&token, modifier))
|
||||
return false;
|
||||
if (token == TOK_NAME && currentToken().name() == keyword) {
|
||||
if (currentToken().nameContainsEscape()) {
|
||||
reportError(JSMSG_ESCAPED_KEYWORD);
|
||||
return false;
|
||||
}
|
||||
|
||||
*matchedp = true;
|
||||
} else {
|
||||
*matchedp = false;
|
||||
ungetToken();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool nextTokenEndsExpr(bool* endsExpr) {
|
||||
TokenKind tt;
|
||||
if (!peekToken(&tt))
|
||||
|
@ -808,19 +763,6 @@ class MOZ_STACK_CLASS TokenStream
|
|||
return sourceMapURL_.get();
|
||||
}
|
||||
|
||||
// If |atom| is not a keyword in this version, return true with *ttp
|
||||
// unchanged.
|
||||
//
|
||||
// If it is a reserved word in this version and strictness mode, and thus
|
||||
// can't be present in correct code, report a SyntaxError and return false.
|
||||
//
|
||||
// If it is a keyword, like "if", return true with the keyword's TokenKind
|
||||
// in *ttp.
|
||||
MOZ_MUST_USE bool checkForKeyword(JSAtom* atom, TokenKind* ttp);
|
||||
|
||||
// Same semantics as above, but for the provided keyword.
|
||||
MOZ_MUST_USE bool checkForKeyword(const KeywordInfo* kw, TokenKind* ttp);
|
||||
|
||||
// This class maps a userbuf offset (which is 0-indexed) to a line number
|
||||
// (which is 1-indexed) and a column index (which is 0-indexed).
|
||||
class SourceCoords
|
||||
|
@ -1102,25 +1044,6 @@ class MOZ_STACK_CLASS TokenStream
|
|||
StrictModeGetter* strictModeGetter; // used to test for strict mode
|
||||
};
|
||||
|
||||
class MOZ_STACK_CLASS AutoAwaitIsKeyword
|
||||
{
|
||||
private:
|
||||
TokenStream* ts_;
|
||||
bool oldAwaitIsKeyword_;
|
||||
|
||||
public:
|
||||
AutoAwaitIsKeyword(TokenStream* ts, bool awaitIsKeyword) {
|
||||
ts_ = ts;
|
||||
oldAwaitIsKeyword_ = ts_->awaitIsKeyword;
|
||||
ts_->awaitIsKeyword = awaitIsKeyword;
|
||||
}
|
||||
|
||||
~AutoAwaitIsKeyword() {
|
||||
ts_->awaitIsKeyword = oldAwaitIsKeyword_;
|
||||
ts_ = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
extern const char*
|
||||
TokenKindToDesc(TokenKind tt);
|
||||
|
||||
|
|
|
@ -403,9 +403,7 @@ assertThrowsInstanceOf(function() {
|
|||
parseAsModule("export {,} from 'a'");
|
||||
}, SyntaxError);
|
||||
|
||||
assertThrowsInstanceOf(function() {
|
||||
parseAsModule("export { true as a } from 'b'");
|
||||
}, SyntaxError);
|
||||
parseAsModule("export { true as a } from 'b'");
|
||||
|
||||
assertThrowsInstanceOf(function () {
|
||||
parseAsModule("export { a } from 'b' f();");
|
||||
|
|
|
@ -265,6 +265,7 @@ MSG_DEF(JSMSG_IMPORT_DECL_AT_TOP_LEVEL, 0, JSEXN_SYNTAXERR, "import declarations
|
|||
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")
|
||||
MSG_DEF(JSMSG_IN_AFTER_LEXICAL_FOR_DECL,0,JSEXN_SYNTAXERR, "a lexical declaration in the head of a for-in loop can't have an initializer")
|
||||
MSG_DEF(JSMSG_INVALID_FOR_IN_DECL_WITH_INIT,0,JSEXN_SYNTAXERR,"for-in loop head declarations may not have initializers")
|
||||
MSG_DEF(JSMSG_INVALID_ID, 1, JSEXN_SYNTAXERR, "{0} is an invalid identifier")
|
||||
MSG_DEF(JSMSG_LABEL_NOT_FOUND, 0, JSEXN_SYNTAXERR, "label not found")
|
||||
MSG_DEF(JSMSG_LET_COMP_BINDING, 0, JSEXN_SYNTAXERR, "'let' is not a valid name for a comprehension variable")
|
||||
MSG_DEF(JSMSG_LEXICAL_DECL_NOT_IN_BLOCK, 1, JSEXN_SYNTAXERR, "{0} declaration not directly within block")
|
||||
|
|
|
@ -54,41 +54,9 @@ FOR_EACH_COMMON_PROPERTYNAME(CONST_CHAR_STR)
|
|||
#undef CONST_CHAR_STR
|
||||
|
||||
/* Constant strings that are not atomized. */
|
||||
const char js_break_str[] = "break";
|
||||
const char js_case_str[] = "case";
|
||||
const char js_catch_str[] = "catch";
|
||||
const char js_class_str[] = "class";
|
||||
const char js_const_str[] = "const";
|
||||
const char js_continue_str[] = "continue";
|
||||
const char js_debugger_str[] = "debugger";
|
||||
const char js_default_str[] = "default";
|
||||
const char js_do_str[] = "do";
|
||||
const char js_else_str[] = "else";
|
||||
const char js_enum_str[] = "enum";
|
||||
const char js_export_str[] = "export";
|
||||
const char js_extends_str[] = "extends";
|
||||
const char js_finally_str[] = "finally";
|
||||
const char js_for_str[] = "for";
|
||||
const char js_getter_str[] = "getter";
|
||||
const char js_if_str[] = "if";
|
||||
const char js_implements_str[] = "implements";
|
||||
const char js_import_str[] = "import";
|
||||
const char js_in_str[] = "in";
|
||||
const char js_instanceof_str[] = "instanceof";
|
||||
const char js_interface_str[] = "interface";
|
||||
const char js_package_str[] = "package";
|
||||
const char js_private_str[] = "private";
|
||||
const char js_protected_str[] = "protected";
|
||||
const char js_public_str[] = "public";
|
||||
const char js_send_str[] = "send";
|
||||
const char js_setter_str[] = "setter";
|
||||
const char js_switch_str[] = "switch";
|
||||
const char js_this_str[] = "this";
|
||||
const char js_try_str[] = "try";
|
||||
const char js_typeof_str[] = "typeof";
|
||||
const char js_void_str[] = "void";
|
||||
const char js_while_str[] = "while";
|
||||
const char js_with_str[] = "with";
|
||||
|
||||
// Use a low initial capacity for atom hash tables to avoid penalizing runtimes
|
||||
// which create a small number of atoms.
|
||||
|
|
|
@ -142,44 +142,9 @@ FOR_EACH_COMMON_PROPERTYNAME(DECLARE_CONST_CHAR_STR)
|
|||
#undef DECLARE_CONST_CHAR_STR
|
||||
|
||||
/* Constant strings that are not atomized. */
|
||||
extern const char js_break_str[];
|
||||
extern const char js_case_str[];
|
||||
extern const char js_catch_str[];
|
||||
extern const char js_class_str[];
|
||||
extern const char js_close_str[];
|
||||
extern const char js_const_str[];
|
||||
extern const char js_continue_str[];
|
||||
extern const char js_debugger_str[];
|
||||
extern const char js_default_str[];
|
||||
extern const char js_do_str[];
|
||||
extern const char js_else_str[];
|
||||
extern const char js_enum_str[];
|
||||
extern const char js_export_str[];
|
||||
extern const char js_extends_str[];
|
||||
extern const char js_finally_str[];
|
||||
extern const char js_for_str[];
|
||||
extern const char js_getter_str[];
|
||||
extern const char js_if_str[];
|
||||
extern const char js_implements_str[];
|
||||
extern const char js_import_str[];
|
||||
extern const char js_in_str[];
|
||||
extern const char js_instanceof_str[];
|
||||
extern const char js_interface_str[];
|
||||
extern const char js_package_str[];
|
||||
extern const char js_private_str[];
|
||||
extern const char js_protected_str[];
|
||||
extern const char js_public_str[];
|
||||
extern const char js_send_str[];
|
||||
extern const char js_setter_str[];
|
||||
extern const char js_static_str[];
|
||||
extern const char js_super_str[];
|
||||
extern const char js_switch_str[];
|
||||
extern const char js_this_str[];
|
||||
extern const char js_try_str[];
|
||||
extern const char js_typeof_str[];
|
||||
extern const char js_void_str[];
|
||||
extern const char js_while_str[];
|
||||
extern const char js_with_str[];
|
||||
|
||||
namespace js {
|
||||
|
||||
|
|
|
@ -619,11 +619,11 @@ else:
|
|||
'perf/pm_stub.cpp'
|
||||
]
|
||||
|
||||
GENERATED_FILES += ['jsautokw.h']
|
||||
jsautokw = GENERATED_FILES['jsautokw.h']
|
||||
jsautokw.script = 'jsautokw.py'
|
||||
jsautokw.inputs += [
|
||||
'vm/Keywords.h'
|
||||
GENERATED_FILES += ['frontend/ReservedWordsGenerated.h']
|
||||
ReservedWordsGenerated = GENERATED_FILES['frontend/ReservedWordsGenerated.h']
|
||||
ReservedWordsGenerated.script = 'frontend/GenerateReservedWords.py'
|
||||
ReservedWordsGenerated.inputs += [
|
||||
'frontend/ReservedWords.h'
|
||||
]
|
||||
|
||||
# JavaScript must be built shared, even for static builds, as it is used by
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
macro(Bool32x4, Bool32x4, "Bool32x4") \
|
||||
macro(Bool64x2, Bool64x2, "Bool64x2") \
|
||||
macro(boundWithSpace, boundWithSpace, "bound ") \
|
||||
macro(break, break_, "break") \
|
||||
macro(breakdown, breakdown, "breakdown") \
|
||||
macro(buffer, buffer, "buffer") \
|
||||
macro(builder, builder, "builder") \
|
||||
|
@ -52,8 +53,10 @@
|
|||
macro(callee, callee, "callee") \
|
||||
macro(caller, caller, "caller") \
|
||||
macro(callFunction, callFunction, "callFunction") \
|
||||
macro(case, case_, "case") \
|
||||
macro(caseFirst, caseFirst, "caseFirst") \
|
||||
macro(class_, class_, "class") \
|
||||
macro(catch, catch_, "catch") \
|
||||
macro(class, class_, "class") \
|
||||
macro(close, close, "close") \
|
||||
macro(Collator, Collator, "Collator") \
|
||||
macro(CollatorCompareGet, CollatorCompareGet, "Intl_Collator_compare_get") \
|
||||
|
@ -62,9 +65,11 @@
|
|||
macro(comma, comma, ",") \
|
||||
macro(compare, compare, "compare") \
|
||||
macro(configurable, configurable, "configurable") \
|
||||
macro(const, const_, "const") \
|
||||
macro(construct, construct, "construct") \
|
||||
macro(constructContentFunction, constructContentFunction, "constructContentFunction") \
|
||||
macro(constructor, constructor, "constructor") \
|
||||
macro(continue, continue_, "continue") \
|
||||
macro(ConvertAndCopyTo, ConvertAndCopyTo, "ConvertAndCopyTo") \
|
||||
macro(copyWithin, copyWithin, "copyWithin") \
|
||||
macro(count, count, "count") \
|
||||
|
@ -76,28 +81,32 @@
|
|||
macro(DateTimeFormatFormatToParts, DateTimeFormatFormatToParts, "Intl_DateTimeFormat_formatToParts") \
|
||||
macro(day, day, "day") \
|
||||
macro(dayPeriod, dayPeriod, "dayPeriod") \
|
||||
macro(debugger, debugger, "debugger") \
|
||||
macro(decodeURI, decodeURI, "decodeURI") \
|
||||
macro(decodeURIComponent, decodeURIComponent, "decodeURIComponent") \
|
||||
macro(DefaultBaseClassConstructor, DefaultBaseClassConstructor, "DefaultBaseClassConstructor") \
|
||||
macro(DefaultDerivedClassConstructor, DefaultDerivedClassConstructor, "DefaultDerivedClassConstructor") \
|
||||
macro(default_, default_, "default") \
|
||||
macro(default, default_, "default") \
|
||||
macro(defineGetter, defineGetter, "__defineGetter__") \
|
||||
macro(defineProperty, defineProperty, "defineProperty") \
|
||||
macro(defineSetter, defineSetter, "__defineSetter__") \
|
||||
macro(delete, delete_, "delete") \
|
||||
macro(deleteProperty, deleteProperty, "deleteProperty") \
|
||||
macro(displayURL, displayURL, "displayURL") \
|
||||
macro(do, do_, "do") \
|
||||
macro(done, done, "done") \
|
||||
macro(dotGenerator, dotGenerator, ".generator") \
|
||||
macro(dotThis, dotThis, ".this") \
|
||||
macro(each, each, "each") \
|
||||
macro(elementType, elementType, "elementType") \
|
||||
macro(else, else_, "else") \
|
||||
macro(empty, empty, "") \
|
||||
macro(emptyRegExp, emptyRegExp, "(?:)") \
|
||||
macro(encodeURI, encodeURI, "encodeURI") \
|
||||
macro(encodeURIComponent, encodeURIComponent, "encodeURIComponent") \
|
||||
macro(endTimestamp, endTimestamp, "endTimestamp") \
|
||||
macro(entries, entries, "entries") \
|
||||
macro(enum, enum_, "enum") \
|
||||
macro(enumerable, enumerable, "enumerable") \
|
||||
macro(enumerate, enumerate, "enumerate") \
|
||||
macro(era, era, "era") \
|
||||
|
@ -105,11 +114,14 @@
|
|||
macro(escape, escape, "escape") \
|
||||
macro(eval, eval, "eval") \
|
||||
macro(exec, exec, "exec") \
|
||||
macro(export, export_, "export") \
|
||||
macro(extends, extends, "extends") \
|
||||
macro(false, false_, "false") \
|
||||
macro(fieldOffsets, fieldOffsets, "fieldOffsets") \
|
||||
macro(fieldTypes, fieldTypes, "fieldTypes") \
|
||||
macro(fileName, fileName, "fileName") \
|
||||
macro(fill, fill, "fill") \
|
||||
macro(finally, finally_, "finally") \
|
||||
macro(find, find, "find") \
|
||||
macro(findIndex, findIndex, "findIndex") \
|
||||
macro(firstDayOfWeek, firstDayOfWeek, "firstDayOfWeek") \
|
||||
|
@ -121,6 +133,7 @@
|
|||
macro(Float32x4, Float32x4, "Float32x4") \
|
||||
macro(float64, float64, "float64") \
|
||||
macro(Float64x2, Float64x2, "Float64x2") \
|
||||
macro(for, for_, "for") \
|
||||
macro(forceInterpreter, forceInterpreter, "forceInterpreter") \
|
||||
macro(forEach, forEach, "forEach") \
|
||||
macro(format, format, "format") \
|
||||
|
@ -146,8 +159,12 @@
|
|||
macro(hasOwn, hasOwn, "hasOwn") \
|
||||
macro(hasOwnProperty, hasOwnProperty, "hasOwnProperty") \
|
||||
macro(hour, hour, "hour") \
|
||||
macro(if, if_, "if") \
|
||||
macro(ignoreCase, ignoreCase, "ignoreCase") \
|
||||
macro(ignorePunctuation, ignorePunctuation, "ignorePunctuation") \
|
||||
macro(implements, implements, "implements") \
|
||||
macro(import, import, "import") \
|
||||
macro(in, in, "in") \
|
||||
macro(includes, includes, "includes") \
|
||||
macro(incumbentGlobal, incumbentGlobal, "incumbentGlobal") \
|
||||
macro(index, index, "index") \
|
||||
|
@ -158,12 +175,14 @@
|
|||
macro(innermost, innermost, "innermost") \
|
||||
macro(inNursery, inNursery, "inNursery") \
|
||||
macro(input, input, "input") \
|
||||
macro(instanceof, instanceof, "instanceof") \
|
||||
macro(int8, int8, "int8") \
|
||||
macro(int16, int16, "int16") \
|
||||
macro(int32, int32, "int32") \
|
||||
macro(Int8x16, Int8x16, "Int8x16") \
|
||||
macro(Int16x8, Int16x8, "Int16x8") \
|
||||
macro(Int32x4, Int32x4, "Int32x4") \
|
||||
macro(interface, interface, "interface") \
|
||||
macro(InterpretGeneratorResume, InterpretGeneratorResume, "InterpretGeneratorResume") \
|
||||
macro(isEntryPoint, isEntryPoint, "isEntryPoint") \
|
||||
macro(isExtensible, isExtensible, "isExtensible") \
|
||||
|
@ -240,13 +259,17 @@
|
|||
macro(outOfMemory, outOfMemory, "out of memory") \
|
||||
macro(ownKeys, ownKeys, "ownKeys") \
|
||||
macro(Object_valueOf, Object_valueOf, "Object_valueOf") \
|
||||
macro(package, package, "package") \
|
||||
macro(parseFloat, parseFloat, "parseFloat") \
|
||||
macro(parseInt, parseInt, "parseInt") \
|
||||
macro(pattern, pattern, "pattern") \
|
||||
macro(pending, pending, "pending") \
|
||||
macro(public, public_, "public") \
|
||||
macro(preventExtensions, preventExtensions, "preventExtensions") \
|
||||
macro(private, private_, "private") \
|
||||
macro(promise, promise, "promise") \
|
||||
macro(propertyIsEnumerable, propertyIsEnumerable, "propertyIsEnumerable") \
|
||||
macro(protected, protected_, "protected") \
|
||||
macro(proto, proto, "__proto__") \
|
||||
macro(prototype, prototype, "prototype") \
|
||||
macro(proxy, proxy, "proxy") \
|
||||
|
@ -295,10 +318,12 @@
|
|||
macro(StructType, StructType, "StructType") \
|
||||
macro(style, style, "style") \
|
||||
macro(super, super, "super") \
|
||||
macro(switch, switch_, "switch") \
|
||||
macro(Symbol_iterator_fun, Symbol_iterator_fun, "[Symbol.iterator]") \
|
||||
macro(target, target, "target") \
|
||||
macro(test, test, "test") \
|
||||
macro(then, then, "then") \
|
||||
macro(this, this_, "this") \
|
||||
macro(throw, throw_, "throw") \
|
||||
macro(timestamp, timestamp, "timestamp") \
|
||||
macro(timeZone, timeZone, "timeZone") \
|
||||
|
@ -311,7 +336,9 @@
|
|||
macro(toString, toString, "toString") \
|
||||
macro(toUTCString, toUTCString, "toUTCString") \
|
||||
macro(true, true_, "true") \
|
||||
macro(try, try_, "try") \
|
||||
macro(type, type, "type") \
|
||||
macro(typeof, typeof_, "typeof") \
|
||||
macro(uint8, uint8, "uint8") \
|
||||
macro(uint8Clamped, uint8Clamped, "uint8Clamped") \
|
||||
macro(uint16, uint16, "uint16") \
|
||||
|
@ -331,6 +358,7 @@
|
|||
macro(useAsm, useAsm, "use asm") \
|
||||
macro(useGrouping, useGrouping, "useGrouping") \
|
||||
macro(useStrict, useStrict, "use strict") \
|
||||
macro(void, void_, "void") \
|
||||
macro(value, value, "value") \
|
||||
macro(valueOf, valueOf, "valueOf") \
|
||||
macro(values, values, "values") \
|
||||
|
@ -345,6 +373,8 @@
|
|||
macro(weekday, weekday, "weekday") \
|
||||
macro(weekendEnd, weekendEnd, "weekendEnd") \
|
||||
macro(weekendStart, weekendStart, "weekendStart") \
|
||||
macro(while, while_, "while") \
|
||||
macro(with, with, "with") \
|
||||
macro(writable, writable, "writable") \
|
||||
macro(year, year, "year") \
|
||||
macro(yield, yield, "yield") \
|
||||
|
|
|
@ -7057,7 +7057,7 @@ ParseFunction(ModuleValidator& m, ParseNode** fnOut, unsigned* line)
|
|||
TokenKind tk;
|
||||
if (!tokenStream.getToken(&tk, TokenStream::Operand))
|
||||
return false;
|
||||
if (tk != TOK_NAME && tk != TOK_YIELD)
|
||||
if (!TokenKindIsPossibleIdentifier(tk))
|
||||
return false; // The regular parser will throw a SyntaxError, no need to m.fail.
|
||||
|
||||
RootedPropertyName name(m.cx(), m.parser().bindingIdentifier(YieldIsName));
|
||||
|
|
Loading…
Reference in New Issue