Version 3.4.5.1.
Patch revisions r8348 and r8351 to trunk.
Review URL: http://codereview.chromium.org/7215015
git-svn-id: http://v8.googlecode.com/svn/trunk@8353 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/objects.cc b/src/objects.cc
index 1e67169..6c9f52b 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -3107,7 +3107,7 @@
FixedArray* parameter_map = FixedArray::cast(elements());
uint32_t length = parameter_map->length();
Object* probe =
- (index + 2) < length ? parameter_map->get(index + 2) : NULL;
+ index < (length - 2) ? parameter_map->get(index + 2) : NULL;
if (probe != NULL && !probe->IsTheHole()) {
// TODO(kmillikin): We could check if this was the last aliased
// parameter, and revert to normal elements in that case. That
@@ -3554,7 +3554,7 @@
FixedArray* parameter_map = FixedArray::cast(elements());
uint32_t length = parameter_map->length();
Object* probe =
- (index + 2) < length ? parameter_map->get(index + 2) : NULL;
+ index < (length - 2) ? parameter_map->get(index + 2) : NULL;
if (probe == NULL || probe->IsTheHole()) {
FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
if (arguments->IsDictionary()) {
@@ -3652,7 +3652,7 @@
// would allow GC of the context.
FixedArray* parameter_map = FixedArray::cast(elements());
uint32_t length = parameter_map->length();
- if (index + 2 < length) {
+ if (index < length - 2) {
parameter_map->set(index + 2, GetHeap()->the_hole_value());
}
parameter_map->set(1, dictionary);
@@ -7902,7 +7902,7 @@
FixedArray* parameter_map = FixedArray::cast(elements());
uint32_t length = parameter_map->length();
Object* probe =
- (index + 2) < length ? parameter_map->get(index + 2) : NULL;
+ index < (length - 2) ? parameter_map->get(index + 2) : NULL;
if (probe != NULL && !probe->IsTheHole()) return FAST_ELEMENT;
// If not aliased, check the arguments.
FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
@@ -8007,7 +8007,7 @@
FixedArray* parameter_map = FixedArray::cast(elements());
uint32_t length = parameter_map->length();
Object* probe =
- (index + 2 < length) ? parameter_map->get(index + 2) : NULL;
+ (index < length - 2) ? parameter_map->get(index + 2) : NULL;
if (probe != NULL && !probe->IsTheHole()) return true;
// Not a mapped parameter, check the arguments.
@@ -8549,7 +8549,7 @@
FixedArray* parameter_map = FixedArray::cast(elements());
uint32_t length = parameter_map->length();
Object* probe =
- (index + 2 < length) ? parameter_map->get(index + 2) : NULL;
+ (index < length - 2) ? parameter_map->get(index + 2) : NULL;
if (probe != NULL && !probe->IsTheHole()) {
Context* context = Context::cast(parameter_map->get(0));
int context_index = Smi::cast(probe)->value();
@@ -8763,7 +8763,7 @@
FixedArray* parameter_map = FixedArray::cast(elements());
uint32_t length = parameter_map->length();
Object* probe =
- (index + 2 < length) ? parameter_map->get(index + 2) : NULL;
+ (index < length - 2) ? parameter_map->get(index + 2) : NULL;
if (probe != NULL && !probe->IsTheHole()) {
Context* context = Context::cast(parameter_map->get(0));
int context_index = Smi::cast(probe)->value();
diff --git a/src/parser.cc b/src/parser.cc
index 3348391..8a2258f 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -1776,7 +1776,7 @@
// no line-terminator between the two words.
if (extension_ != NULL &&
peek() == Token::FUNCTION &&
- !scanner().has_line_terminator_before_next() &&
+ !scanner().HasAnyLineTerminatorBeforeNext() &&
expr != NULL &&
expr->AsVariableProxy() != NULL &&
expr->AsVariableProxy()->name()->Equals(
@@ -1818,7 +1818,7 @@
Expect(Token::CONTINUE, CHECK_OK);
Handle<String> label = Handle<String>::null();
Token::Value tok = peek();
- if (!scanner().has_line_terminator_before_next() &&
+ if (!scanner().HasAnyLineTerminatorBeforeNext() &&
tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
label = ParseIdentifier(CHECK_OK);
}
@@ -1848,7 +1848,7 @@
Expect(Token::BREAK, CHECK_OK);
Handle<String> label;
Token::Value tok = peek();
- if (!scanner().has_line_terminator_before_next() &&
+ if (!scanner().HasAnyLineTerminatorBeforeNext() &&
tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
label = ParseIdentifier(CHECK_OK);
}
@@ -1897,7 +1897,7 @@
}
Token::Value tok = peek();
- if (scanner().has_line_terminator_before_next() ||
+ if (scanner().HasAnyLineTerminatorBeforeNext() ||
tok == Token::SEMICOLON ||
tok == Token::RBRACE ||
tok == Token::EOS) {
@@ -2032,7 +2032,7 @@
Expect(Token::THROW, CHECK_OK);
int pos = scanner().location().beg_pos;
- if (scanner().has_line_terminator_before_next()) {
+ if (scanner().HasAnyLineTerminatorBeforeNext()) {
ReportMessage("newline_after_throw", Vector<const char*>::empty());
*ok = false;
return NULL;
@@ -2619,7 +2619,7 @@
// LeftHandSideExpression ('++' | '--')?
Expression* expression = ParseLeftHandSideExpression(CHECK_OK);
- if (!scanner().has_line_terminator_before_next() &&
+ if (!scanner().HasAnyLineTerminatorBeforeNext() &&
Token::IsCountOp(peek())) {
// Signal a reference error if the expression is an invalid
// left-hand side expression. We could report this as a syntax
@@ -3818,7 +3818,7 @@
Next();
return;
}
- if (scanner().has_line_terminator_before_next() ||
+ if (scanner().HasAnyLineTerminatorBeforeNext() ||
tok == Token::RBRACE ||
tok == Token::EOS) {
return;
diff --git a/src/preparser-api.cc b/src/preparser-api.cc
index a0d13ed..1a7402f 100644
--- a/src/preparser-api.cc
+++ b/src/preparser-api.cc
@@ -169,6 +169,7 @@
// Skip initial whitespace allowing HTML comment ends just like
// after a newline and scan first token.
has_line_terminator_before_next_ = true;
+ has_multiline_comment_before_next_ = false;
SkipWhiteSpace();
Scan();
}
diff --git a/src/preparser.cc b/src/preparser.cc
index 818f02a..7553430 100644
--- a/src/preparser.cc
+++ b/src/preparser.cc
@@ -383,7 +383,7 @@
Expect(i::Token::CONTINUE, CHECK_OK);
i::Token::Value tok = peek();
- if (!scanner_->has_line_terminator_before_next() &&
+ if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
tok != i::Token::SEMICOLON &&
tok != i::Token::RBRACE &&
tok != i::Token::EOS) {
@@ -400,7 +400,7 @@
Expect(i::Token::BREAK, CHECK_OK);
i::Token::Value tok = peek();
- if (!scanner_->has_line_terminator_before_next() &&
+ if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
tok != i::Token::SEMICOLON &&
tok != i::Token::RBRACE &&
tok != i::Token::EOS) {
@@ -426,7 +426,7 @@
// This is not handled during preparsing.
i::Token::Value tok = peek();
- if (!scanner_->has_line_terminator_before_next() &&
+ if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
tok != i::Token::SEMICOLON &&
tok != i::Token::RBRACE &&
tok != i::Token::EOS) {
@@ -577,7 +577,7 @@
// 'throw' [no line terminator] Expression ';'
Expect(i::Token::THROW, CHECK_OK);
- if (scanner_->has_line_terminator_before_next()) {
+ if (scanner_->HasAnyLineTerminatorBeforeNext()) {
i::JavaScriptScanner::Location pos = scanner_->location();
ReportMessageAt(pos.beg_pos, pos.end_pos,
"newline_after_throw", NULL);
@@ -800,7 +800,7 @@
i::Scanner::Location before = scanner_->peek_location();
Expression expression = ParseLeftHandSideExpression(CHECK_OK);
- if (!scanner_->has_line_terminator_before_next() &&
+ if (!scanner_->HasAnyLineTerminatorBeforeNext() &&
i::Token::IsCountOp(peek())) {
if (strict_mode() && expression.IsIdentifier() &&
expression.AsIdentifier().IsEvalOrArguments()) {
@@ -1274,7 +1274,7 @@
Next();
return;
}
- if (scanner_->has_line_terminator_before_next() ||
+ if (scanner_->HasAnyLineTerminatorBeforeNext() ||
tok == i::Token::RBRACE ||
tok == i::Token::EOS) {
return;
diff --git a/src/scanner-base.cc b/src/scanner-base.cc
index 89591ba..a55f0f4 100644
--- a/src/scanner-base.cc
+++ b/src/scanner-base.cc
@@ -80,6 +80,7 @@
Token::Value JavaScriptScanner::Next() {
current_ = next_;
has_line_terminator_before_next_ = false;
+ has_multiline_comment_before_next_ = false;
Scan();
return current_.token;
}
@@ -163,7 +164,7 @@
if (unicode_cache_->IsLineTerminator(ch)) {
// Following ECMA-262, section 7.4, a comment containing
// a newline will make the comment count as a line-terminator.
- has_line_terminator_before_next_ = true;
+ has_multiline_comment_before_next_ = true;
}
// If we have reached the end of the multi-line comment, we
// consume the '/' and insert a whitespace. This way all
@@ -449,6 +450,7 @@
// of the end of a function (at the "}" token). It doesn't matter
// whether there was a line terminator in the part we skip.
has_line_terminator_before_next_ = false;
+ has_multiline_comment_before_next_ = false;
}
Scan();
}
diff --git a/src/scanner-base.h b/src/scanner-base.h
index 02566dd..cb279a6 100644
--- a/src/scanner-base.h
+++ b/src/scanner-base.h
@@ -474,9 +474,11 @@
// Returns the next token.
Token::Value Next();
- // Returns true if there was a line terminator before the peek'ed token.
- bool has_line_terminator_before_next() const {
- return has_line_terminator_before_next_;
+ // Returns true if there was a line terminator before the peek'ed token,
+ // possibly inside a multi-line comment.
+ bool HasAnyLineTerminatorBeforeNext() const {
+ return has_line_terminator_before_next_ ||
+ has_multiline_comment_before_next_;
}
// Scans the input as a regular expression pattern, previous
@@ -529,7 +531,13 @@
// Start position of the octal literal last scanned.
Location octal_pos_;
+ // Whether there is a line terminator whitespace character after
+ // the current token, and before the next. Does not count newlines
+ // inside multiline comments.
bool has_line_terminator_before_next_;
+ // Whether there is a multi-line comment that containins a
+ // line-terminator after the current token, and before the next.
+ bool has_multiline_comment_before_next_;
};
diff --git a/src/scanner.cc b/src/scanner.cc
index 21a0c2d..844db1b 100755
--- a/src/scanner.cc
+++ b/src/scanner.cc
@@ -337,6 +337,7 @@
// Skip initial whitespace allowing HTML comment ends just like
// after a newline and scan first token.
has_line_terminator_before_next_ = true;
+ has_multiline_comment_before_next_ = false;
SkipWhiteSpace();
Scan();
}
diff --git a/src/version.cc b/src/version.cc
index eecee41..3700910 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -35,7 +35,7 @@
#define MAJOR_VERSION 3
#define MINOR_VERSION 4
#define BUILD_NUMBER 5
-#define PATCH_LEVEL 0
+#define PATCH_LEVEL 1
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
#define IS_CANDIDATE_VERSION 0
diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc
index 08f117b..2b707fc 100755
--- a/test/cctest/test-parsing.cc
+++ b/test/cctest/test-parsing.cc
@@ -137,8 +137,9 @@
// Regression test. See:
// http://code.google.com/p/chromium/issues/detail?id=53548
// Tests that --> is correctly interpreted as comment-to-end-of-line if there
- // is only whitespace before it on the line, even after a multiline-comment
- // comment. This was not the case if it occurred before the first real token
+ // is only whitespace before it on the line (with comments considered as
+ // whitespace, even a multiline-comment containing a newline).
+ // This was not the case if it occurred before the first real token
// in the input.
const char* tests[] = {
// Before first real token.
@@ -152,6 +153,16 @@
NULL
};
+ const char* fail_tests[] = {
+ "x --> is eol-comment\nvar y = 37;\n",
+ "\"\\n\" --> is eol-comment\nvar y = 37;\n",
+ "x/* precomment */ --> is eol-comment\nvar y = 37;\n",
+ "x/* precomment\n */ --> is eol-comment\nvar y = 37;\n",
+ "var x = 42; --> is eol-comment\nvar y = 37;\n",
+ "var x = 42; /* precomment\n */ --> is eol-comment\nvar y = 37;\n",
+ NULL
+ };
+
// Parser/Scanner needs a stack limit.
int marker;
i::Isolate::Current()->stack_guard()->SetStackLimit(
@@ -163,6 +174,13 @@
CHECK(data != NULL && !data->HasError());
delete data;
}
+
+ for (int i = 0; fail_tests[i]; i++) {
+ v8::ScriptData* data =
+ v8::ScriptData::PreCompile(fail_tests[i], i::StrLength(fail_tests[i]));
+ CHECK(data == NULL || data->HasError());
+ delete data;
+ }
}
diff --git a/test/mjsunit/arguments.js b/test/mjsunit/arguments.js
index e38dcea..78b7722 100644
--- a/test/mjsunit/arguments.js
+++ b/test/mjsunit/arguments.js
@@ -180,3 +180,11 @@
assertArrayEquals([1, void 0], f1(3));
assertArrayEquals([2, 5, 5], f1(3, 5));
assertArrayEquals([3, 5, 5, 7], f1(3, 5, 7));
+
+// Check out of bounds behavior.
+function arg_get(x) { return arguments[x]; }
+function arg_del(x) { return delete arguments[x]; }
+function arg_set(x) { return (arguments[x] = 117); }
+assertEquals(undefined, arg_get(0xFFFFFFFF));
+assertEquals(true, arg_del(0xFFFFFFFF));
+assertEquals(117, arg_set(0xFFFFFFFF));
\ No newline at end of file