Reviewers: Mads Ager,

Description:
Make invalid break/continue statements an early syntax error.

Previously we delayed the throwing of syntax errors until runtime, so
unreachable errors didn't get reported.
To match a change in JSC, we now stop parsing and report the error immediately.

BUG=69736
TEST=

Please review this at http://codereview.chromium.org/6355006/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge/build-ia32

Affected files:
  M src/parser.h
  M src/parser.cc
  M test/mjsunit/delay-syntax-error.js
  M test/mjsunit/regress/regress-1036894.js
  M test/mjsunit/regress/regress-990205.js


Index: src/parser.cc
diff --git a/src/parser.cc b/src/parser.cc
index 3730a4577cf6f1e70440637b575f8547d96892a0..bf25e7311eda35a0692579c86b754ab804b3ac2c 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -788,6 +788,20 @@ void Parser::ReportMessageAt(Scanner::Location source_location,
 }


+void Parser::ReportMessageAt(Scanner::Location source_location,
+                             const char* type,
+                             Vector<Handle<String> > args) {
+  MessageLocation location(script_,
+ source_location.beg_pos, source_location.end_pos);
+  Handle<JSArray> array = Factory::NewJSArray(args.length());
+  for (int i = 0; i < args.length(); i++) {
+    SetElement(array, i, args[i]);
+  }
+  Handle<Object> result = Factory::NewSyntaxError(type, array);
+  Top::Throw(*result, &location);
+}
+
+
// Base class containing common code for the different finder classes used by
 // the parser.
 class ParserFinder {
@@ -1693,12 +1707,16 @@ Statement* Parser::ParseContinueStatement(bool* ok) {
   IterationStatement* target = NULL;
   target = LookupContinueTarget(label, CHECK_OK);
   if (target == NULL) {
-    // Illegal continue statement.  To be consistent with KJS we delay
-    // reporting of the syntax error until runtime.
-    Handle<String> error_type = Factory::illegal_continue_symbol();
-    if (!label.is_null()) error_type = Factory::unknown_label_symbol();
-    Expression* throw_error = NewThrowSyntaxError(error_type, label);
-    return new ExpressionStatement(throw_error);
+    // Illegal continue statement.
+    const char* message = "illegal_continue";
+    Vector<Handle<String> > args;
+    if (!label.is_null()) {
+      message = "unknown_label";
+      args = Vector<Handle<String> >(&label, 1);
+    }
+    ReportMessageAt(scanner().location(), message, args);
+    *ok = false;
+    return NULL;
   }
   ExpectSemicolon(CHECK_OK);
   return new ContinueStatement(target);
@@ -1724,12 +1742,16 @@ Statement* Parser::ParseBreakStatement(ZoneStringList* labels, bool* ok) {
   BreakableStatement* target = NULL;
   target = LookupBreakTarget(label, CHECK_OK);
   if (target == NULL) {
-    // Illegal break statement.  To be consistent with KJS we delay
-    // reporting of the syntax error until runtime.
-    Handle<String> error_type = Factory::illegal_break_symbol();
-    if (!label.is_null()) error_type = Factory::unknown_label_symbol();
-    Expression* throw_error = NewThrowSyntaxError(error_type, label);
-    return new ExpressionStatement(throw_error);
+    // Illegal break statement.
+    const char* message = "illegal_break";
+    Vector<Handle<String> > args;
+    if (!label.is_null()) {
+      message = "unknown_label";
+      args = Vector<Handle<String> >(&label, 1);
+    }
+    ReportMessageAt(scanner().location(), message, args);
+    *ok = false;
+    return NULL;
   }
   ExpectSemicolon(CHECK_OK);
   return new BreakStatement(target);
Index: src/parser.h
diff --git a/src/parser.h b/src/parser.h
index 460f6647facb6bc7680f3dcf28c8ca583b081527..0613a8de99c4aad758ebc825201515aa0f56ca43 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -430,6 +430,9 @@ class Parser {
   void ReportMessageAt(Scanner::Location loc,
                        const char* message,
                        Vector<const char*> args);
+  void ReportMessageAt(Scanner::Location loc,
+                       const char* message,
+                       Vector<Handle<String> > args);

  protected:
   FunctionLiteral* ParseLazy(Handle<SharedFunctionInfo> info,
Index: test/mjsunit/delay-syntax-error.js
diff --git a/test/mjsunit/delay-syntax-error.js b/test/mjsunit/delay-syntax-error.js index 4fcb1435c574c8d609a102b0d9ceaa955e6dae17..25ccd1ba61c94136c574a24c186f652256735fa5 100644
--- a/test/mjsunit/delay-syntax-error.js
+++ b/test/mjsunit/delay-syntax-error.js
@@ -27,15 +27,18 @@

 // To be compatible with KJS syntax errors for illegal return, break
 // and continue should be delayed to runtime.
+// CHANGED in Jan. 2011. JSC switched to reporting these syntax errors
+// early and we have followed.

-// Do not throw syntax errors for illegal return, break and continue
-// at compile time.
+// Do not throw syntax errors for illegal return at compile time.
 assertDoesNotThrow("if (false) return;");
-assertDoesNotThrow("if (false) break;");
-assertDoesNotThrow("if (false) continue;");
+
+// Do throw syntax errors for illegal break and continue at compile time.
+assertThrows("if (false) break;");
+assertThrows("if (false) continue;");

 // Throw syntax errors for illegal return, break and continue at
-// compile time.
+// runtime.
 assertThrows("return;");
 assertThrows("break;");
 assertThrows("continue;");
Index: test/mjsunit/regress/regress-1036894.js
diff --git a/test/mjsunit/regress/regress-1036894.js b/test/mjsunit/regress/regress-1036894.js index d89ceda11c0a291ca8a56f0cb0ab8e54e5d28af9..03ed8f9d61087f9fd5fdfb39fd9f037f88349c2b 100644
--- a/test/mjsunit/regress/regress-1036894.js
+++ b/test/mjsunit/regress/regress-1036894.js
@@ -25,14 +25,14 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

-xeval = function(s) { eval(s); }
-xeval("$=function anonymous() { /*noex*/do {} while(({ get x(x) { break ; }, set x() { (undefined);} })); }"); +assertThrows("$=function anonymous() { /*noex*/do {} while(({ get x(x) { break ; }, set x() { (undefined);} })); }");

-foo = function() { eval("$=function anonymous() { /*noex*/do {} while(({ get x(x) { break ; }, set x() { (undefined);} })); }"); }
+function foo() {
+ assertThrows("$=function anonymous() { /*noex*/do {} while(({ get x(x) { break ; }, set x() { (undefined);} })); }");
+}
 foo();

-xeval = function(s) { eval(s); }
-eval("$=function anonymous() { /*noex*/do {} while(({ get x(x) { break ; }, set x() { (undefined);} })); }"); +assertThrows("$=function anonymous() { /*noex*/do {} while(({ get x(x) { break ; }, set x() { (undefined);} })); }");

 xeval = function(s) { eval(s); }
 xeval('$=function(){L: {break L;break L;}};');
Index: test/mjsunit/regress/regress-990205.js
diff --git a/test/mjsunit/regress/regress-990205.js b/test/mjsunit/regress/regress-990205.js index 1ab5bf88b4252d475408e946808a557cfadbc90b..981e63f1b7e65c5c70875c696e739095ebd02d7c 100644
--- a/test/mjsunit/regress/regress-990205.js
+++ b/test/mjsunit/regress/regress-990205.js
@@ -25,11 +25,16 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+// We not throw syntax errors early for invalid break and continue
+// statements. The behavior has changed to make this a syntax error.
+// (Notice that the example isn't valid ECMAScript due to the
+// function declaration that is not at top level.)
+
 function f() {
   // Force eager compilation of x through the use of eval. The break
   // in function x should not try to break out of the enclosing while.
   return eval("while(0) function x() { break; }; 42");
 };

-assertEquals(42, f());
+assertThrows("f()");



--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to