|
Lines 1150-1155
template <class TreeBuilder> TreeStatement Parser<LexerType>::parseStatement(Tre
a/Source/JavaScriptCore/parser/Parser.cpp_sec1
|
| 1150 |
case CONSTTOKEN: |
1150 |
case CONSTTOKEN: |
| 1151 |
result = parseConstDeclaration(context); |
1151 |
result = parseConstDeclaration(context); |
| 1152 |
break; |
1152 |
break; |
|
|
1153 |
case CLASSTOKEN: |
| 1154 |
failIfFalse(m_statementDepth == 1, "Class declaration is not allowed in a lexically nested statement"); |
| 1155 |
result = parseClassDeclaration(context); |
| 1156 |
break; |
| 1153 |
case FUNCTION: |
1157 |
case FUNCTION: |
| 1154 |
failIfFalseIfStrict(m_statementDepth == 1, "Strict mode does not allow function declarations in a lexically nested statement"); |
1158 |
failIfFalseIfStrict(m_statementDepth == 1, "Strict mode does not allow function declarations in a lexically nested statement"); |
| 1155 |
result = parseFunctionDeclaration(context); |
1159 |
result = parseFunctionDeclaration(context); |
|
Lines 1267-1279
static const char* stringForFunctionMode(FunctionParseMode mode)
a/Source/JavaScriptCore/parser/Parser.cpp_sec2
|
| 1267 |
return "setter"; |
1271 |
return "setter"; |
| 1268 |
case FunctionMode: |
1272 |
case FunctionMode: |
| 1269 |
return "function"; |
1273 |
return "function"; |
|
|
1274 |
case MethodMode: |
| 1275 |
return "method"; |
| 1270 |
} |
1276 |
} |
| 1271 |
RELEASE_ASSERT_NOT_REACHED(); |
1277 |
RELEASE_ASSERT_NOT_REACHED(); |
| 1272 |
return nullptr; |
1278 |
return nullptr; |
| 1273 |
} |
1279 |
} |
| 1274 |
|
1280 |
|
| 1275 |
template <typename LexerType> |
1281 |
template <typename LexerType> |
| 1276 |
template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuilder& context, FunctionRequirements requirements, FunctionParseMode mode, bool nameIsInContainingScope, const Identifier*& name, TreeFormalParameterList& parameters, TreeFunctionBody& body, unsigned& openBraceOffset, unsigned& closeBraceOffset, int& bodyStartLine, unsigned& bodyStartColumn) |
1282 |
template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuilder& context, FunctionRequirements requirements, FunctionParseMode mode, bool nameIsInContainingScope, ParserFunctionInfo<TreeBuilder>& info) |
| 1277 |
{ |
1283 |
{ |
| 1278 |
AutoPopScopeRef functionScope(this, pushScope()); |
1284 |
AutoPopScopeRef functionScope(this, pushScope()); |
| 1279 |
functionScope->setIsFunction(); |
1285 |
functionScope->setIsFunction(); |
|
Lines 1281-1294
template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuild
a/Source/JavaScriptCore/parser/Parser.cpp_sec3
|
| 1281 |
const Identifier* lastFunctionName = m_lastFunctionName; |
1287 |
const Identifier* lastFunctionName = m_lastFunctionName; |
| 1282 |
m_lastFunctionName = nullptr; |
1288 |
m_lastFunctionName = nullptr; |
| 1283 |
if (match(IDENT)) { |
1289 |
if (match(IDENT)) { |
| 1284 |
name = m_token.m_data.ident; |
1290 |
info.name = m_token.m_data.ident; |
| 1285 |
m_lastFunctionName = name; |
1291 |
m_lastFunctionName = info.name; |
| 1286 |
next(); |
1292 |
next(); |
| 1287 |
if (!nameIsInContainingScope) |
1293 |
if (!nameIsInContainingScope) |
| 1288 |
failIfFalseIfStrict(functionScope->declareVariable(name), "'", name->impl(), "' is not a valid ", stringForFunctionMode(mode), " name in strict mode"); |
1294 |
failIfFalseIfStrict(functionScope->declareVariable(info.name), "'", info.name->impl(), "' is not a valid ", stringForFunctionMode(mode), " name in strict mode"); |
| 1289 |
} else if (requirements == FunctionNeedsName) { |
1295 |
} else if (requirements == FunctionNeedsName) { |
| 1290 |
if (match(OPENPAREN) && mode == FunctionMode) |
1296 |
if (match(OPENPAREN) && mode == FunctionMode) |
| 1291 |
semanticFail("Function statements must have a name"); |
1297 |
semanticFail(stringForFunctionMode(mode), " must have a name"); |
| 1292 |
semanticFailureDueToKeyword(stringForFunctionMode(mode), " name"); |
1298 |
semanticFailureDueToKeyword(stringForFunctionMode(mode), " name"); |
| 1293 |
failDueToUnexpectedToken(); |
1299 |
failDueToUnexpectedToken(); |
| 1294 |
return false; |
1300 |
return false; |
|
Lines 1298-1316
template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuild
a/Source/JavaScriptCore/parser/Parser.cpp_sec4
|
| 1298 |
failWithMessage("Expected an opening '(' before a ", stringForFunctionMode(mode), "'s parameter list"); |
1304 |
failWithMessage("Expected an opening '(' before a ", stringForFunctionMode(mode), "'s parameter list"); |
| 1299 |
} |
1305 |
} |
| 1300 |
if (!match(CLOSEPAREN)) { |
1306 |
if (!match(CLOSEPAREN)) { |
| 1301 |
parameters = parseFormalParameters(context); |
1307 |
info.parameters = parseFormalParameters(context); |
| 1302 |
failIfFalse(parameters, "Cannot parse parameters for this ", stringForFunctionMode(mode)); |
1308 |
failIfFalse(info.parameters, "Cannot parse parameters for this ", stringForFunctionMode(mode)); |
| 1303 |
} |
1309 |
} |
| 1304 |
consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration"); |
1310 |
consumeOrFail(CLOSEPAREN, "Expected a ')' or a ',' after a parameter declaration"); |
| 1305 |
matchOrFail(OPENBRACE, "Expected an opening '{' at the start of a ", stringForFunctionMode(mode), " body"); |
1311 |
matchOrFail(OPENBRACE, "Expected an opening '{' at the start of a ", stringForFunctionMode(mode), " body"); |
| 1306 |
|
1312 |
|
| 1307 |
openBraceOffset = m_token.m_data.offset; |
1313 |
info.openBraceOffset = m_token.m_data.offset; |
| 1308 |
bodyStartLine = tokenLine(); |
1314 |
info.bodyStartLine = tokenLine(); |
| 1309 |
bodyStartColumn = m_token.m_data.offset - m_token.m_data.lineStartOffset; |
1315 |
info.bodyStartColumn = m_token.m_data.offset - m_token.m_data.lineStartOffset; |
| 1310 |
JSTokenLocation startLocation(tokenLocation()); |
1316 |
JSTokenLocation startLocation(tokenLocation()); |
| 1311 |
|
1317 |
|
| 1312 |
// If we know about this function already, we can use the cached info and skip the parser to the end of the function. |
1318 |
// If we know about this function already, we can use the cached info and skip the parser to the end of the function. |
| 1313 |
if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(openBraceOffset) : 0) { |
1319 |
if (const SourceProviderCacheItem* cachedInfo = TreeBuilder::CanUseFunctionCache ? findCachedFunctionInfo(info.openBraceOffset) : 0) { |
| 1314 |
// If we're in a strict context, the cached function info must say it was strict too. |
1320 |
// If we're in a strict context, the cached function info must say it was strict too. |
| 1315 |
ASSERT(!strictMode() || cachedInfo->strictMode); |
1321 |
ASSERT(!strictMode() || cachedInfo->strictMode); |
| 1316 |
JSTokenLocation endLocation; |
1322 |
JSTokenLocation endLocation; |
|
Lines 1319-1339
template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuild
a/Source/JavaScriptCore/parser/Parser.cpp_sec5
|
| 1319 |
endLocation.startOffset = cachedInfo->closeBraceOffset; |
1325 |
endLocation.startOffset = cachedInfo->closeBraceOffset; |
| 1320 |
endLocation.lineStartOffset = cachedInfo->closeBraceLineStartOffset; |
1326 |
endLocation.lineStartOffset = cachedInfo->closeBraceLineStartOffset; |
| 1321 |
|
1327 |
|
| 1322 |
bool endColumnIsOnStartLine = (endLocation.line == bodyStartLine); |
1328 |
bool endColumnIsOnStartLine = (endLocation.line == info.bodyStartLine); |
| 1323 |
ASSERT(endLocation.startOffset >= endLocation.lineStartOffset); |
1329 |
ASSERT(endLocation.startOffset >= endLocation.lineStartOffset); |
| 1324 |
unsigned bodyEndColumn = endColumnIsOnStartLine ? |
1330 |
unsigned bodyEndColumn = endColumnIsOnStartLine ? |
| 1325 |
endLocation.startOffset - m_token.m_data.lineStartOffset : |
1331 |
endLocation.startOffset - m_token.m_data.lineStartOffset : |
| 1326 |
endLocation.startOffset - endLocation.lineStartOffset; |
1332 |
endLocation.startOffset - endLocation.lineStartOffset; |
| 1327 |
unsigned currentLineStartOffset = m_token.m_location.lineStartOffset; |
1333 |
unsigned currentLineStartOffset = m_token.m_location.lineStartOffset; |
| 1328 |
|
1334 |
|
| 1329 |
body = context.createFunctionBody(startLocation, endLocation, bodyStartColumn, bodyEndColumn, cachedInfo->strictMode); |
1335 |
info.body = context.createFunctionBody(startLocation, endLocation, info.bodyStartColumn, bodyEndColumn, cachedInfo->strictMode); |
| 1330 |
|
1336 |
|
| 1331 |
functionScope->restoreFromSourceProviderCache(cachedInfo); |
1337 |
functionScope->restoreFromSourceProviderCache(cachedInfo); |
| 1332 |
failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo), "Parser error"); |
1338 |
failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo), "Parser error"); |
| 1333 |
|
1339 |
|
| 1334 |
closeBraceOffset = cachedInfo->closeBraceOffset; |
1340 |
info.closeBraceOffset = cachedInfo->closeBraceOffset; |
| 1335 |
|
1341 |
|
| 1336 |
context.setFunctionNameStart(body, functionNameStart); |
1342 |
context.setFunctionNameStart(info.body, functionNameStart); |
| 1337 |
m_token = cachedInfo->closeBraceToken(); |
1343 |
m_token = cachedInfo->closeBraceToken(); |
| 1338 |
if (endColumnIsOnStartLine) |
1344 |
if (endColumnIsOnStartLine) |
| 1339 |
m_token.m_location.lineStartOffset = currentLineStartOffset; |
1345 |
m_token.m_location.lineStartOffset = currentLineStartOffset; |
|
Lines 1341-1363
template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuild
a/Source/JavaScriptCore/parser/Parser.cpp_sec6
|
| 1341 |
m_lexer->setOffset(m_token.m_location.endOffset, m_token.m_location.lineStartOffset); |
1347 |
m_lexer->setOffset(m_token.m_location.endOffset, m_token.m_location.lineStartOffset); |
| 1342 |
m_lexer->setLineNumber(m_token.m_location.line); |
1348 |
m_lexer->setLineNumber(m_token.m_location.line); |
| 1343 |
|
1349 |
|
| 1344 |
context.setEndOffset(body, m_lexer->currentOffset()); |
1350 |
context.setEndOffset(info.body, m_lexer->currentOffset()); |
| 1345 |
|
1351 |
|
| 1346 |
next(); |
1352 |
next(); |
|
|
1353 |
info.bodyEndLine = m_lastTokenEndPosition.line; |
| 1347 |
return true; |
1354 |
return true; |
| 1348 |
} |
1355 |
} |
| 1349 |
m_lastFunctionName = lastFunctionName; |
1356 |
m_lastFunctionName = lastFunctionName; |
| 1350 |
ParserState oldState = saveState(); |
1357 |
ParserState oldState = saveState(); |
| 1351 |
body = parseFunctionBody(context); |
1358 |
info.body = parseFunctionBody(context); |
| 1352 |
restoreState(oldState); |
1359 |
restoreState(oldState); |
| 1353 |
failIfFalse(body, "Cannot parse the body of this ", stringForFunctionMode(mode)); |
1360 |
failIfFalse(info.body, "Cannot parse the body of this ", stringForFunctionMode(mode)); |
| 1354 |
context.setEndOffset(body, m_lexer->currentOffset()); |
1361 |
context.setEndOffset(info.body, m_lexer->currentOffset()); |
| 1355 |
if (functionScope->strictMode() && name) { |
1362 |
if (functionScope->strictMode() && info.name) { |
| 1356 |
RELEASE_ASSERT(mode == FunctionMode); |
1363 |
RELEASE_ASSERT(mode == FunctionMode); |
| 1357 |
semanticFailIfTrue(m_vm->propertyNames->arguments == *name, "'", name->impl(), "' is not a valid function name in strict mode"); |
1364 |
semanticFailIfTrue(m_vm->propertyNames->arguments == *info.name, "'", info.name->impl(), "' is not a valid function name in strict mode"); |
| 1358 |
semanticFailIfTrue(m_vm->propertyNames->eval == *name, "'", name->impl(), "' is not a valid function name in strict mode"); |
1365 |
semanticFailIfTrue(m_vm->propertyNames->eval == *info.name, "'", info.name->impl(), "' is not a valid function name in strict mode"); |
| 1359 |
} |
1366 |
} |
| 1360 |
closeBraceOffset = m_token.m_data.offset; |
1367 |
info.closeBraceOffset = m_token.m_data.offset; |
| 1361 |
unsigned closeBraceLine = m_token.m_data.line; |
1368 |
unsigned closeBraceLine = m_token.m_data.line; |
| 1362 |
unsigned closeBraceLineStartOffset = m_token.m_data.lineStartOffset; |
1369 |
unsigned closeBraceLineStartOffset = m_token.m_data.lineStartOffset; |
| 1363 |
|
1370 |
|
|
Lines 1365-1390
template <class TreeBuilder> bool Parser<LexerType>::parseFunctionInfo(TreeBuild
a/Source/JavaScriptCore/parser/Parser.cpp_sec7
|
| 1365 |
// Any future reparsing can then skip the function. |
1372 |
// Any future reparsing can then skip the function. |
| 1366 |
static const int minimumFunctionLengthToCache = 16; |
1373 |
static const int minimumFunctionLengthToCache = 16; |
| 1367 |
std::unique_ptr<SourceProviderCacheItem> newInfo; |
1374 |
std::unique_ptr<SourceProviderCacheItem> newInfo; |
| 1368 |
int functionLength = closeBraceOffset - openBraceOffset; |
1375 |
int functionLength = info.closeBraceOffset - info.openBraceOffset; |
| 1369 |
if (TreeBuilder::CanUseFunctionCache && m_functionCache && functionLength > minimumFunctionLengthToCache) { |
1376 |
if (TreeBuilder::CanUseFunctionCache && m_functionCache && functionLength > minimumFunctionLengthToCache) { |
| 1370 |
SourceProviderCacheItemCreationParameters parameters; |
1377 |
SourceProviderCacheItemCreationParameters parameters; |
| 1371 |
parameters.functionNameStart = functionNameStart; |
1378 |
parameters.functionNameStart = functionNameStart; |
| 1372 |
parameters.closeBraceLine = closeBraceLine; |
1379 |
parameters.closeBraceLine = closeBraceLine; |
| 1373 |
parameters.closeBraceOffset = closeBraceOffset; |
1380 |
parameters.closeBraceOffset = info.closeBraceOffset; |
| 1374 |
parameters.closeBraceLineStartOffset = closeBraceLineStartOffset; |
1381 |
parameters.closeBraceLineStartOffset = closeBraceLineStartOffset; |
| 1375 |
functionScope->fillParametersForSourceProviderCache(parameters); |
1382 |
functionScope->fillParametersForSourceProviderCache(parameters); |
| 1376 |
newInfo = SourceProviderCacheItem::create(parameters); |
1383 |
newInfo = SourceProviderCacheItem::create(parameters); |
| 1377 |
|
1384 |
|
| 1378 |
} |
1385 |
} |
| 1379 |
context.setFunctionNameStart(body, functionNameStart); |
1386 |
context.setFunctionNameStart(info.body, functionNameStart); |
| 1380 |
|
1387 |
|
| 1381 |
failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo), "Parser error"); |
1388 |
failIfFalse(popScope(functionScope, TreeBuilder::NeedsFreeVariableInfo), "Parser error"); |
| 1382 |
matchOrFail(CLOSEBRACE, "Expected a closing '}' after a ", stringForFunctionMode(mode), " body"); |
1389 |
matchOrFail(CLOSEBRACE, "Expected a closing '}' after a ", stringForFunctionMode(mode), " body"); |
| 1383 |
|
1390 |
|
| 1384 |
if (newInfo) |
1391 |
if (newInfo) |
| 1385 |
m_functionCache->add(openBraceOffset, WTF::move(newInfo)); |
1392 |
m_functionCache->add(info.openBraceOffset, WTF::move(newInfo)); |
| 1386 |
|
1393 |
|
| 1387 |
next(); |
1394 |
next(); |
|
|
1395 |
info.bodyEndLine = m_lastTokenEndPosition.line; |
| 1388 |
return true; |
1396 |
return true; |
| 1389 |
} |
1397 |
} |
| 1390 |
|
1398 |
|
|
Lines 1395-1411
template <class TreeBuilder> TreeStatement Parser<LexerType>::parseFunctionDecla
a/Source/JavaScriptCore/parser/Parser.cpp_sec8
|
| 1395 |
JSTokenLocation location(tokenLocation()); |
1403 |
JSTokenLocation location(tokenLocation()); |
| 1396 |
unsigned functionKeywordStart = tokenStart(); |
1404 |
unsigned functionKeywordStart = tokenStart(); |
| 1397 |
next(); |
1405 |
next(); |
|
|
1406 |
ParserFunctionInfo<TreeBuilder> info; |
| 1407 |
failIfFalse((parseFunctionInfo(context, FunctionNeedsName, FunctionMode, true, info)), "Cannot parse this function"); |
| 1408 |
failIfFalse(info.name, "Function statements must have a name"); |
| 1409 |
failIfFalseIfStrict(declareVariable(info.name), "Cannot declare a function named '", info.name->impl(), "' in strict mode"); |
| 1410 |
return context.createFuncDeclStatement(location, info, functionKeywordStart); |
| 1411 |
} |
| 1412 |
|
| 1413 |
template <typename LexerType> |
| 1414 |
template <class TreeBuilder> TreeStatement Parser<LexerType>::parseClassDeclaration(TreeBuilder& context) |
| 1415 |
{ |
| 1416 |
ASSERT(match(CLASSTOKEN)); |
| 1417 |
JSTokenLocation location(tokenLocation()); |
| 1418 |
JSTextPosition classStart = tokenStartPosition(); |
| 1419 |
unsigned classStartLine = tokenLine(); |
| 1420 |
unsigned classEndLine = 0; |
| 1421 |
next(); |
| 1398 |
const Identifier* name = 0; |
1422 |
const Identifier* name = 0; |
| 1399 |
TreeFormalParameterList parameters = 0; |
1423 |
TreeExpression parentClass = 0; |
| 1400 |
TreeFunctionBody body = 0; |
1424 |
TreeExpression constructor = 0; |
| 1401 |
unsigned openBraceOffset = 0; |
1425 |
TreePropertyList instanceMethods = 0; |
| 1402 |
unsigned closeBraceOffset = 0; |
1426 |
TreePropertyList staticMethods = 0; |
| 1403 |
int bodyStartLine = 0; |
1427 |
// TreeFormalParameterList constructorParameters = 0; |
| 1404 |
unsigned bodyStartColumn = 0; |
1428 |
failIfFalse((parseClassInfo(context, FunctionNeedsName, name, parentClass, constructor, instanceMethods, staticMethods)), "Cannot parse this class"); |
| 1405 |
failIfFalse((parseFunctionInfo(context, FunctionNeedsName, FunctionMode, true, name, parameters, body, openBraceOffset, closeBraceOffset, bodyStartLine, bodyStartColumn)), "Cannot parse this function"); |
1429 |
failIfFalse(name, "Class statements must have a name"); |
| 1406 |
failIfFalse(name, "Function statements must have a name"); |
1430 |
failIfFalse(declareVariable(name), "Cannot declare a class named '", name->impl(), "'"); |
| 1407 |
failIfFalseIfStrict(declareVariable(name), "Cannot declare a function named '", name->impl(), "' in strict mode"); |
1431 |
|
| 1408 |
return context.createFuncDeclStatement(location, name, body, parameters, openBraceOffset, closeBraceOffset, bodyStartLine, m_lastTokenEndPosition.line, bodyStartColumn, functionKeywordStart); |
1432 |
// FIXME: We should create a Miranda function here. |
|
|
1433 |
failIfFalse(constructor, "Cannot declare a class without constructor"); |
| 1434 |
|
| 1435 |
JSTextPosition classEnd = lastTokenEndPosition(); |
| 1436 |
|
| 1437 |
TreeExpression classDeclration = context.createAssignResolve(location, *name, constructor, classStart, classStart + 1, classEnd); |
| 1438 |
return context.createClassDeclStatement(location, *name, classDeclration, parentClass, instanceMethods, staticMethods, classStartLine, classEndLine); |
| 1439 |
|
| 1440 |
// return context.createFuncDeclStatement(location, name, constructor, constructorParameters, 0, 0, 0, 0, 0, 0); |
| 1441 |
// return context.createEmptyStatement(location); |
| 1442 |
} |
| 1443 |
|
| 1444 |
template <typename LexerType> |
| 1445 |
template <class TreeBuilder> bool Parser<LexerType>::parseClassInfo(TreeBuilder& context, FunctionRequirements requirements, const Identifier*& name, |
| 1446 |
TreeExpression& parentClass, TreeExpression& constructor, TreePropertyList& instanceMethods, TreePropertyList& staticMethods) |
| 1447 |
{ |
| 1448 |
AutoPopScopeRef classScope(this, pushScope()); |
| 1449 |
classScope->setStrictMode(); |
| 1450 |
|
| 1451 |
if (match(IDENT)) { |
| 1452 |
name = m_token.m_data.ident; |
| 1453 |
next(); |
| 1454 |
failIfFalse(classScope->declareVariable(name), "'", name->impl(), "' is not a valid class name"); |
| 1455 |
} else if (requirements == FunctionNeedsName) { |
| 1456 |
/* if (match(OPENBRACKET) || match(EXTENDS)) |
| 1457 |
semanticFail("class statements must have a name");*/ |
| 1458 |
semanticFailureDueToKeyword("class name"); |
| 1459 |
failDueToUnexpectedToken(); |
| 1460 |
return false; |
| 1461 |
} |
| 1462 |
|
| 1463 |
if (consume(EXTENDS)) { |
| 1464 |
parentClass = parsePrimaryExpression(context); |
| 1465 |
failIfFalse(parentClass, "Cannot parse the parent class name"); |
| 1466 |
} |
| 1467 |
|
| 1468 |
consumeOrFail(OPENBRACE, "Expected an opening '{' at the start of a class body"); |
| 1469 |
|
| 1470 |
TreePropertyList instanceMethodsTail = 0; |
| 1471 |
TreePropertyList staticMethodsTail = 0; |
| 1472 |
while (!match(CLOSEBRACE)) { |
| 1473 |
if (match(SEMICOLON)) |
| 1474 |
next(); |
| 1475 |
|
| 1476 |
bool isStaticMethod = match(STATICTOKEN); |
| 1477 |
if (isStaticMethod) |
| 1478 |
next(); |
| 1479 |
|
| 1480 |
// FIXME: Should be a binding identifier. |
| 1481 |
if (!match(IDENT)) { |
| 1482 |
failWithMessage("Expected an indentifier"); |
| 1483 |
break; |
| 1484 |
} |
| 1485 |
|
| 1486 |
JSTokenLocation methodLocation(tokenLocation()); |
| 1487 |
unsigned methodStart = tokenStart(); |
| 1488 |
ParserFunctionInfo<TreeBuilder> info; |
| 1489 |
failIfFalse((parseFunctionInfo(context, FunctionNeedsName, FunctionMode, false, info)), "Cannot parse this method"); |
| 1490 |
failIfFalse(info.name, "method must have a name"); |
| 1491 |
failIfFalse(declareVariable(info.name), "Cannot declare a method named '", info.name->impl(), "'"); |
| 1492 |
|
| 1493 |
bool isConstructor = !isStaticMethod && *info.name == m_vm->propertyNames->constructor; |
| 1494 |
if (isConstructor) |
| 1495 |
info.name = name; // FIXME: Is this correct?? |
| 1496 |
|
| 1497 |
TreeExpression method = context.createFunctionExpr(methodLocation, info, methodStart); |
| 1498 |
if (isConstructor) { |
| 1499 |
semanticFailIfTrue(constructor, "Cannot declrate multiple constructors in a single class"); |
| 1500 |
constructor = method; |
| 1501 |
} else { |
| 1502 |
// FIXME: Syntax error when super() is called |
| 1503 |
semanticFailIfTrue(*info.name == m_vm->propertyNames->prototype, "Cannot declrate a static method named '", info.name->impl(), "'"); |
| 1504 |
TreeProperty property = context.createProperty(info.name, method, PropertyNode::Constant, /* complete */ false); |
| 1505 |
|
| 1506 |
TreePropertyList& head = isStaticMethod ? staticMethods : instanceMethods; |
| 1507 |
TreePropertyList& tail = isStaticMethod ? staticMethodsTail : instanceMethodsTail; |
| 1508 |
|
| 1509 |
if (tail) |
| 1510 |
tail = context.createPropertyList(methodLocation, property, tail); |
| 1511 |
else { |
| 1512 |
head = context.createPropertyList(methodLocation, property); |
| 1513 |
tail = head; |
| 1514 |
} |
| 1515 |
} |
| 1516 |
} |
| 1517 |
|
| 1518 |
consumeOrFail(CLOSEBRACE, "Expected a closing '}' after a class body"); |
| 1519 |
|
| 1520 |
return true; |
| 1409 |
} |
1521 |
} |
| 1410 |
|
1522 |
|
| 1411 |
struct LabelInfo { |
1523 |
struct LabelInfo { |
|
Lines 1799-1811
template <class TreeBuilder> TreeProperty Parser<LexerType>::parseProperty(TreeB
a/Source/JavaScriptCore/parser/Parser.cpp_sec9
|
| 1799 |
return context.createProperty(ident, node, PropertyNode::Constant, complete); |
1911 |
return context.createProperty(ident, node, PropertyNode::Constant, complete); |
| 1800 |
} |
1912 |
} |
| 1801 |
failIfFalse(wasIdent, "Expected an identifier as property name"); |
1913 |
failIfFalse(wasIdent, "Expected an identifier as property name"); |
| 1802 |
const Identifier* accessorName = 0; |
|
|
| 1803 |
TreeFormalParameterList parameters = 0; |
| 1804 |
TreeFunctionBody body = 0; |
| 1805 |
unsigned openBraceOffset = 0; |
| 1806 |
unsigned closeBraceOffset = 0; |
| 1807 |
int bodyStartLine = 0; |
| 1808 |
unsigned bodyStartColumn = 0; |
| 1809 |
PropertyNode::Type type; |
1914 |
PropertyNode::Type type; |
| 1810 |
if (*ident == m_vm->propertyNames->get) |
1915 |
if (*ident == m_vm->propertyNames->get) |
| 1811 |
type = PropertyNode::Getter; |
1916 |
type = PropertyNode::Getter; |
|
Lines 1823-1838
template <class TreeBuilder> TreeProperty Parser<LexerType>::parseProperty(TreeB
a/Source/JavaScriptCore/parser/Parser.cpp_sec10
|
| 1823 |
failDueToUnexpectedToken(); |
1928 |
failDueToUnexpectedToken(); |
| 1824 |
JSTokenLocation location(tokenLocation()); |
1929 |
JSTokenLocation location(tokenLocation()); |
| 1825 |
next(); |
1930 |
next(); |
|
|
1931 |
ParserFunctionInfo<TreeBuilder> info; |
| 1826 |
if (type == PropertyNode::Getter) { |
1932 |
if (type == PropertyNode::Getter) { |
| 1827 |
failIfFalse(match(OPENPAREN), "Expected a parameter list for getter definition"); |
1933 |
failIfFalse(match(OPENPAREN), "Expected a parameter list for getter definition"); |
| 1828 |
failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, GetterMode, false, accessorName, parameters, body, openBraceOffset, closeBraceOffset, bodyStartLine, bodyStartColumn)), "Cannot parse getter definition"); |
1934 |
failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, GetterMode, false, info)), "Cannot parse getter definition"); |
| 1829 |
} else { |
1935 |
} else { |
| 1830 |
failIfFalse(match(OPENPAREN), "Expected a parameter list for setter definition"); |
1936 |
failIfFalse(match(OPENPAREN), "Expected a parameter list for setter definition"); |
| 1831 |
failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SetterMode, false, accessorName, parameters, body, openBraceOffset, closeBraceOffset, bodyStartLine, bodyStartColumn)), "Cannot parse setter definition"); |
1937 |
failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, SetterMode, false, info)), "Cannot parse setter definition"); |
| 1832 |
} |
1938 |
} |
| 1833 |
if (stringPropertyName) |
1939 |
if (stringPropertyName) |
| 1834 |
return context.createGetterOrSetterProperty(location, type, complete, stringPropertyName, parameters, body, openBraceOffset, closeBraceOffset, bodyStartLine, m_lastTokenEndPosition.line, bodyStartColumn, getterOrSetterStartOffset); |
1940 |
return context.createGetterOrSetterProperty(location, type, complete, stringPropertyName, info, getterOrSetterStartOffset); |
| 1835 |
return context.createGetterOrSetterProperty(const_cast<VM*>(m_vm), m_parserArena, location, type, complete, numericPropertyName, parameters, body, openBraceOffset, closeBraceOffset, bodyStartLine, m_lastTokenEndPosition.line, bodyStartColumn, getterOrSetterStartOffset); |
1941 |
return context.createGetterOrSetterProperty(const_cast<VM*>(m_vm), m_parserArena, location, type, complete, numericPropertyName, info, getterOrSetterStartOffset); |
| 1836 |
} |
1942 |
} |
| 1837 |
case NUMBER: { |
1943 |
case NUMBER: { |
| 1838 |
double propertyName = m_token.m_data.doubleValue; |
1944 |
double propertyName = m_token.m_data.doubleValue; |
|
Lines 2172-2191
template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpres
a/Source/JavaScriptCore/parser/Parser.cpp_sec11
|
| 2172 |
next(); |
2278 |
next(); |
| 2173 |
newCount++; |
2279 |
newCount++; |
| 2174 |
} |
2280 |
} |
| 2175 |
|
2281 |
|
|
|
2282 |
bool baseIsSuper = false; |
| 2176 |
if (match(FUNCTION)) { |
2283 |
if (match(FUNCTION)) { |
| 2177 |
const Identifier* name = &m_vm->propertyNames->nullIdentifier; |
|
|
| 2178 |
TreeFormalParameterList parameters = 0; |
| 2179 |
TreeFunctionBody body = 0; |
| 2180 |
unsigned openBraceOffset = 0; |
| 2181 |
unsigned closeBraceOffset = 0; |
| 2182 |
int bodyStartLine = 0; |
| 2183 |
unsigned bodyStartColumn = 0; |
| 2184 |
unsigned functionKeywordStart = tokenStart(); |
2284 |
unsigned functionKeywordStart = tokenStart(); |
| 2185 |
location = tokenLocation(); |
2285 |
location = tokenLocation(); |
| 2186 |
next(); |
2286 |
next(); |
| 2187 |
failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, FunctionMode, false, name, parameters, body, openBraceOffset, closeBraceOffset, bodyStartLine, bodyStartColumn)), "Cannot parse function expression"); |
2287 |
ParserFunctionInfo<TreeBuilder> info; |
| 2188 |
base = context.createFunctionExpr(location, name, body, parameters, openBraceOffset, closeBraceOffset, bodyStartLine, m_lastTokenEndPosition.line, bodyStartColumn, functionKeywordStart); |
2288 |
info.name = &m_vm->propertyNames->nullIdentifier; |
|
|
2289 |
failIfFalse((parseFunctionInfo(context, FunctionNoRequirements, FunctionMode, false, info)), "Cannot parse function expression"); |
| 2290 |
base = context.createFunctionExpr(location, info, functionKeywordStart); |
| 2291 |
} else if (match(SUPER)) { |
| 2292 |
base = context.superExpr(location); |
| 2293 |
baseIsSuper = true; |
| 2294 |
next(); |
| 2189 |
} else |
2295 |
} else |
| 2190 |
base = parsePrimaryExpression(context); |
2296 |
base = parsePrimaryExpression(context); |
| 2191 |
|
2297 |
|
|
Lines 2201-2206
template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpres
a/Source/JavaScriptCore/parser/Parser.cpp_sec12
|
| 2201 |
int initialAssignments = m_assignmentCount; |
2307 |
int initialAssignments = m_assignmentCount; |
| 2202 |
TreeExpression property = parseExpression(context); |
2308 |
TreeExpression property = parseExpression(context); |
| 2203 |
failIfFalse(property, "Cannot parse subscript expression"); |
2309 |
failIfFalse(property, "Cannot parse subscript expression"); |
|
|
2310 |
if (baseIsSuper) |
| 2311 |
failIfTrue(initialAssignments || m_assignmentCount, "Cannot assign a value to super"); |
| 2204 |
base = context.createBracketAccess(location, base, property, initialAssignments != m_assignmentCount, expressionStart, expressionEnd, tokenEndPosition()); |
2312 |
base = context.createBracketAccess(location, base, property, initialAssignments != m_assignmentCount, expressionStart, expressionEnd, tokenEndPosition()); |
| 2205 |
handleProductionOrFail(CLOSEBRACKET, "]", "end", "subscript expression"); |
2313 |
handleProductionOrFail(CLOSEBRACKET, "]", "end", "subscript expression"); |
| 2206 |
m_nonLHSCount = nonLHSCount; |
2314 |
m_nonLHSCount = nonLHSCount; |
|
Lines 2219-2224
template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpres
a/Source/JavaScriptCore/parser/Parser.cpp_sec13
|
| 2219 |
JSTextPosition expressionEnd = lastTokenEndPosition(); |
2327 |
JSTextPosition expressionEnd = lastTokenEndPosition(); |
| 2220 |
TreeArguments arguments = parseArguments(context, AllowSpread); |
2328 |
TreeArguments arguments = parseArguments(context, AllowSpread); |
| 2221 |
failIfFalse(arguments, "Cannot parse call arguments"); |
2329 |
failIfFalse(arguments, "Cannot parse call arguments"); |
|
|
2330 |
// FIXME: if baseIsSuper: failIfFalse(isConstructor, "Cannot call super() in this function"). |
| 2222 |
base = context.makeFunctionCallNode(location, base, arguments, expressionStart, expressionEnd, lastTokenEndPosition()); |
2331 |
base = context.makeFunctionCallNode(location, base, arguments, expressionStart, expressionEnd, lastTokenEndPosition()); |
| 2223 |
} |
2332 |
} |
| 2224 |
m_nonLHSCount = nonLHSCount; |
2333 |
m_nonLHSCount = nonLHSCount; |
|
Lines 2236-2243
template <class TreeBuilder> TreeExpression Parser<LexerType>::parseMemberExpres
a/Source/JavaScriptCore/parser/Parser.cpp_sec14
|
| 2236 |
default: |
2345 |
default: |
| 2237 |
goto endMemberExpression; |
2346 |
goto endMemberExpression; |
| 2238 |
} |
2347 |
} |
|
|
2348 |
baseIsSuper = false; |
| 2239 |
} |
2349 |
} |
| 2240 |
endMemberExpression: |
2350 |
endMemberExpression: |
|
|
2351 |
// failIfTrue(baseIsSuper && !newCount, "Cannot reference super"); |
| 2241 |
while (newCount--) |
2352 |
while (newCount--) |
| 2242 |
base = context.createNewExpr(location, base, expressionStart, lastTokenEndPosition()); |
2353 |
base = context.createNewExpr(location, base, expressionStart, lastTokenEndPosition()); |
| 2243 |
return base; |
2354 |
return base; |