Strict mode detection in preparser.

Handle octal escapes in everything but RegExps.
Extend preparser test suite to test whether the preparser reports
exceptions to throw.

TEST=preparser/*

Review URL: http://codereview.chromium.org/6927075

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7804 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
lrn@chromium.org 2011-05-06 11:41:15 +00:00
parent cf19179266
commit 1a169aa3f0
26 changed files with 800 additions and 109 deletions

View File

@ -66,7 +66,8 @@
namespace v8 {
// The result of preparsing is either a stack overflow error, or an opaque
// blob of data that can be passed back into the parser.
class V8EXPORT PreParserData {
public:
PreParserData(size_t size, const uint8_t* data)

View File

@ -28,16 +28,29 @@
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include "../include/v8stdint.h"
#include "../include/v8-preparser.h"
#include "../src/preparse-data-format.h"
namespace i = v8::internal;
// This file is only used for testing the stand-alone preparser
// library.
// The first (and only) argument must be the path of a JavaScript file.
// This file is preparsed and the resulting preparser data is written
// to stdout. Diagnostic output is output on stderr.
// The file must contain only ASCII characters (UTF-8 isn't supported).
// The first argument must be the path of a JavaScript source file.
// Optionally this can be followed by the word "throws" (case sensitive),
// which signals that the parsing is expected to throw - the default is
// to expect the parsing to not throw.
// The command line can further be followed by a message text (the
// *type* of the exception to throw), and even more optionally, the
// start and end position reported with the exception.
//
// This source file is preparsed and tested against the expectations, and if
// successful, the resulting preparser data is written to stdout.
// Diagnostic output is output on stderr.
// The source file must contain only ASCII characters (UTF-8 isn't supported).
// The file is read into memory, so it should have a reasonable size.
@ -97,6 +110,69 @@ bool WriteBuffer(FILE* dest, const void* buffer, size_t length) {
}
class PreparseDataInterpreter {
public:
PreparseDataInterpreter(const uint8_t* data, int length)
: data_(data), length_(length), message_(NULL) { }
~PreparseDataInterpreter() {
if (message_ != NULL) delete[] message_;
}
bool valid() {
int header_length =
i::PreparseDataConstants::kHeaderSize * sizeof(int); // NOLINT
return length_ >= header_length;
}
bool throws() {
return valid() &&
word(i::PreparseDataConstants::kHasErrorOffset) != 0;
}
const char* message() {
if (message_ != NULL) return message_;
if (!throws()) return NULL;
int text_pos = i::PreparseDataConstants::kHeaderSize +
i::PreparseDataConstants::kMessageTextPos;
int length = word(text_pos);
char* buffer = new char[length + 1];
for (int i = 1; i <= length; i++) {
int character = word(text_pos + i);
buffer[i - 1] = character;
}
buffer[length] = '\0';
message_ = buffer;
return buffer;
}
int beg_pos() {
if (!throws()) return -1;
return word(i::PreparseDataConstants::kHeaderSize +
i::PreparseDataConstants::kMessageStartPos);
}
int end_pos() {
if (!throws()) return -1;
return word(i::PreparseDataConstants::kHeaderSize +
i::PreparseDataConstants::kMessageEndPos);
}
private:
int word(int offset) {
const int* word_data = reinterpret_cast<const int*>(data_);
if (word_data + offset < reinterpret_cast<const int*>(data_ + length_)) {
return word_data[offset];
}
return -1;
}
const uint8_t* const data_;
const int length_;
const char* message_;
};
template <typename T>
class ScopedPointer {
public:
@ -109,15 +185,93 @@ class ScopedPointer {
};
void fail(v8::PreParserData* data, const char* message, ...) {
va_list args;
va_start(args, message);
vfprintf(stderr, message, args);
va_end(args);
fflush(stderr);
// Print preparser data to stdout.
uint32_t size = data->size();
fprintf(stderr, "LOG: data size: %u\n", size);
if (!WriteBuffer(stdout, data->data(), size)) {
perror("ERROR: Writing data");
fflush(stderr);
}
exit(EXIT_FAILURE);
};
void CheckException(v8::PreParserData* data,
bool throws,
const char* message,
int beg_pos,
int end_pos) {
PreparseDataInterpreter reader(data->data(), data->size());
if (throws) {
if (!reader.throws()) {
if (message == NULL) {
fail(data, "Didn't throw as expected\n");
} else {
fail(data, "Didn't throw \"%s\" as expected\n", message);
}
}
if (message != NULL) {
const char* actual_message = reader.message();
if (strcmp(message, actual_message)) {
fail(data, "Wrong error message. Expected <%s>, found <%s>\n",
message, actual_message);
}
}
if (beg_pos >= 0) {
if (beg_pos != reader.beg_pos()) {
fail(data, "Wrong error start position: Expected %i, found %i\n",
beg_pos, reader.beg_pos());
}
}
if (end_pos >= 0) {
if (end_pos != reader.end_pos()) {
fail(data, "Wrong error end position: Expected %i, found %i\n",
end_pos, reader.end_pos());
}
}
} else if (reader.throws()) {
const char* message = reader.message();
fail(data, "Throws unexpectedly with message: %s\n",
message);
}
}
int main(int argc, char* argv[]) {
// Check for filename argument.
if (argc < 2) {
fprintf(stderr, "ERROR: No filename on command line.\n");
fflush(stderr);
return EXIT_FAILURE;
fail(NULL, "ERROR: No filename on command line.\n");
}
const char* filename = argv[1];
// Parse expectations.
bool throws = false;
const char* throws_message = NULL;
int throws_beg_pos = -1;
int throws_end_pos = -1;
// Check for throws argument.
if (argc > 2) {
if (strncmp("throws", argv[2], 6)) {
fail(NULL, "ERROR: Extra arguments not prefixed by \"throws\".\n");
}
throws = true;
if (argc > 3) {
throws_message = argv[3];
}
if (argc > 4) {
throws_beg_pos = atoi(argv[4]);
}
if (argc > 5) {
throws_end_pos = atoi(argv[5]);
}
}
// Open JS file.
FILE* input = fopen(filename, "rb");
if (input == NULL) {
@ -151,19 +305,13 @@ int main(int argc, char* argv[]) {
// Fail if stack overflow.
if (data.stack_overflow()) {
fprintf(stderr, "ERROR: Stack overflow\n");
fflush(stderr);
return EXIT_FAILURE;
fail(&data, "ERROR: Stack overflow\n");
}
// Print preparser data to stdout.
uint32_t size = data.size();
fprintf(stderr, "LOG: Success, data size: %u\n", size);
fflush(stderr);
if (!WriteBuffer(stdout, data.data(), size)) {
perror("ERROR: Writing data");
return EXIT_FAILURE;
}
// Check that the expected exception is thrown, if an exception is
// expected.
CheckException(&data, throws, throws_message,
throws_beg_pos, throws_end_pos);
return EXIT_SUCCESS;
}

View File

@ -3543,9 +3543,9 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
// '(' (Identifier)*[','] ')'
Expect(Token::LPAREN, CHECK_OK);
start_pos = scanner().location().beg_pos;
Scanner::Location name_loc = Scanner::NoLocation();
Scanner::Location dupe_loc = Scanner::NoLocation();
Scanner::Location reserved_loc = Scanner::NoLocation();
Scanner::Location name_loc = Scanner::Location::invalid();
Scanner::Location dupe_loc = Scanner::Location::invalid();
Scanner::Location reserved_loc = Scanner::Location::invalid();
bool done = (peek() == Token::RPAREN);
while (!done) {
@ -3864,12 +3864,14 @@ void Parser::CheckStrictModeLValue(Expression* expression,
}
// Checks whether octal literal last seen is between beg_pos and end_pos.
// If so, reports an error.
// Checks whether an octal literal was last seen between beg_pos and end_pos.
// If so, reports an error. Only called for strict mode.
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",
Scanner::Location octal = scanner().octal_position();
if (octal.IsValid() &&
beg_pos <= octal.beg_pos &&
octal.end_pos <= end_pos) {
ReportMessageAt(octal, "strict_octal_literal",
Vector<const char*>::empty());
scanner().clear_octal_position();
*ok = false;

View File

@ -32,6 +32,7 @@
#include "ast.h"
#include "scanner.h"
#include "scopes.h"
#include "preparse-data-format.h"
#include "preparse-data.h"
namespace v8 {

View File

@ -0,0 +1,62 @@
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef V8_PREPARSE_DATA_FORMAT_H_
#define V8_PREPARSE_DATA_FORMAT_H_
namespace v8 {
namespace internal {
// Generic and general data used by preparse data recorders and readers.
struct PreparseDataConstants {
public:
// Layout and constants of the preparse data exchange format.
static const unsigned kMagicNumber = 0xBadDead;
static const unsigned kCurrentVersion = 6;
static const int kMagicOffset = 0;
static const int kVersionOffset = 1;
static const int kHasErrorOffset = 2;
static const int kFunctionsSizeOffset = 3;
static const int kSymbolCountOffset = 4;
static const int kSizeOffset = 5;
static const int kHeaderSize = 6;
// If encoding a message, the following positions are fixed.
static const int kMessageStartPos = 0;
static const int kMessageEndPos = 1;
static const int kMessageArgCountPos = 2;
static const int kMessageTextPos = 3;
static const unsigned char kNumberTerminator = 0x80u;
};
} } // namespace v8::internal.
#endif // V8_PREPARSE_DATA_FORMAT_H_

View File

@ -27,6 +27,7 @@
#include "../include/v8stdint.h"
#include "preparse-data-format.h"
#include "preparse-data.h"
#include "checks.h"

View File

@ -25,8 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef V8_PREPARSER_DATA_H_
#define V8_PREPARSER_DATA_H_
#ifndef V8_PREPARSE_DATA_H_
#define V8_PREPARSE_DATA_H_
#include "allocation.h"
#include "hashmap.h"
@ -35,32 +35,6 @@
namespace v8 {
namespace internal {
// Generic and general data used by preparse data recorders and readers.
class PreparseDataConstants : public AllStatic {
public:
// Layout and constants of the preparse data exchange format.
static const unsigned kMagicNumber = 0xBadDead;
static const unsigned kCurrentVersion = 6;
static const int kMagicOffset = 0;
static const int kVersionOffset = 1;
static const int kHasErrorOffset = 2;
static const int kFunctionsSizeOffset = 3;
static const int kSymbolCountOffset = 4;
static const int kSizeOffset = 5;
static const int kHeaderSize = 6;
// If encoding a message, the following positions are fixed.
static const int kMessageStartPos = 0;
static const int kMessageEndPos = 1;
static const int kMessageArgCountPos = 2;
static const int kMessageTextPos = 3;
static const byte kNumberTerminator = 0x80u;
};
// ----------------------------------------------------------------------------
// ParserRecorder - Logging of preparser data.
@ -248,4 +222,4 @@ class CompleteParserRecorder: public FunctionLoggingParserRecorder {
} } // namespace v8::internal.
#endif // V8_PREPARSER_DATA_H_
#endif // V8_PREPARSE_DATA_H_

View File

@ -33,6 +33,7 @@
#include "utils.h"
#include "list.h"
#include "scanner-base.h"
#include "preparse-data-format.h"
#include "preparse-data.h"
#include "preparser.h"

View File

@ -34,6 +34,7 @@
#include "list.h"
#include "scanner-base.h"
#include "preparse-data-format.h"
#include "preparse-data.h"
#include "preparser.h"
@ -94,13 +95,33 @@ void PreParser::ReportUnexpectedToken(i::Token::Value token) {
}
// Checks whether octal literal last seen is between beg_pos and end_pos.
// If so, reports an error.
void PreParser::CheckOctalLiteral(int beg_pos, int end_pos, bool* ok) {
i::Scanner::Location octal = scanner_->octal_position();
if (beg_pos <= octal.beg_pos && octal.end_pos <= end_pos) {
ReportMessageAt(octal.beg_pos, octal.end_pos, "strict_octal_literal", NULL);
scanner_->clear_octal_position();
*ok = false;
}
}
PreParser::SourceElements PreParser::ParseSourceElements(int end_token,
bool* ok) {
// SourceElements ::
// (Statement)* <end_token>
bool allow_directive_prologue = true;
while (peek() != end_token) {
ParseStatement(CHECK_OK);
Statement statement = ParseStatement(CHECK_OK);
if (allow_directive_prologue) {
if (statement == kUseStrictExpressionStatement) {
set_strict_mode();
} else if (statement != kStringLiteralExpressionStatement) {
allow_directive_prologue = false;
}
}
}
return kUnknownSourceElements;
}
@ -299,10 +320,17 @@ PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(
Expression expr = ParseExpression(true, CHECK_OK);
if (peek() == i::Token::COLON && expr == kIdentifierExpression) {
Consume(i::Token::COLON);
return ParseStatement(ok);
ParseStatement(ok);
return kUnknownStatement;
}
// Parsed expression statement.
ExpectSemicolon(CHECK_OK);
if (expr == kStringLiteralExpression) {
return kStringLiteralExpressionStatement;
}
if (expr == kUseStrictString) {
return kUseStrictExpressionStatement;
}
return kUnknownStatement;
}
@ -1057,10 +1085,10 @@ PreParser::Expression PreParser::ParseFunctionLiteral(bool* ok) {
ScopeType outer_scope_type = scope_->type();
bool inside_with = scope_->IsInsideWith();
Scope function_scope(&scope_, kFunctionScope);
// FormalParameterList ::
// '(' (Identifier)*[','] ')'
Expect(i::Token::LPAREN, CHECK_OK);
int start_position = scanner_->location().beg_pos;
bool done = (peek() == i::Token::RPAREN);
while (!done) {
ParseIdentifier(CHECK_OK);
@ -1099,6 +1127,12 @@ PreParser::Expression PreParser::ParseFunctionLiteral(bool* ok) {
ParseSourceElements(i::Token::RBRACE, CHECK_OK);
Expect(i::Token::RBRACE, CHECK_OK);
}
if (scope_->is_strict()) {
int end_position = scanner_->location().end_pos;
CheckOctalLiteral(start_position, end_position, CHECK_OK);
}
return kUnknownExpression;
}
@ -1149,8 +1183,17 @@ PreParser::Identifier PreParser::GetIdentifierSymbol() {
PreParser::Expression PreParser::GetStringSymbol() {
const int kUseStrictLength = 10;
const char* kUseStrictChars = "use strict";
LogSymbol();
return kUnknownExpression;
if (scanner_->is_literal_ascii() &&
scanner_->literal_length() == kUseStrictLength &&
!scanner_->literal_contains_escapes() &&
!strncmp(scanner_->literal_ascii_string().start(), kUseStrictChars,
kUseStrictLength)) {
return kUseStrictString;
}
return kStringLiteralExpression;
}

View File

@ -33,7 +33,7 @@ namespace preparser {
// Preparsing checks a JavaScript program and emits preparse-data that helps
// a later parsing to be faster.
// See preparse-data.h for the data.
// See preparse-data-format.h for the data format.
// The PreParser checks that the syntax follows the grammar for JavaScript,
// and collects some information about the program along the way.
@ -80,14 +80,18 @@ class PreParser {
// simple this-property assignments.
enum StatementType {
kUnknownStatement
kUnknownStatement,
kStringLiteralExpressionStatement,
kUseStrictExpressionStatement
};
enum ExpressionType {
kUnknownExpression,
kIdentifierExpression, // Used to detect labels.
kThisExpression,
kThisPropertyExpression
kThisPropertyExpression,
kStringLiteralExpression,
kUseStrictString
};
enum IdentifierType {
@ -95,7 +99,9 @@ class PreParser {
};
enum SourceElementTypes {
kUnknownSourceElements
kUnknownSourceElements,
kDirectivePrologue,
kUseStrictDirective
};
typedef int SourceElements;
@ -112,7 +118,8 @@ class PreParser {
type_(type),
materialized_literal_count_(0),
expected_properties_(0),
with_nesting_count_(0) {
with_nesting_count_(0),
strict_((prev_ != NULL) && prev_->is_strict()) {
*variable = this;
}
~Scope() { *variable_ = prev_; }
@ -122,6 +129,8 @@ class PreParser {
int expected_properties() { return expected_properties_; }
int materialized_literal_count() { return materialized_literal_count_; }
bool IsInsideWith() { return with_nesting_count_ != 0; }
bool is_strict() { return strict_; }
void set_strict() { strict_ = true; }
void EnterWith() { with_nesting_count_++; }
void LeaveWith() { with_nesting_count_--; }
@ -132,6 +141,7 @@ class PreParser {
int materialized_literal_count_;
int expected_properties_;
int with_nesting_count_;
bool strict_;
};
// Private constructor only used in PreParseProgram.
@ -152,10 +162,13 @@ class PreParser {
PreParseResult PreParse() {
Scope top_scope(&scope_, kTopLevelScope);
bool ok = true;
int start_position = scanner_->peek_location().beg_pos;
ParseSourceElements(i::Token::EOS, &ok);
if (stack_overflow_) return kPreParseStackOverflow;
if (!ok) {
ReportUnexpectedToken(scanner_->current_token());
} else if (scope_->is_strict()) {
CheckOctalLiteral(start_position, scanner_->location().end_pos, &ok);
}
return kPreParseSuccess;
}
@ -169,6 +182,8 @@ class PreParser {
log_->LogMessage(start_pos, end_pos, type, name_opt);
}
void CheckOctalLiteral(int beg_pos, int end_pos, bool* ok);
// All ParseXXX functions take as the last argument an *ok parameter
// which is set to false if parsing failed; it is unchanged otherwise.
// By making the 'exception handling' explicit, we are forced to check
@ -245,6 +260,12 @@ class PreParser {
bool peek_any_identifier();
void set_strict_mode() {
scope_->set_strict();
}
bool is_strict_mode() { return scope_->is_strict(); }
void Consume(i::Token::Value token) { Next(); }
void Expect(i::Token::Value token, bool* ok) {

View File

@ -38,8 +38,7 @@ namespace internal {
// Scanner
Scanner::Scanner(UnicodeCache* unicode_cache)
: unicode_cache_(unicode_cache),
octal_pos_(kNoOctalLocation) { }
: unicode_cache_(unicode_cache) { }
uc32 Scanner::ScanHexEscape(uc32 c, int length) {
@ -70,34 +69,12 @@ 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) {
uc32 x = c - '0';
int i = 0;
for (; i < length; i++) {
int d = c0_ - '0';
if (d < 0 || d > 7) break;
int nx = x * 8 + d;
if (nx >= 256) break;
x = nx;
Advance();
}
// Anything excelt '\0' is an octal escape sequence, illegal in strict mode.
// Remember the position of octal escape sequences so that better error
// can be reported later (in strict mode).
if (c != '0' || i > 0) {
octal_pos_ = source_pos() - i - 1; // Already advanced
}
return x;
}
// ----------------------------------------------------------------------------
// JavaScriptScanner
JavaScriptScanner::JavaScriptScanner(UnicodeCache* scanner_contants)
: Scanner(scanner_contants) { }
: Scanner(scanner_contants), octal_pos_(Location::invalid()) { }
Token::Value JavaScriptScanner::Next() {
@ -518,6 +495,31 @@ void JavaScriptScanner::ScanEscape() {
}
// Octal escapes of the forms '\0xx' and '\xxx' are not a part of
// ECMA-262. Other JS VMs support them.
uc32 JavaScriptScanner::ScanOctalEscape(uc32 c, int length) {
uc32 x = c - '0';
int i = 0;
for (; i < length; i++) {
int d = c0_ - '0';
if (d < 0 || d > 7) break;
int nx = x * 8 + d;
if (nx >= 256) break;
x = nx;
Advance();
}
// Anything except '\0' is an octal escape sequence, illegal in strict mode.
// Remember the position of octal escape sequences so that an error
// can be reported later (in strict mode).
// We don't report the error immediately, because the octal escape can
// occur before the "use strict" directive.
if (c != '0' || i > 0) {
octal_pos_ = Location(source_pos() - i - 1, source_pos() - 1);
}
return x;
}
Token::Value JavaScriptScanner::ScanString() {
uc32 quote = c0_;
Advance(); // consume quote
@ -586,7 +588,7 @@ Token::Value JavaScriptScanner::ScanNumber(bool seen_period) {
}
if (c0_ < '0' || '7' < c0_) {
// Octal literal finished.
octal_pos_ = next_.location.beg_pos;
octal_pos_ = next_.location;
break;
}
AddLiteralCharAdvance();
@ -729,6 +731,9 @@ bool JavaScriptScanner::ScanRegExpPattern(bool seen_equal) {
// worrying whether the following characters are part of the escape
// or not, since any '/', '\\' or '[' is guaranteed to not be part
// of the escape sequence.
// TODO(896): At some point, parse RegExps more throughly to capture
// octal esacpes in strict mode.
} else { // Unescaped character.
if (c0_ == '[') in_character_class = true;
if (c0_ == ']') in_character_class = false;

View File

@ -286,23 +286,17 @@ class Scanner {
return beg_pos >= 0 && end_pos >= beg_pos;
}
static Location invalid() { return Location(-1, -1); }
int beg_pos;
int end_pos;
};
static Location NoLocation() {
return Location(-1, -1);
}
// Returns the location information for the current token
// (the token returned by Next()).
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
@ -326,6 +320,16 @@ class Scanner {
return current_.literal_chars->length();
}
bool literal_contains_escapes() const {
Location location = current_.location;
int source_length = (location.end_pos - location.beg_pos);
if (current_.token == Token::STRING) {
// Subtract delimiters.
source_length -= 2;
}
return current_.literal_chars->length() != source_length;
}
// Returns the literal string for the next token (the token that
// would be returned if Next() were called).
bool is_next_literal_ascii() {
@ -417,9 +421,6 @@ class Scanner {
uc32 ScanHexEscape(uc32 c, int length);
// Scans octal escape sequence. Also accepts "\0" decimal escape sequence.
uc32 ScanOctalEscape(uc32 c, int length);
// Return the current source position.
int source_pos() {
return source_->pos() - kCharacterLookaheadBufferSize;
@ -437,9 +438,6 @@ 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_;
};
@ -492,6 +490,13 @@ class JavaScriptScanner : public Scanner {
// Used for checking if a property name is an identifier.
static bool IsIdentifier(unibrow::CharacterStream* buffer);
// Scans octal escape sequence. Also accepts "\0" decimal escape sequence.
uc32 ScanOctalEscape(uc32 c, int length);
// Returns the location of the last seen octal literal
Location octal_position() const { return octal_pos_; }
void clear_octal_position() { octal_pos_ = Location::invalid(); }
// Seek forward to the given position. This operation does not
// work in general, for instance when there are pushed back
// characters, but works for seeking forward until simple delimiter
@ -521,6 +526,9 @@ class JavaScriptScanner : public Scanner {
// If the escape sequence cannot be decoded the result is kBadChar.
uc32 ScanIdentifierUnicodeEscape();
// Start position of the octal literal last scanned.
Location octal_pos_;
bool has_line_terminator_before_next_;
};

View File

@ -0,0 +1,35 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// A string looking like "use strict", but with a hex escape in it,
// doesn't trigger strict mode.
function foo() {
"use\x20strict";
var x = "hello\040world";
return x;
}

View File

@ -0,0 +1,35 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// A string looking like "use strict", but with an octal escape in it,
// doesn't trigger strict mode.
function foo() {
"use\040strict";
var x = "hello\040world";
return x;
}

View File

@ -0,0 +1,35 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// A string looking like "use strict", but with a long hex escape in it,
// doesn't trigger strict mode.
function foo() {
"use\u0020strict";
var x = "hello\040world";
return x;
}

View File

@ -0,0 +1,12 @@
# Expectations for preparser tests.
# Only mentions tests that throw SyntaxError, and optionally specifies
# the message and location expected in the exception.
# Format:
# testname[:message[:beg_pos,end_pos]]
strict-octal-string:strict_octal_literal
strict-octal-regexp:strict_octal_literal
strict-octal-directive-before:strict_octal_literal
strict-octal-directive-after:strict_octal_literal
strict-octal-use-strict-after:strict_octal_literal
strict-octal-use-strict-before:strict_octal_literal

View File

@ -0,0 +1,39 @@
# Copyright 2011 the V8 project authors. All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
prefix preparser
# We don't parse RegExps at scanning time, so we can't fail on octal
# escapes (we need to parse to distinguish octal escapes from valid
# back-references).
strict-octal-regexp: FAIL
##############################################################################
[ $arch == mips ]
# Skip all tests on MIPS.
*: SKIP

View File

@ -0,0 +1,35 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Strict mode with octal escape in string/directive prologue after
// "use strict" directive.
function foo() {
"use strict";
"use hello\040world";
return true;
}

View File

@ -0,0 +1,35 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Strict mode with octal escape in string/directive prologue prior to
// "use strict" directive.
function foo() {
"use hello\040world";
"use strict";
return true;
}

View File

@ -0,0 +1,34 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Strict mode with call to RegExp containing octal escape:
function foo() {
"use strict";
var re = RegExp("Hello\\040World");
return re;
}

View File

@ -0,0 +1,34 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Strict mode with octal escape in RegExp literal.
function foo() {
"use strict";
var re = /hello\040world/;
return re;
}

View File

@ -0,0 +1,34 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Strict mode with octal escape in string literal.
function foo() {
"use strict";
var x = "hello\040world";
return x;
}

View File

@ -0,0 +1,35 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Strict mode with octal escape in string/directive prologue looking like
// "use strict", after "use strict" directive.
function foo() {
"use strict";
"use\040strict";
return true;
}

View File

@ -0,0 +1,35 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Strict mode with octal escape in string/directive prologue looking like
// "use strict, before "use strict" directive.
function foo() {
"use\040strict";
"use strict";
return true;
}

View File

@ -30,14 +30,15 @@ import os
from os.path import join, dirname, exists
import platform
import utils
import re
class PreparserTestCase(test.TestCase):
def __init__(self, root, path, executable, mode, context):
def __init__(self, root, path, executable, mode, throws, context):
super(PreparserTestCase, self).__init__(context, path, mode)
self.executable = executable
self.root = root
self.throws = throws
def GetLabel(self):
return "%s %s %s" % (self.mode, self.path[-2], self.path[-1])
@ -48,6 +49,8 @@ class PreparserTestCase(test.TestCase):
def BuildCommand(self, path):
testfile = join(self.root, self.GetName()) + ".js"
result = [self.executable, testfile]
if (self.throws):
result += ['throws'] + self.throws
return result
def GetCommand(self):
@ -65,19 +68,41 @@ class PreparserTestConfiguration(test.TestConfiguration):
def GetBuildRequirements(self):
return ['preparser']
def GetExpectations(self):
expects_file = join(self.root, 'preparser.expectation')
map = {}
if exists(expects_file):
rule_regex = re.compile("^([\w\-]+)(?::([\w\-]+))?(?::(\d+),(\d+))?$")
for line in utils.ReadLinesFrom(expects_file):
if (line[0] == '#'): continue
rule_match = rule_regex.match(line)
if rule_match:
expects = []
if (rule_match.group(2)):
expects = expects + [rule_match.group(2)]
if (rule_match.group(3)):
expects = expects + [rule_match.group(3), rule_match.group(4)]
map[rule_match.group(1)] = expects
return map;
def ListTests(self, current_path, path, mode, variant_flags):
executable = join('obj', 'preparser', mode, 'preparser')
if utils.IsWindows():
executable += '.exe'
executable = join(self.context.buildspace, executable)
expectations = self.GetExpectations()
# Find all .js files in tests/preparser directory.
filenames = [f[:-3] for f in os.listdir(self.root) if f.endswith(".js")]
filenames.sort()
result = []
for file in filenames:
throws = None;
if (file in expectations):
throws = expectations[file]
result.append(PreparserTestCase(self.root,
current_path + [file], executable,
mode, self.context))
mode, throws, self.context))
return result
def GetTestStatus(self, sections, defs):

View File

@ -526,6 +526,7 @@
'../../src/platform-tls-win32.h',
'../../src/platform-tls.h',
'../../src/platform.h',
'../../src/preparse-data-format.h',
'../../src/preparse-data.cc',
'../../src/preparse-data.h',
'../../src/preparser.cc',
@ -591,7 +592,7 @@
'../../src/unicode-inl.h',
'../../src/unicode.cc',
'../../src/unicode.h',
'../../src/utils-inl.h',
'../../src/utils-inl.h',
'../../src/utils.cc',
'../../src/utils.h',
'../../src/v8-counters.cc',