Strict mode octal literals.
git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6446 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
e01336c3dc
commit
8d79f3a788
@ -216,6 +216,7 @@ function FormatMessage(message) {
|
||||
strict_param_dupe: "Strict mode function may not have duplicate parameter names",
|
||||
strict_var_name: "Variable name may not be eval or arguments in strict mode",
|
||||
strict_function_name: "Function name may not be eval or arguments in strict mode",
|
||||
strict_octal_literal: "Octal literals are not allowed in strict mode.",
|
||||
};
|
||||
}
|
||||
var format = kMessages[message.type];
|
||||
|
@ -664,7 +664,11 @@ FunctionLiteral* Parser::DoParseProgram(Handle<String> source,
|
||||
TemporaryScope temp_scope(&this->temp_scope_);
|
||||
ZoneList<Statement*>* body = new ZoneList<Statement*>(16);
|
||||
bool ok = true;
|
||||
int beg_loc = scanner().location().beg_pos;
|
||||
ParseSourceElements(body, Token::EOS, &ok);
|
||||
if (ok && temp_scope_->StrictMode()) {
|
||||
CheckOctalLiteral(beg_loc, scanner().location().end_pos, &ok);
|
||||
}
|
||||
if (ok) {
|
||||
result = new FunctionLiteral(
|
||||
no_name,
|
||||
@ -3384,7 +3388,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
|
||||
*ok = false;
|
||||
return NULL;
|
||||
}
|
||||
// TODO(mmaly): Check for octal escape sequence here.
|
||||
CheckOctalLiteral(start_pos, end_pos, CHECK_OK);
|
||||
}
|
||||
|
||||
FunctionLiteral* function_literal =
|
||||
@ -3530,6 +3534,18 @@ Handle<String> Parser::ParseIdentifierName(bool* ok) {
|
||||
return GetSymbol(ok);
|
||||
}
|
||||
|
||||
// Checks whether octal literal last seen is between beg_pos and end_pos.
|
||||
// If so, reports an error.
|
||||
void Parser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
|
||||
int octal = scanner().octal_position();
|
||||
if (beg_pos <= octal && octal <= end_pos) {
|
||||
ReportMessageAt(Scanner::Location(octal, octal + 1), "strict_octal_literal",
|
||||
Vector<const char*>::empty());
|
||||
scanner().clear_octal_position();
|
||||
*ok = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This function reads an identifier and determines whether or not it
|
||||
// is 'get' or 'set'. The reason for not using ParseIdentifier and
|
||||
|
@ -613,6 +613,9 @@ class Parser {
|
||||
bool* is_set,
|
||||
bool* ok);
|
||||
|
||||
// Strict mode octal literal validation.
|
||||
void CheckOctalLiteral(int beg_pos, int end_pos, bool* ok);
|
||||
|
||||
// Parser support
|
||||
VariableProxy* Declare(Handle<String> name, Variable::Mode mode,
|
||||
FunctionLiteral* fun,
|
||||
|
@ -64,7 +64,8 @@ bool ScannerConstants::IsIdentifier(unibrow::CharacterStream* buffer) {
|
||||
// ----------------------------------------------------------------------------
|
||||
// Scanner
|
||||
|
||||
Scanner::Scanner() { }
|
||||
Scanner::Scanner()
|
||||
: octal_pos_(kNoOctalLocation) { }
|
||||
|
||||
|
||||
uc32 Scanner::ScanHexEscape(uc32 c, int length) {
|
||||
@ -98,6 +99,7 @@ uc32 Scanner::ScanHexEscape(uc32 c, int length) {
|
||||
// Octal escapes of the forms '\0xx' and '\xxx' are not a part of
|
||||
// ECMA-262. Other JS VMs support them.
|
||||
uc32 Scanner::ScanOctalEscape(uc32 c, int length) {
|
||||
octal_pos_ = source_pos() - 1; // Already advanced
|
||||
uc32 x = c - '0';
|
||||
for (int i = 0; i < length; i++) {
|
||||
int d = c0_ - '0';
|
||||
@ -601,7 +603,11 @@ Token::Value JavaScriptScanner::ScanNumber(bool seen_period) {
|
||||
kind = DECIMAL;
|
||||
break;
|
||||
}
|
||||
if (c0_ < '0' || '7' < c0_) break;
|
||||
if (c0_ < '0' || '7' < c0_) {
|
||||
// Octal literal finished.
|
||||
octal_pos_ = next_.location.beg_pos;
|
||||
break;
|
||||
}
|
||||
AddLiteralCharAdvance();
|
||||
}
|
||||
}
|
||||
|
@ -247,6 +247,9 @@ class LiteralBuffer {
|
||||
// Generic functionality used by both JSON and JavaScript scanners.
|
||||
class Scanner {
|
||||
public:
|
||||
// -1 is outside of the range of any real source code.
|
||||
static const int kNoOctalLocation = -1;
|
||||
|
||||
typedef unibrow::Utf8InputBuffer<1024> Utf8Decoder;
|
||||
|
||||
class LiteralScope {
|
||||
@ -280,6 +283,10 @@ class Scanner {
|
||||
Location location() const { return current_.location; }
|
||||
Location peek_location() const { return next_.location; }
|
||||
|
||||
// Returns the location of the last seen octal literal
|
||||
int octal_position() const { return octal_pos_; }
|
||||
void clear_octal_position() { octal_pos_ = -1; }
|
||||
|
||||
// Returns the literal string, if any, for the current token (the
|
||||
// token returned by Next()). The string is 0-terminated and in
|
||||
// UTF-8 format; they may contain 0-characters. Literal strings are
|
||||
@ -410,6 +417,8 @@ class Scanner {
|
||||
// Input stream. Must be initialized to an UC16CharacterStream.
|
||||
UC16CharacterStream* source_;
|
||||
|
||||
// Start position of the octal literal last scanned.
|
||||
int octal_pos_;
|
||||
|
||||
// One Unicode character look-ahead; c0_ < 0 at the end of the input.
|
||||
uc32 c0_;
|
||||
|
@ -115,3 +115,17 @@ function NotStrict(eval) {
|
||||
}
|
||||
with ({}) {};
|
||||
}
|
||||
|
||||
// Octal literal
|
||||
CheckStrictMode("var x = 012");
|
||||
CheckStrictMode("012");
|
||||
CheckStrictMode("'Hello octal\\032'");
|
||||
CheckStrictMode("function octal() { return 012; }");
|
||||
CheckStrictMode("function octal() { return '\\032'; }");
|
||||
|
||||
// Octal before "use strict"
|
||||
assertThrows('\
|
||||
function strict() {\
|
||||
"octal\\032directive";\
|
||||
"use strict";\
|
||||
}', SyntaxError);
|
||||
|
Loading…
Reference in New Issue
Block a user