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:
parent
cf19179266
commit
1a169aa3f0
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "ast.h"
|
||||
#include "scanner.h"
|
||||
#include "scopes.h"
|
||||
#include "preparse-data-format.h"
|
||||
#include "preparse-data.h"
|
||||
|
||||
namespace v8 {
|
||||
|
62
src/preparse-data-format.h
Normal file
62
src/preparse-data-format.h
Normal 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_
|
@ -27,6 +27,7 @@
|
||||
|
||||
#include "../include/v8stdint.h"
|
||||
|
||||
#include "preparse-data-format.h"
|
||||
#include "preparse-data.h"
|
||||
|
||||
#include "checks.h"
|
||||
|
@ -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_
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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_;
|
||||
};
|
||||
|
||||
|
35
test/preparser/non-use-strict-hex-escape.js
Normal file
35
test/preparser/non-use-strict-hex-escape.js
Normal 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;
|
||||
}
|
35
test/preparser/non-use-strict-octal-escape.js
Normal file
35
test/preparser/non-use-strict-octal-escape.js
Normal 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;
|
||||
}
|
35
test/preparser/non-use-strict-uhex-escape.js
Normal file
35
test/preparser/non-use-strict-uhex-escape.js
Normal 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;
|
||||
}
|
12
test/preparser/preparser.expectation
Normal file
12
test/preparser/preparser.expectation
Normal 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
|
39
test/preparser/preparser.status
Normal file
39
test/preparser/preparser.status
Normal 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
|
35
test/preparser/strict-octal-directive-after.js
Normal file
35
test/preparser/strict-octal-directive-after.js
Normal 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;
|
||||
}
|
35
test/preparser/strict-octal-directive-before.js
Normal file
35
test/preparser/strict-octal-directive-before.js
Normal 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;
|
||||
}
|
34
test/preparser/strict-octal-indirect-regexp.js
Normal file
34
test/preparser/strict-octal-indirect-regexp.js
Normal 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;
|
||||
}
|
34
test/preparser/strict-octal-regexp.js
Normal file
34
test/preparser/strict-octal-regexp.js
Normal 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;
|
||||
}
|
34
test/preparser/strict-octal-string.js
Normal file
34
test/preparser/strict-octal-string.js
Normal 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;
|
||||
}
|
35
test/preparser/strict-octal-use-strict-after.js
Normal file
35
test/preparser/strict-octal-use-strict-after.js
Normal 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;
|
||||
}
|
35
test/preparser/strict-octal-use-strict-before.js
Normal file
35
test/preparser/strict-octal-use-strict-before.js
Normal 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;
|
||||
}
|
@ -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):
|
||||
|
@ -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',
|
||||
|
Loading…
Reference in New Issue
Block a user