Revision: 20434
Author: [email protected]
Date: Wed Apr 2 12:38:01 2014 UTC
Log: Make stray 'return' an early error
As required by the spec, and implemented by other browsers.
(Plus minor clean-up for redeclaration TypeErrors.)
[email protected]
BUG=
LOG=Y
Review URL: https://codereview.chromium.org/220473014
http://code.google.com/p/v8/source/detail?r=20434
Modified:
/branches/bleeding_edge/src/messages.js
/branches/bleeding_edge/src/parser.cc
/branches/bleeding_edge/src/parser.h
/branches/bleeding_edge/src/preparser.cc
/branches/bleeding_edge/src/preparser.h
/branches/bleeding_edge/src/runtime.cc
/branches/bleeding_edge/test/cctest/test-parsing.cc
/branches/bleeding_edge/test/mjsunit/debug-stepout-scope-part2.js
/branches/bleeding_edge/test/mjsunit/debug-stepout-scope-part3.js
/branches/bleeding_edge/test/mjsunit/debug-stepout-scope-part4.js
/branches/bleeding_edge/test/mjsunit/debug-stepout-scope-part5.js
/branches/bleeding_edge/test/mjsunit/debug-stepout-scope-part6.js
/branches/bleeding_edge/test/mjsunit/delay-syntax-error.js
/branches/bleeding_edge/test/webkit/fast/js/arguments-expected.txt
=======================================
--- /branches/bleeding_edge/src/messages.js Wed Apr 2 08:21:37 2014 UTC
+++ /branches/bleeding_edge/src/messages.js Wed Apr 2 12:38:01 2014 UTC
@@ -47,7 +47,8 @@
incompatible_method_receiver: ["Method ", "%0", " called on
incompatible receiver ", "%1"],
multiple_defaults_in_switch: ["More than one default clause in switch
statement"],
newline_after_throw: ["Illegal newline after throw"],
- redeclaration: ["%0", " '", "%1", "' has already been
declared"],
+ label_redeclaration: ["Label '", "%0", "' has already been
declared"],
+ var_redeclaration: ["Identifier '", "%0", "' has already
been declared"],
no_catch_or_finally: ["Missing catch or finally after try"],
unknown_label: ["Undefined label '", "%0", "'"],
uncaught_exception: ["Uncaught ", "%0"],
=======================================
--- /branches/bleeding_edge/src/parser.cc Wed Apr 2 11:03:05 2014 UTC
+++ /branches/bleeding_edge/src/parser.cc Wed Apr 2 12:38:01 2014 UTC
@@ -590,8 +590,7 @@
}
-Expression* ParserTraits::NewThrowReferenceError(
- const char* message, int pos) {
+Expression* ParserTraits::NewThrowReferenceError(const char* message, int
pos) {
return NewThrowError(
parser_->isolate()->factory()->MakeReferenceError_string(),
message, HandleVector<Object>(NULL, 0), pos);
@@ -609,11 +608,9 @@
Expression* ParserTraits::NewThrowTypeError(
- const char* message, Handle<Object> arg1, Handle<Object> arg2, int
pos) {
- ASSERT(!arg1.is_null() && !arg2.is_null());
- Handle<Object> elements[] = { arg1, arg2 };
- Vector< Handle<Object> > arguments =
- HandleVector<Object>(elements, ARRAY_SIZE(elements));
+ const char* message, Handle<Object> arg, int pos) {
+ int argc = arg.is_null() ? 0 : 1;
+ Vector< Handle<Object> > arguments = HandleVector<Object>(&arg, argc);
return NewThrowError(
parser_->isolate()->factory()->MakeTypeError_string(),
message, arguments, pos);
@@ -1754,18 +1751,14 @@
// In harmony we treat re-declarations as early errors. See
// ES5 16 for a definition of early errors.
SmartArrayPointer<char> c_string = name->ToCString(DISALLOW_NULLS);
- const char* elms[2] = { "Variable", c_string.get() };
- Vector<const char*> args(elms, 2);
- ReportMessage("redeclaration", args);
+ const char* elms[1] = { c_string.get() };
+ Vector<const char*> args(elms, 1);
+ ReportMessage("var_redeclaration", args);
*ok = false;
return;
}
- Handle<String> message_string =
- isolate()->factory()->InternalizeOneByteString(
- STATIC_ASCII_VECTOR("Variable"));
- Expression* expression =
- NewThrowTypeError("redeclaration",
- message_string, name, declaration->position());
+ Expression* expression = NewThrowTypeError(
+ "var_redeclaration", name, declaration->position());
declaration_scope->SetIllegalRedeclaration(expression);
}
}
@@ -2374,9 +2367,9 @@
// make later anyway so we should go back and fix this then.
if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) {
SmartArrayPointer<char> c_string = label->ToCString(DISALLOW_NULLS);
- const char* elms[2] = { "Label", c_string.get() };
- Vector<const char*> args(elms, 2);
- ReportMessage("redeclaration", args);
+ const char* elms[1] = { c_string.get() };
+ Vector<const char*> args(elms, 1);
+ ReportMessage("label_redeclaration", args);
*ok = false;
return NULL;
}
@@ -2521,7 +2514,7 @@
// reporting any errors on it, because of the way errors are
// reported (underlining).
Expect(Token::RETURN, CHECK_OK);
- int pos = position();
+ Scanner::Location loc = scanner()->location();
Token::Value tok = peek();
Statement* result;
@@ -2539,23 +2532,17 @@
Expression* generator = factory()->NewVariableProxy(
function_state_->generator_object_variable());
Expression* yield = factory()->NewYield(
- generator, return_value, Yield::FINAL, pos);
- result = factory()->NewExpressionStatement(yield, pos);
+ generator, return_value, Yield::FINAL, loc.beg_pos);
+ result = factory()->NewExpressionStatement(yield, loc.beg_pos);
} else {
- result = factory()->NewReturnStatement(return_value, pos);
+ result = factory()->NewReturnStatement(return_value, loc.beg_pos);
}
- // An ECMAScript program is considered syntactically incorrect if it
- // contains a return statement that is not within the body of a
- // function. See ECMA-262, section 12.9, page 67.
- //
- // To be consistent with KJS we report the syntax error at runtime.
- Scope* declaration_scope = scope_->DeclarationScope();
- if (declaration_scope->is_global_scope() ||
- declaration_scope->is_eval_scope()) {
- Expression* throw_error =
- NewThrowSyntaxError("illegal_return", Handle<Object>::null(), pos);
- return factory()->NewExpressionStatement(throw_error, pos);
+ Scope* decl_scope = scope_->DeclarationScope();
+ if (decl_scope->is_global_scope() || decl_scope->is_eval_scope()) {
+ ReportMessageAt(loc, "illegal_return");
+ *ok = false;
+ return NULL;
}
return result;
}
@@ -3669,13 +3656,13 @@
// errors. See ES5 16 for a definition of early errors.
Handle<String> name = decl->proxy()->name();
SmartArrayPointer<char> c_string = name->ToCString(DISALLOW_NULLS);
- const char* elms[2] = { "Variable", c_string.get() };
- Vector<const char*> args(elms, 2);
+ const char* elms[1] = { c_string.get() };
+ Vector<const char*> args(elms, 1);
int position = decl->proxy()->position();
Scanner::Location location = position == RelocInfo::kNoPosition
? Scanner::Location::invalid()
: Scanner::Location(position, position + 1);
- ParserTraits::ReportMessageAt(location, "redeclaration", args);
+ ParserTraits::ReportMessageAt(location, "var_redeclaration", args);
*ok = false;
}
}
=======================================
--- /branches/bleeding_edge/src/parser.h Wed Apr 2 11:03:05 2014 UTC
+++ /branches/bleeding_edge/src/parser.h Wed Apr 2 12:38:01 2014 UTC
@@ -538,8 +538,7 @@
// Generate AST node that throws a TypeError with the given
// type. Both arguments must be non-null (in the handle sense).
- Expression* NewThrowTypeError(
- const char* type, Handle<Object> arg1, Handle<Object> arg2, int pos);
+ Expression* NewThrowTypeError(const char* type, Handle<Object> arg, int
pos);
// Generic AST generator for throwing errors from compiled code.
Expression* NewThrowError(
=======================================
--- /branches/bleeding_edge/src/preparser.cc Wed Apr 2 11:03:05 2014 UTC
+++ /branches/bleeding_edge/src/preparser.cc Wed Apr 2 12:38:01 2014 UTC
@@ -582,7 +582,7 @@
// ReturnStatement ::
// 'return' [no line terminator] Expression? ';'
- // Consume the return token. It is necessary to do the before
+ // Consume the return token. It is necessary to do before
// reporting any errors on it, because of the way errors are
// reported (underlining).
Expect(Token::RETURN, CHECK_OK);
=======================================
--- /branches/bleeding_edge/src/preparser.h Wed Apr 2 11:03:05 2014 UTC
+++ /branches/bleeding_edge/src/preparser.h Wed Apr 2 12:38:01 2014 UTC
@@ -922,7 +922,7 @@
return PreParserExpression::Default();
}
PreParserExpression NewThrowTypeError(
- const char* type, Handle<Object> arg1, Handle<Object> arg2, int pos)
{
+ const char* type, Handle<Object> arg, int pos) {
return PreParserExpression::Default();
}
=======================================
--- /branches/bleeding_edge/src/runtime.cc Tue Apr 1 17:43:20 2014 UTC
+++ /branches/bleeding_edge/src/runtime.cc Wed Apr 2 12:38:01 2014 UTC
@@ -2117,15 +2117,11 @@
}
-static Failure* ThrowRedeclarationError(Isolate* isolate,
- const char* type,
- Handle<String> name) {
+static Failure* ThrowRedeclarationError(Isolate* isolate, Handle<String>
name) {
HandleScope scope(isolate);
- Handle<Object> type_handle =
- isolate->factory()->NewStringFromAscii(CStrVector(type));
- Handle<Object> args[2] = { type_handle, name };
- Handle<Object> error =
- isolate->factory()->NewTypeError("redeclaration", HandleVector(args,
2));
+ Handle<Object> args[1] = { name };
+ Handle<Object> error = isolate->factory()->NewTypeError(
+ "var_redeclaration", HandleVector(args, 1));
return isolate->Throw(*error);
}
@@ -2202,7 +2198,7 @@
if (lookup.IsFound() && lookup.IsDontDelete()) {
if (lookup.IsReadOnly() || lookup.IsDontEnum() ||
lookup.IsPropertyCallbacks()) {
- return ThrowRedeclarationError(isolate, "function", name);
+ return ThrowRedeclarationError(isolate, name);
}
// If the existing property is not configurable, keep its
attributes.
attr = lookup.GetAttributes();
@@ -2254,8 +2250,7 @@
if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) {
// Functions are not read-only.
ASSERT(mode != READ_ONLY || initial_value->IsTheHole());
- const char* type = ((attributes & READ_ONLY) != 0) ? "const" : "var";
- return ThrowRedeclarationError(isolate, type, name);
+ return ThrowRedeclarationError(isolate, name);
}
// Initialize it if necessary.
@@ -2309,7 +2304,7 @@
LookupResult lookup(isolate);
object->Lookup(*name, &lookup);
if (lookup.IsPropertyCallbacks()) {
- return ThrowRedeclarationError(isolate, "const", name);
+ return ThrowRedeclarationError(isolate, name);
}
}
if (object->IsJSGlobalObject()) {
=======================================
--- /branches/bleeding_edge/test/cctest/test-parsing.cc Wed Apr 2 11:03:05
2014 UTC
+++ /branches/bleeding_edge/test/cctest/test-parsing.cc Wed Apr 2 12:38:01
2014 UTC
@@ -1480,9 +1480,10 @@
"break",
"break label",
"break\nlabel",
- "return",
- "return 12",
- "return\n12",
+ // TODO(marja): activate once parsing 'return' is merged into
ParserBase.
+ // "return",
+ // "return 12",
+ // "return\n12",
"with ({}) ;",
"with ({}) {}",
"with ({}) 12",
=======================================
--- /branches/bleeding_edge/test/mjsunit/debug-stepout-scope-part2.js Mon
Sep 24 11:18:29 2012 UTC
+++ /branches/bleeding_edge/test/mjsunit/debug-stepout-scope-part2.js Wed
Apr 2 12:38:01 2014 UTC
@@ -54,7 +54,7 @@
var q = 42;
var prefixes = [ "debugger; ",
- "if (false) { try { throw 0; } catch(x) { return x; } };
debugger; " ];
+ "if (false) { try { throw 0; } catch(x) { this.x = x; }
}; debugger; " ];
var bodies = [ "1",
"1 ",
"1;",
=======================================
--- /branches/bleeding_edge/test/mjsunit/debug-stepout-scope-part3.js Mon
Sep 24 11:18:29 2012 UTC
+++ /branches/bleeding_edge/test/mjsunit/debug-stepout-scope-part3.js Wed
Apr 2 12:38:01 2014 UTC
@@ -55,7 +55,7 @@
var q = 42;
var prefixes = [
"debugger; ",
- "if (false) { try { throw 0; } catch(x) { return x; } }; debugger; " ];
+ "if (false) { try { throw 0; } catch(x) { this.x = x; } }; debugger; "
];
var with_bodies = [ "with ({}) {}",
"with ({x:1}) x",
"with ({x:1}) x = 1",
=======================================
--- /branches/bleeding_edge/test/mjsunit/debug-stepout-scope-part4.js Mon
Sep 24 11:18:29 2012 UTC
+++ /branches/bleeding_edge/test/mjsunit/debug-stepout-scope-part4.js Wed
Apr 2 12:38:01 2014 UTC
@@ -55,7 +55,7 @@
var q = 42;
var prefixes = [
"debugger; ",
- "if (false) { try { throw 0; } catch(x) { return x; } }; debugger; " ];
+ "if (false) { try { throw 0; } catch(x) { this.x = x; } }; debugger; " ];
var bodies = [ "1",
"1 ",
"1;",
=======================================
--- /branches/bleeding_edge/test/mjsunit/debug-stepout-scope-part5.js Mon
Sep 24 11:18:29 2012 UTC
+++ /branches/bleeding_edge/test/mjsunit/debug-stepout-scope-part5.js Wed
Apr 2 12:38:01 2014 UTC
@@ -54,7 +54,7 @@
var q = 42;
var prefixes = [ "debugger; ",
- "if (false) { try { throw 0; } catch(x) { return x; } };
debugger; " ];
+ "if (false) { try { throw 0; } catch(x) { this.x = x; }
}; debugger; " ];
var with_bodies = [ "with ({}) {}",
"with ({x:1}) x",
"with ({x:1}) x = 1",
=======================================
--- /branches/bleeding_edge/test/mjsunit/debug-stepout-scope-part6.js Mon
Sep 24 11:18:29 2012 UTC
+++ /branches/bleeding_edge/test/mjsunit/debug-stepout-scope-part6.js Wed
Apr 2 12:38:01 2014 UTC
@@ -54,7 +54,7 @@
var q = 42;
var prefixes = [ "debugger; ",
- "if (false) { try { throw 0; } catch(x) { return x; } };
debugger; " ];
+ "if (false) { try { throw 0; } catch(x) { this.x = x; }
}; debugger; " ];
var bodies = [ "1",
"1 ",
"1;",
=======================================
--- /branches/bleeding_edge/test/mjsunit/delay-syntax-error.js Mon Jan 17
09:36:10 2011 UTC
+++ /branches/bleeding_edge/test/mjsunit/delay-syntax-error.js Wed Apr 2
12:38:01 2014 UTC
@@ -25,18 +25,11 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// To be compatible with JSC syntax errors for illegal returns should be
delayed
-// to runtime.
-// Invalid continue and break statements are caught at compile time.
-
-// Do not throw syntax errors for illegal return at compile time.
-assertDoesNotThrow("if (false) return;");
-
-// Throw syntax errors for illegal break and continue at compile time.
+// Throw syntax errors for illegal return, break and continue at compile
time.
+assertThrows("if (false) return;");
assertThrows("if (false) break;");
assertThrows("if (false) continue;");
-// Throw syntax errors for illegal return, break and continue at runtime.
assertThrows("return;");
assertThrows("break;");
assertThrows("continue;");
=======================================
--- /branches/bleeding_edge/test/webkit/fast/js/arguments-expected.txt Thu
Jul 25 19:54:24 2013 UTC
+++ /branches/bleeding_edge/test/webkit/fast/js/arguments-expected.txt Wed
Apr 2 12:38:01 2014 UTC
@@ -157,7 +157,7 @@
PASS argumentsParam(true) is true
PASS argumentsFunctionConstructorParam(true) is true
PASS argumentsVarUndefined() is '[object Arguments]'
-FAIL argumentsConstUndefined() should be [object Arguments]. Threw
exception TypeError: Variable 'arguments' has already been declared
+FAIL argumentsConstUndefined() should be [object Arguments]. Threw
exception TypeError: Identifier 'arguments' has already been declared
PASS argumentCalleeInException() is argumentCalleeInException
PASS shadowedArgumentsApply([true]) is true
PASS shadowedArgumentsLength([]) is 0
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.