mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 22:32:46 +00:00
Added support for named function parameters. Fixed several minor variable definition bugs.
This commit is contained in:
parent
03bcfe58b9
commit
7742f17c6f
@ -2268,9 +2268,10 @@ BinaryOpEquals:
|
||||
|
||||
uint32 reqArgCount = 0;
|
||||
uint32 optArgCount = 0;
|
||||
uint32 namedArgCount = 0;
|
||||
|
||||
VariableBinding *b = f->function.parameters;
|
||||
while ((b != f->function.optParameters) && (b != f->function.restParameter)) {
|
||||
while (b != f->function.optParameters) {
|
||||
reqArgCount++;
|
||||
b = b->next;
|
||||
}
|
||||
@ -2278,7 +2279,13 @@ BinaryOpEquals:
|
||||
optArgCount++;
|
||||
b = b->next;
|
||||
}
|
||||
fnc->setArgCounts(m_cx, reqArgCount, optArgCount, (f->function.restParameter != NULL));
|
||||
b = f->function.namedParameters;
|
||||
while (b) {
|
||||
namedArgCount++;
|
||||
b = b->next;
|
||||
}
|
||||
fnc->setArgCounts(m_cx, reqArgCount, optArgCount, namedArgCount,
|
||||
f->function.restParameter != f->function.namedParameters, f->function.restIsNamed);
|
||||
|
||||
if (mScopeChain->isPossibleUncheckedFunction(&f->function))
|
||||
fnc->setIsPrototype(true);
|
||||
|
@ -952,7 +952,6 @@ bool ScopeChain::isPossibleUncheckedFunction(FunctionDefinition *f)
|
||||
{
|
||||
bool result = false;
|
||||
if ((f->resultType == NULL)
|
||||
&& (f->restParameter == NULL)
|
||||
&& (f->optParameters == NULL)
|
||||
&& (f->prefix == FunctionName::normal)
|
||||
&& (topClass() == NULL)) {
|
||||
@ -1107,9 +1106,10 @@ void ScopeChain::collectNames(StmtNode *p)
|
||||
|
||||
uint32 reqArgCount = 0;
|
||||
uint32 optArgCount = 0;
|
||||
uint32 namedArgCount = 0;
|
||||
|
||||
VariableBinding *b = f->function.parameters;
|
||||
while ((b != f->function.optParameters) && (b != f->function.restParameter)) {
|
||||
while (b != f->function.optParameters) {
|
||||
reqArgCount++;
|
||||
b = b->next;
|
||||
}
|
||||
@ -1117,7 +1117,13 @@ void ScopeChain::collectNames(StmtNode *p)
|
||||
optArgCount++;
|
||||
b = b->next;
|
||||
}
|
||||
fnc->setArgCounts(m_cx, reqArgCount, optArgCount, (f->function.restParameter != NULL));
|
||||
b = f->function.namedParameters;
|
||||
while (b) {
|
||||
namedArgCount++;
|
||||
b = b->next;
|
||||
}
|
||||
fnc->setArgCounts(m_cx, reqArgCount, optArgCount, namedArgCount,
|
||||
f->function.restParameter != f->function.namedParameters, f->function.restIsNamed);
|
||||
|
||||
if (isOperator) {
|
||||
// no need to do anything yet, all operators are 'pre-declared'
|
||||
@ -1922,9 +1928,10 @@ static JSValue Function_Constructor(Context *cx, const JSValue& thisValue, JSVal
|
||||
|
||||
uint32 reqArgCount = 0;
|
||||
uint32 optArgCount = 0;
|
||||
uint32 namedArgCount = 0;
|
||||
|
||||
VariableBinding *b = f->function.parameters;
|
||||
while ((b != f->function.optParameters) && (b != f->function.restParameter)) {
|
||||
while (b != f->function.optParameters) {
|
||||
reqArgCount++;
|
||||
b = b->next;
|
||||
}
|
||||
@ -1932,7 +1939,13 @@ static JSValue Function_Constructor(Context *cx, const JSValue& thisValue, JSVal
|
||||
optArgCount++;
|
||||
b = b->next;
|
||||
}
|
||||
fnc->setArgCounts(cx, reqArgCount, optArgCount, (f->function.restParameter != NULL));
|
||||
b = f->function.namedParameters;
|
||||
while (b) {
|
||||
namedArgCount++;
|
||||
b = b->next;
|
||||
}
|
||||
fnc->setArgCounts(cx, reqArgCount, optArgCount, namedArgCount,
|
||||
f->function.restParameter != f->function.namedParameters, f->function.restIsNamed);
|
||||
|
||||
if (cx->mScopeChain->isPossibleUncheckedFunction(&f->function)) {
|
||||
fnc->setIsPrototype(true);
|
||||
@ -2497,15 +2510,17 @@ JSFunction::JSFunction(Context *, NativeCode *code, JSType *resultType)
|
||||
JSValue JSFunction::runArgInitializer(Context *cx, uint32 a, const JSValue& thisValue, JSValue *argv, uint32 argc)
|
||||
{
|
||||
ASSERT(mArguments && (a < (mRequiredArgs + mOptionalArgs)));
|
||||
return cx->interpret(getByteCode(), (int32)mArguments[a].mInitializer, getScopeChain(), thisValue, argv, argc);
|
||||
return cx->interpret(getByteCode(), (int32)mArguments[a].mInitializer, getScopeChain(), thisValue, argv, argc);
|
||||
}
|
||||
|
||||
void JSFunction::setArgCounts(Context *cx, uint32 r, uint32 o, bool hasRest)
|
||||
void JSFunction::setArgCounts(Context *cx, uint32 r, uint32 o, uint32 n, bool hasRest, bool restIsNamed)
|
||||
{
|
||||
mHasRestParameter = hasRest;
|
||||
mRequiredArgs = r;
|
||||
mOptionalArgs = o;
|
||||
mArguments = new ArgumentData[mRequiredArgs + mOptionalArgs + ((hasRest) ? 1 : 0)];
|
||||
mHasRestParameter = hasRest;
|
||||
mRestIsNamed = restIsNamed;
|
||||
mRequiredArgs = r;
|
||||
mOptionalArgs = o;
|
||||
mNamedArgs = n;
|
||||
mArguments = new ArgumentData[mRequiredArgs + mOptionalArgs + ((hasRest) ? 1 : 0)];
|
||||
defineVariable(cx, cx->Length_StringAtom, (NamespaceList *)NULL, Property::DontDelete | Property::ReadOnly, Number_Type, JSValue((float64)mRequiredArgs));
|
||||
}
|
||||
|
||||
@ -2553,7 +2568,7 @@ void Context::initClass(JSType *type, ClassDef *cdef, PrototypeFunctions *pdef)
|
||||
// fun->setClass(type); don't do this, it makes the function a method
|
||||
StringAtom *name = &mWorld.identifiers[widenCString(pdef->mDef[i].name)];
|
||||
fun->setFunctionName(name);
|
||||
fun->setArgCounts(this, pdef->mDef[i].length, 0, false);
|
||||
fun->setArgCounts(this, pdef->mDef[i].length, 0, 0, false, false);
|
||||
type->mPrototypeObject->defineVariable(this, *name,
|
||||
(NamespaceList *)(NULL),
|
||||
Property::NoAttribute,
|
||||
@ -2963,7 +2978,7 @@ Context::Context(JSObject **global, World &world, Arena &a, Pragma::Flags flags)
|
||||
|
||||
for (i = 0; i < (sizeof(globalObjectFunctions) / sizeof(ProtoFunDef)); i++) {
|
||||
x = new JSFunction(this, globalObjectFunctions[i].imp, globalObjectFunctions[i].result);
|
||||
x->setArgCounts(this, globalObjectFunctions[i].length, 0, false);
|
||||
x->setArgCounts(this, globalObjectFunctions[i].length, 0, 0, false, false);
|
||||
x->setIsPrototype(true);
|
||||
getGlobalObject()->defineVariable(this, widenCString(globalObjectFunctions[i].name), (NamespaceList *)(NULL), Property::NoAttribute, globalObjectFunctions[i].result, JSValue(x));
|
||||
}
|
||||
|
@ -1212,7 +1212,7 @@ XXX ...couldn't get this to work...
|
||||
|
||||
void setByteCode(ByteCodeModule *b) { ASSERT(!isNative()); mByteCode = b; }
|
||||
void setResultType(JSType *r) { mResultType = r; }
|
||||
void setArgCounts(Context *cx, uint32 r, uint32 o, bool hasRest);
|
||||
void setArgCounts(Context *cx, uint32 r, uint32 o, uint32 n, bool hasRest, bool restIsNamed);
|
||||
void setArgument(uint32 index, const String *n, JSType *t)
|
||||
{ ASSERT(mArguments && (index < (mRequiredArgs + mOptionalArgs + ((mHasRestParameter) ? 1 : 0) ))); mArguments[index].mType = t; mArguments[index].mName = n; }
|
||||
void setArgumentInitializer(uint32 index, uint32 offset)
|
||||
@ -1269,12 +1269,14 @@ XXX ...couldn't get this to work...
|
||||
JSType *mResultType;
|
||||
uint32 mRequiredArgs; // total # parameters
|
||||
uint32 mOptionalArgs;
|
||||
uint32 mNamedArgs;
|
||||
ArgumentData *mArguments;
|
||||
ScopeChain *mScopeChain;
|
||||
bool mIsPrototype; // set for functions with prototype attribute
|
||||
bool mIsConstructor;
|
||||
bool mIsChecked;
|
||||
bool mHasRestParameter;
|
||||
bool mRestIsNamed;
|
||||
const String *mRestParameterName;
|
||||
JSType *mClass; // pointer to owning class if this function is a method
|
||||
FunctionName *mFunctionName;
|
||||
|
@ -256,7 +256,7 @@ void initMathObject(Context *cx, JSObject *mathObj)
|
||||
|
||||
for (i = 0; i < sizeof(MathObjectFunctions) / sizeof(MathObjectFunctionDef); i++) {
|
||||
JSFunction *f = new JSFunction(cx, MathObjectFunctions[i].imp, Number_Type);
|
||||
f->setArgCounts(cx, MathObjectFunctions[i].length, 0, false);
|
||||
f->setArgCounts(cx, MathObjectFunctions[i].length, 0, 0, false, false);
|
||||
mathObj->defineVariable(cx, widenCString(MathObjectFunctions[i].name),
|
||||
(NamespaceList *)(NULL), Property::ReadOnly | Property::DontDelete,
|
||||
Number_Type, JSValue(f));
|
||||
|
@ -787,6 +787,7 @@ const JS::Parser::BinaryOperatorInfo JS::Parser::tokenBinaryOperatorInfos[Token:
|
||||
{ExprNode::none, pExpression, pNone, false}, // Token::Get
|
||||
{ExprNode::none, pExpression, pNone, false}, // Token::Include
|
||||
{ExprNode::none, pExpression, pNone, false}, // Token::Javascript
|
||||
{ExprNode::none, pExpression, pNone, false}, // Token::Named
|
||||
{ExprNode::none, pExpression, pNone, false}, // Token::Set
|
||||
{ExprNode::none, pExpression, pNone, false}, // Token::Strict
|
||||
|
||||
@ -1053,32 +1054,40 @@ bool JS::Parser::doubleColonFollows()
|
||||
}
|
||||
|
||||
|
||||
// Parse and return a VariableBinding (UntypedVariableBinding if untyped is true).
|
||||
// Parse and return a VariableBinding or, depnding on the flags given, one of the related productions
|
||||
// UntypedVariableBinding, TypedIdentifier, TypedInitialiser, or Identifier.
|
||||
// pos is the position of the binding or its first attribute, if any.
|
||||
// If noIn is false, allow the in operator.
|
||||
// If noIn is true, don't allow the in operator.
|
||||
// If noType is true, don't allow a type annotation.
|
||||
// If noInitializer is true, don't allow any initializers.
|
||||
// If noAttributes is true, don't allow initializers that are not expressions.
|
||||
// The value of the constant parameter is stored in the returned VariableBinding.
|
||||
//
|
||||
// If the first token was peeked, it should be have been done with preferRegExp set to true.
|
||||
// If the first or second token was peeked, it should be have been done with preferRegExp set to true.
|
||||
// After parseVariableBinding finishes, the next token might have been peeked with preferRegExp set to true.
|
||||
// The reason preferRegExp is true is to correctly parse the following case of semicolon insertion:
|
||||
// var a
|
||||
// /regexp/
|
||||
JS::VariableBinding *JS::Parser::parseVariableBinding(size_t pos, bool noIn, bool untyped, bool constant)
|
||||
JS::VariableBinding *JS::Parser::parseVariableBinding(size_t pos, bool noIn, bool noType, bool noInitializer, bool noAttributes, bool constant)
|
||||
{
|
||||
const StringAtom &name = parseIdentifier();
|
||||
|
||||
ExprNode *type = 0;
|
||||
if (lexer.eat(true, Token::colon))
|
||||
if (untyped)
|
||||
syntaxError("Type annotation not allowed in a var inside a substatement; enclose the var in a block");
|
||||
if (noType)
|
||||
syntaxError(noInitializer ? "Type annotation not allowed on a named ... parameter" :
|
||||
"Type annotation not allowed in a var inside a substatement; enclose the var in a block");
|
||||
else
|
||||
type = parseTypeExpression(noIn);
|
||||
|
||||
ExprNode *initializer = 0;
|
||||
if (lexer.eat(true, Token::assignment)) {
|
||||
if (noInitializer)
|
||||
syntaxError("Initializer not allowed on a ... parameter");
|
||||
|
||||
const Token &t = lexer.get(true);
|
||||
size_t tPos = t.getPos();
|
||||
if (!untyped && (t.getFlag(Token::isNonExpressionAttribute) || t.hasKind(Token::Private) && !doubleColonFollows())) {
|
||||
if (!noAttributes && (t.getFlag(Token::isNonExpressionAttribute) || t.hasKind(Token::Private) && !doubleColonFollows())) {
|
||||
initializer = new(arena) IdentifierExprNode(t);
|
||||
makeAttribute:
|
||||
initializer = parseAttributes(tPos, initializer);
|
||||
@ -1087,7 +1096,7 @@ JS::VariableBinding *JS::Parser::parseVariableBinding(size_t pos, bool noIn, boo
|
||||
initializer = parseAssignmentExpression(noIn);
|
||||
lexer.redesignate(true); // Safe: a '/' or a '/=' would have been interpreted as an operator,
|
||||
// so it can't be the next token.
|
||||
if (!untyped && expressionIsAttribute(initializer)) {
|
||||
if (!noAttributes && expressionIsAttribute(initializer)) {
|
||||
const Token &t2 = lexer.peek(true);
|
||||
if (!lineBreakBefore(t2) && t2.getFlag(Token::canFollowAttribute))
|
||||
goto makeAttribute;
|
||||
@ -1100,20 +1109,37 @@ JS::VariableBinding *JS::Parser::parseVariableBinding(size_t pos, bool noIn, boo
|
||||
|
||||
|
||||
// Parse and return a VariableBinding for a function parameter. The parameter may optionally be
|
||||
// preceded by the const attribute.
|
||||
// preceded by the const and/or named attributes. If named is true on entry to this function, then
|
||||
// the named attribute is required and named will remain true on exit. If named is false on entry,
|
||||
// then the named attribute is optional and named will be true only if the named attribute was given.
|
||||
// If rest is true, then no initializer is allowed and, if the named attribute is also found, no type
|
||||
// is allowed. rest and named must not be simultaneously true on entry to this function.
|
||||
// This function does not check that named parameters have initializers; the caller should make this
|
||||
// check.
|
||||
//
|
||||
// If the first token was peeked, it should be have been done with preferRegExp set to true.
|
||||
// After parseParameter finishes, the next token might have been peeked with preferRegExp set to true.
|
||||
JS::VariableBinding *JS::Parser::parseParameter()
|
||||
JS::VariableBinding *JS::Parser::parseParameter(bool rest, bool &named)
|
||||
{
|
||||
const Token &t = lexer.peek(true);
|
||||
size_t pos = t.getPos();
|
||||
bool constant = false;
|
||||
if (t.hasKind(Token::Const)) {
|
||||
lexer.skip();
|
||||
constant = true;
|
||||
const Token *t = &lexer.get(true);
|
||||
size_t pos = t->getPos();
|
||||
bool constToken = false;
|
||||
bool namedToken = false;
|
||||
while (true) {
|
||||
if (t->hasKind(Token::Const) && !constToken)
|
||||
constToken = true;
|
||||
// If the named attribute is required then assume that any Token::Named is the attribute. If it
|
||||
// isn't, then the parse will generate an error further down.
|
||||
else if (t->hasKind(Token::Named) && !namedToken && (named || lexer.peek(true).getFlag(Token::canFollowAttribute)))
|
||||
namedToken = true;
|
||||
else break;
|
||||
t = &lexer.get(true);
|
||||
}
|
||||
return parseVariableBinding(pos, false, false, constant);
|
||||
lexer.unget();
|
||||
if (named && !namedToken)
|
||||
syntaxError("'named' expected", 0);
|
||||
named = namedToken;
|
||||
return parseVariableBinding(pos, false, rest && namedToken, rest, true, constToken);
|
||||
}
|
||||
|
||||
|
||||
@ -1157,40 +1183,58 @@ void JS::Parser::parseFunctionSignature(FunctionDefinition &fd)
|
||||
NodeQueue<VariableBinding> parameters;
|
||||
VariableBinding *optParameters = 0;
|
||||
VariableBinding *restParameter = 0;
|
||||
VariableBinding *namedParameters = 0;
|
||||
bool restIsNamed = false;
|
||||
bool named = false;
|
||||
|
||||
// The code below is very tricky because it discovers syntax errors on the earliest
|
||||
// possible token. Be careful to account for all possible error cases.
|
||||
if (!lexer.eat(true, Token::closeParenthesis)) {
|
||||
while (true) {
|
||||
if (lexer.eat(true, Token::tripleDot)) {
|
||||
if (restParameter)
|
||||
syntaxError("A ... parameter can't follow a named or ... parameter");
|
||||
const Token &t1 = lexer.peek(true);
|
||||
if (t1.hasKind(Token::closeParenthesis))
|
||||
if (t1.hasKind(Token::closeParenthesis) || t1.hasKind(Token::comma))
|
||||
restParameter = new(arena) VariableBinding(t1.getPos(), 0, 0, 0, false);
|
||||
else
|
||||
restParameter = parseParameter();
|
||||
restParameter = parseParameter(true, named);
|
||||
restIsNamed = named;
|
||||
if (!optParameters)
|
||||
optParameters = restParameter;
|
||||
parameters += restParameter;
|
||||
require(true, Token::closeParenthesis);
|
||||
break;
|
||||
named = true; // Only named parameters may follow.
|
||||
} else {
|
||||
VariableBinding *b = parseParameter();
|
||||
VariableBinding *b = parseParameter(false, named);
|
||||
if (named) {
|
||||
if (!namedParameters)
|
||||
namedParameters = b;
|
||||
if (!restParameter)
|
||||
restParameter = b;
|
||||
}
|
||||
if (b->initializer) {
|
||||
if (!optParameters)
|
||||
optParameters = b;
|
||||
} else
|
||||
if (optParameters)
|
||||
if (optParameters || named)
|
||||
syntaxError("'=' expected", 0);
|
||||
parameters += b;
|
||||
const Token &t = lexer.get(true);
|
||||
if (!t.hasKind(Token::comma))
|
||||
if (t.hasKind(Token::closeParenthesis))
|
||||
break;
|
||||
else
|
||||
syntaxError("',' or ')' expected");
|
||||
}
|
||||
const Token &t = lexer.get(true);
|
||||
if (!t.hasKind(Token::comma))
|
||||
if (t.hasKind(Token::closeParenthesis))
|
||||
break;
|
||||
else
|
||||
syntaxError("',' or ')' expected");
|
||||
if (restIsNamed)
|
||||
syntaxError("')' expected"); // Nothing may follow a named rest parameter.
|
||||
}
|
||||
}
|
||||
fd.parameters = parameters.first;
|
||||
fd.optParameters = optParameters;
|
||||
fd.restParameter = restParameter;
|
||||
fd.namedParameters = namedParameters;
|
||||
fd.restIsNamed = restIsNamed;
|
||||
fd.resultType = parseTypeBinding(Token::colon, false);
|
||||
}
|
||||
|
||||
@ -1525,7 +1569,7 @@ JS::StmtNode *JS::Parser::parseAnnotatableDirective(size_t pos, ExprNode *attrib
|
||||
{
|
||||
NodeQueue<VariableBinding> bindings;
|
||||
|
||||
do bindings += parseVariableBinding(lexer.peek(true).getPos(), noIn, untyped, sKind == StmtNode::Const);
|
||||
do bindings += parseVariableBinding(lexer.peek(true).getPos(), noIn, untyped, false, false, sKind == StmtNode::Const);
|
||||
while (lexer.eat(true, Token::comma));
|
||||
s = new(arena) VariableStmtNode(pos, sKind, attributes, bindings.first);
|
||||
}
|
||||
@ -2057,13 +2101,20 @@ void JS::FunctionDefinition::print(PrettyPrinter &f, const AttributeStmtNode *at
|
||||
{
|
||||
PrettyPrinter::Block b2(f);
|
||||
const VariableBinding *p = parameters;
|
||||
if (p)
|
||||
if (p) {
|
||||
bool named = false;
|
||||
while (true) {
|
||||
if (p == restParameter) {
|
||||
if (p == namedParameters)
|
||||
named = true;
|
||||
else if (p == restParameter) {
|
||||
f << "...";
|
||||
if (p->name)
|
||||
if (restIsNamed)
|
||||
f << " named ";
|
||||
else if (p->name)
|
||||
f << ' ';
|
||||
}
|
||||
if (named)
|
||||
f << "named ";
|
||||
p->print(f, true);
|
||||
p = p->next;
|
||||
if (!p)
|
||||
@ -2071,6 +2122,7 @@ void JS::FunctionDefinition::print(PrettyPrinter &f, const AttributeStmtNode *at
|
||||
f << ',';
|
||||
f.fillBreak(1);
|
||||
}
|
||||
}
|
||||
f << ')';
|
||||
}
|
||||
if (resultType) {
|
||||
|
@ -274,9 +274,15 @@ namespace JavaScript {
|
||||
|
||||
|
||||
struct FunctionDefinition: FunctionName {
|
||||
VariableBinding *parameters; // Linked list of all parameters, including optional and rest parameters, if any
|
||||
VariableBinding *optParameters; // Pointer to first non-required (or rest) parameter inside parameters list; nil if none
|
||||
VariableBinding *restParameter; // Pointer to rest parameter inside parameters list; nil if none
|
||||
// The parameters linked list includes all kinds of parameters. optParameters, restParameter, and namedParameters
|
||||
// are pointers into the interior of the linked list. If any kind is empty, then that kind's pointer is equal to
|
||||
// the following kind's pointer, so, for example, if there is no rest parameter then restParameter == namedParameters.
|
||||
// A pointer is nil only if its kind and all subsequent kinds are empty.
|
||||
VariableBinding *parameters; // Linked list of all parameters, including optional, rest, and named parameters
|
||||
VariableBinding *optParameters; // Pointer to first optional parameter inside parameters list
|
||||
VariableBinding *restParameter; // Pointer to rest parameter inside parameters list
|
||||
VariableBinding *namedParameters;// Pointer to first named parameter inside parameters list
|
||||
bool restIsNamed; // True if the rest parameter has the 'named' attribute
|
||||
ExprNode *resultType; // Result type expression or nil if not provided
|
||||
BlockStmtNode *body; // Body; nil if none
|
||||
|
||||
@ -827,8 +833,8 @@ namespace JavaScript {
|
||||
ExprNode *parseTypeExpression(bool noIn=false);
|
||||
ExprNode *parseTypeBinding(Token::Kind kind, bool noIn);
|
||||
bool doubleColonFollows();
|
||||
VariableBinding *parseVariableBinding(size_t pos, bool noIn, bool untyped, bool constant);
|
||||
VariableBinding *parseParameter();
|
||||
VariableBinding *parseVariableBinding(size_t pos, bool noIn, bool noType, bool noInitializer, bool noAttributes, bool constant);
|
||||
VariableBinding *parseParameter(bool rest, bool &named);
|
||||
void parseFunctionName(FunctionName &fn);
|
||||
void parseFunctionSignature(FunctionDefinition &fd);
|
||||
ExportBinding *parseExportBinding();
|
||||
|
@ -171,6 +171,7 @@ const char *const JS::Token::kindNames[kindsEnd] = {
|
||||
"get", // Get
|
||||
"include", // Include
|
||||
"javascript", // Javascript
|
||||
"named", // Named
|
||||
"set", // Set
|
||||
"strict" // Strict
|
||||
};
|
||||
@ -314,6 +315,7 @@ const uchar JS::Token::kindFlags[kindsEnd] = {
|
||||
isAttr|nonreserved, // Get
|
||||
isAttr|nonreserved, // Include
|
||||
isAttr|nonreserved, // Javascript
|
||||
isAttr|nonreserved, // Named
|
||||
isAttr|nonreserved, // Set
|
||||
isAttr|nonreserved, // Strict
|
||||
|
||||
|
@ -186,6 +186,7 @@ namespace JavaScript
|
||||
Get, // get
|
||||
Include, // include
|
||||
Javascript, // javascript
|
||||
Named, // named
|
||||
Set, // set
|
||||
Strict, // strict
|
||||
|
||||
@ -208,6 +209,7 @@ namespace JavaScript
|
||||
case Token::Get: \
|
||||
case Token::Include: \
|
||||
case Token::Javascript: \
|
||||
case Token::Named: \
|
||||
case Token::Set: \
|
||||
case Token::Strict: \
|
||||
case Token::identifier
|
||||
@ -218,6 +220,7 @@ namespace JavaScript
|
||||
case Token::Exclude: \
|
||||
case Token::Get: \
|
||||
case Token::Javascript: \
|
||||
case Token::Named: \
|
||||
case Token::Set: \
|
||||
case Token::Strict: \
|
||||
case Token::identifier
|
||||
|
Loading…
Reference in New Issue
Block a user