Commit c3c185c1 authored by rossberg@chromium.org's avatar rossberg@chromium.org

Make invalid LHSs a parse-time (reference) error

This is required by the spec. It also prevents crashes resulting from the attempt to read type feedback for the RHS of an invalid assignment which full codegen never actually allocated info for.

To do: check properly in preparser already.

R=marja@chromium.org, mstarzinger@chromium.org
BUG=351658
LOG=Y

Review URL: https://codereview.chromium.org/200473003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19976 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent dbb7f982
......@@ -1854,13 +1854,9 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
void FullCodeGenerator::VisitAssignment(Assignment* expr) {
ASSERT(expr->target()->IsValidLeftHandSide());
Comment cmnt(masm_, "[ Assignment");
// Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
// on the left-hand side.
if (!expr->target()->IsValidLeftHandSide()) {
VisitForEffect(expr->target());
return;
}
// Left-hand side can only be a property, a global or a (parameter or local)
// slot.
......@@ -2099,12 +2095,7 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
void FullCodeGenerator::EmitAssignment(Expression* expr) {
// Invalid left-hand sides are rewritten to have a 'throw
// ReferenceError' on the left-hand side.
if (!expr->IsValidLeftHandSide()) {
VisitForEffect(expr);
return;
}
ASSERT(expr->IsValidLeftHandSide());
// Left-hand side can only be a property, a global or a (parameter or local)
// slot.
......@@ -3990,16 +3981,11 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
ASSERT(expr->expression()->IsValidLeftHandSide());
Comment cmnt(masm_, "[ CountOperation");
SetSourcePosition(expr->position());
// Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
// as the left-hand side.
if (!expr->expression()->IsValidLeftHandSide()) {
VisitForEffect(expr->expression());
return;
}
// Expression can only be a property, a global or a (parameter or local)
// slot.
enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
......
......@@ -1865,13 +1865,9 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
void FullCodeGenerator::VisitAssignment(Assignment* expr) {
ASSERT(expr->target()->IsValidLeftHandSide());
Comment cmnt(masm_, "[ Assignment");
// Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
// on the left-hand side.
if (!expr->target()->IsValidLeftHandSide()) {
VisitForEffect(expr->target());
return;
}
// Left-hand side can only be a property, a global or a (parameter or local)
// slot.
......@@ -2402,12 +2398,7 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
void FullCodeGenerator::EmitAssignment(Expression* expr) {
// Invalid left-hand sides are rewritten by the parser to have a 'throw
// ReferenceError' on the left-hand side.
if (!expr->IsValidLeftHandSide()) {
VisitForEffect(expr);
return;
}
ASSERT(expr->IsValidLeftHandSide());
// Left-hand side can only be a property, a global or a (parameter or local)
// slot.
......@@ -4282,16 +4273,11 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
ASSERT(expr->expression()->IsValidLeftHandSide());
Comment cmnt(masm_, "[ CountOperation");
SetSourcePosition(expr->position());
// Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
// as the left-hand side.
if (!expr->expression()->IsValidLeftHandSide()) {
VisitForEffect(expr->expression());
return;
}
// Expression can only be a property, a global or a (parameter or local)
// slot.
enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
......
......@@ -1067,6 +1067,12 @@ Handle<Object> Factory::NewReferenceError(const char* message,
}
Handle<Object> Factory::NewReferenceError(const char* message,
Handle<JSArray> args) {
return NewError("MakeReferenceError", message, args);
}
Handle<Object> Factory::NewReferenceError(Handle<String> message) {
return NewError("$ReferenceError", message);
}
......
......@@ -436,6 +436,7 @@ class Factory {
Handle<Object> NewReferenceError(const char* message,
Vector< Handle<Object> > args);
Handle<Object> NewReferenceError(const char* message, Handle<JSArray> args);
Handle<Object> NewReferenceError(Handle<String> message);
Handle<Object> NewEvalError(const char* message,
......
......@@ -333,10 +333,6 @@ namespace internal {
V(MakeReferenceError_string, "MakeReferenceError") \
V(MakeSyntaxError_string, "MakeSyntaxError") \
V(MakeTypeError_string, "MakeTypeError") \
V(invalid_lhs_in_assignment_string, "invalid_lhs_in_assignment") \
V(invalid_lhs_in_for_in_string, "invalid_lhs_in_for_in") \
V(invalid_lhs_in_postfix_op_string, "invalid_lhs_in_postfix_op") \
V(invalid_lhs_in_prefix_op_string, "invalid_lhs_in_prefix_op") \
V(illegal_return_string, "illegal_return") \
V(illegal_break_string, "illegal_break") \
V(illegal_continue_string, "illegal_continue") \
......
......@@ -1818,13 +1818,9 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
void FullCodeGenerator::VisitAssignment(Assignment* expr) {
ASSERT(expr->target()->IsValidLeftHandSide());
Comment cmnt(masm_, "[ Assignment");
// Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
// on the left-hand side.
if (!expr->target()->IsValidLeftHandSide()) {
VisitForEffect(expr->target());
return;
}
// Left-hand side can only be a property, a global or a (parameter or local)
// slot.
......@@ -2353,12 +2349,7 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
void FullCodeGenerator::EmitAssignment(Expression* expr) {
// Invalid left-hand sides are rewritten by the parser to have a 'throw
// ReferenceError' on the left-hand side.
if (!expr->IsValidLeftHandSide()) {
VisitForEffect(expr);
return;
}
ASSERT(expr->IsValidLeftHandSide());
// Left-hand side can only be a property, a global or a (parameter or local)
// slot.
......@@ -4284,16 +4275,11 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
ASSERT(expr->expression()->IsValidLeftHandSide());
Comment cmnt(masm_, "[ CountOperation");
SetSourcePosition(expr->position());
// Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
// as the left-hand side.
if (!expr->expression()->IsValidLeftHandSide()) {
VisitForEffect(expr->expression());
return;
}
// Expression can only be a property, a global or a (parameter or local)
// slot.
enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
......
......@@ -45,10 +45,6 @@ var kMessages = {
unterminated_regexp: ["Invalid regular expression: missing /"],
regexp_flags: ["Cannot supply flags when constructing one RegExp from another"],
incompatible_method_receiver: ["Method ", "%0", " called on incompatible receiver ", "%1"],
invalid_lhs_in_assignment: ["Invalid left-hand side in assignment"],
invalid_lhs_in_for_in: ["Invalid left-hand side in for-in"],
invalid_lhs_in_postfix_op: ["Invalid left-hand side expression in postfix operation"],
invalid_lhs_in_prefix_op: ["Invalid left-hand side expression in prefix operation"],
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"],
......@@ -132,6 +128,11 @@ var kMessages = {
stack_overflow: ["Maximum call stack size exceeded"],
invalid_time_value: ["Invalid time value"],
invalid_count_value: ["Invalid count value"],
// ReferenceError
invalid_lhs_in_assignment: ["Invalid left-hand side in assignment"],
invalid_lhs_in_for: ["Invalid left-hand side in for-loop"],
invalid_lhs_in_postfix_op: ["Invalid left-hand side expression in postfix operation"],
invalid_lhs_in_prefix_op: ["Invalid left-hand side expression in prefix operation"],
// SyntaxError
paren_in_arg_string: ["Function arg string contains parenthesis"],
not_isvar: ["builtin %IS_VAR: not a variable"],
......
......@@ -456,18 +456,6 @@ void ParserTraits::CheckAssigningFunctionLiteralToProperty(Expression* left,
}
Expression* ParserTraits::ValidateAssignmentLeftHandSide(
Expression* expression) const {
ASSERT(expression != NULL);
if (!expression->IsValidLeftHandSide()) {
Handle<String> message =
parser_->isolate()->factory()->invalid_lhs_in_assignment_string();
expression = parser_->NewThrowReferenceError(message);
}
return expression;
}
Expression* ParserTraits::MarkExpressionAsLValue(Expression* expression) {
VariableProxy* proxy = expression != NULL
? expression->AsVariableProxy()
......@@ -492,7 +480,8 @@ void ParserTraits::CheckStrictModeLValue(Expression* expression,
void ParserTraits::ReportMessageAt(Scanner::Location source_location,
const char* message,
Vector<const char*> args) {
Vector<const char*> args,
bool is_reference_error) {
if (parser_->stack_overflow()) {
// Suppress the error message (syntax error or such) in the presence of a
// stack overflow. The isolate allows only one pending exception at at time
......@@ -509,21 +498,25 @@ void ParserTraits::ReportMessageAt(Scanner::Location source_location,
elements->set(i, *arg_string);
}
Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
Handle<Object> result = factory->NewSyntaxError(message, array);
Handle<Object> result = is_reference_error
? factory->NewReferenceError(message, array)
: factory->NewSyntaxError(message, array);
parser_->isolate()->Throw(*result, &location);
}
void ParserTraits::ReportMessage(const char* message,
Vector<Handle<String> > args) {
Vector<Handle<String> > args,
bool is_reference_error) {
Scanner::Location source_location = parser_->scanner()->location();
ReportMessageAt(source_location, message, args);
ReportMessageAt(source_location, message, args, is_reference_error);
}
void ParserTraits::ReportMessageAt(Scanner::Location source_location,
const char* message,
Vector<Handle<String> > args) {
Vector<Handle<String> > args,
bool is_reference_error) {
if (parser_->stack_overflow()) {
// Suppress the error message (syntax error or such) in the presence of a
// stack overflow. The isolate allows only one pending exception at at time
......@@ -539,7 +532,9 @@ void ParserTraits::ReportMessageAt(Scanner::Location source_location,
elements->set(i, *args[i]);
}
Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
Handle<Object> result = factory->NewSyntaxError(message, array);
Handle<Object> result = is_reference_error
? factory->NewReferenceError(message, array)
: factory->NewSyntaxError(message, array);
parser_->isolate()->Throw(*result, &location);
}
......@@ -2844,19 +2839,16 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
init = variable_statement;
}
} else {
Scanner::Location lhs_location = scanner()->peek_location();
Expression* expression = ParseExpression(false, CHECK_OK);
ForEachStatement::VisitMode mode;
bool accept_OF = expression->AsVariableProxy();
if (CheckInOrOf(accept_OF, &mode)) {
// Signal a reference error if the expression is an invalid
// left-hand side expression. We could report this as a syntax
// error here but for compatibility with JSC we choose to report
// the error at runtime.
if (expression == NULL || !expression->IsValidLeftHandSide()) {
Handle<String> message =
isolate()->factory()->invalid_lhs_in_for_in_string();
expression = NewThrowReferenceError(message);
ReportMessageAt(lhs_location, "invalid_lhs_in_for", true);
*ok = false;
return NULL;
}
ForEachStatement* loop =
factory()->NewForEachStatement(mode, labels, pos);
......@@ -3125,15 +3117,12 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
} else if (Token::IsCountOp(op)) {
op = Next();
Scanner::Location lhs_location = scanner()->peek_location();
Expression* expression = ParseUnaryExpression(CHECK_OK);
// Signal a reference error if the expression is an invalid
// left-hand side expression. We could report this as a syntax
// error here but for compatibility with JSC we choose to report the
// error at runtime.
if (expression == NULL || !expression->IsValidLeftHandSide()) {
Handle<String> message =
isolate()->factory()->invalid_lhs_in_prefix_op_string();
expression = NewThrowReferenceError(message);
ReportMessageAt(lhs_location, "invalid_lhs_in_prefix_op", true);
*ok = false;
return NULL;
}
if (strict_mode() == STRICT) {
......@@ -3157,17 +3146,14 @@ Expression* Parser::ParsePostfixExpression(bool* ok) {
// PostfixExpression ::
// LeftHandSideExpression ('++' | '--')?
Scanner::Location lhs_location = scanner()->peek_location();
Expression* expression = ParseLeftHandSideExpression(CHECK_OK);
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
// error here but for compatibility with JSC we choose to report the
// error at runtime.
if (expression == NULL || !expression->IsValidLeftHandSide()) {
Handle<String> message =
isolate()->factory()->invalid_lhs_in_postfix_op_string();
expression = NewThrowReferenceError(message);
ReportMessageAt(lhs_location, "invalid_lhs_in_postfix_op", true);
*ok = false;
return NULL;
}
if (strict_mode() == STRICT) {
......
......@@ -484,10 +484,10 @@ class ParserTraits {
static void CheckAssigningFunctionLiteralToProperty(Expression* left,
Expression* right);
// Signal a reference error if the expression is an invalid left-hand side
// expression. We could report this as a syntax error but for compatibility
// with JSC we choose to report the error at runtime.
Expression* ValidateAssignmentLeftHandSide(Expression* expression) const;
// Determine whether the expression is a valid assignment left-hand side.
static bool IsValidLeftHandSide(Expression* expression) {
return expression->IsValidLeftHandSide();
}
// Determine if the expression is a variable proxy and mark it as being used
// in an assignment or with a increment/decrement operator. This is currently
......@@ -501,11 +501,15 @@ class ParserTraits {
// Reporting errors.
void ReportMessageAt(Scanner::Location source_location,
const char* message,
Vector<const char*> args);
void ReportMessage(const char* message, Vector<Handle<String> > args);
Vector<const char*> args,
bool is_reference_error = false);
void ReportMessage(const char* message,
Vector<Handle<String> > args,
bool is_reference_error = false);
void ReportMessageAt(Scanner::Location source_location,
const char* message,
Vector<Handle<String> > args);
Vector<Handle<String> > args,
bool is_reference_error = false);
// "null" return type creators.
static Handle<String> EmptyIdentifier() {
......
......@@ -69,17 +69,20 @@ void PreParserTraits::CheckStrictModeLValue(PreParserExpression expression,
void PreParserTraits::ReportMessageAt(Scanner::Location location,
const char* message,
Vector<const char*> args) {
Vector<const char*> args,
bool is_reference_error) {
ReportMessageAt(location.beg_pos,
location.end_pos,
message,
args.length() > 0 ? args[0] : NULL);
args.length() > 0 ? args[0] : NULL,
is_reference_error);
}
void PreParserTraits::ReportMessageAt(Scanner::Location location,
const char* type,
const char* name_opt) {
const char* name_opt,
bool is_reference_error) {
pre_parser_->log_
->LogMessage(location.beg_pos, location.end_pos, type, name_opt);
}
......@@ -88,7 +91,8 @@ void PreParserTraits::ReportMessageAt(Scanner::Location location,
void PreParserTraits::ReportMessageAt(int start_pos,
int end_pos,
const char* type,
const char* name_opt) {
const char* name_opt,
bool is_reference_error) {
pre_parser_->log_->LogMessage(start_pos, end_pos, type, name_opt);
}
......
......@@ -342,13 +342,16 @@ class ParserBase : public Traits {
bool is_generator() const { return function_state_->is_generator(); }
// Report syntax errors.
void ReportMessage(const char* message, Vector<const char*> args) {
void ReportMessage(const char* message, Vector<const char*> args,
bool is_reference_error = false) {
Scanner::Location source_location = scanner()->location();
Traits::ReportMessageAt(source_location, message, args);
Traits::ReportMessageAt(source_location, message, args, is_reference_error);
}
void ReportMessageAt(Scanner::Location location, const char* message) {
Traits::ReportMessageAt(location, message, Vector<const char*>::empty());
void ReportMessageAt(Scanner::Location location, const char* message,
bool is_reference_error = false) {
Traits::ReportMessageAt(location, message, Vector<const char*>::empty(),
is_reference_error);
}
void ReportUnexpectedToken(Token::Value token);
......@@ -789,12 +792,10 @@ class PreParserTraits {
static void CheckAssigningFunctionLiteralToProperty(
PreParserExpression left, PreParserExpression right) {}
static PreParserExpression ValidateAssignmentLeftHandSide(
PreParserExpression expression) {
// Parser generates a runtime error here if the left hand side is not valid.
// PreParser doesn't have to.
return expression;
// Determine whether the expression is a valid assignment left-hand side.
static bool IsValidLeftHandSide(PreParserExpression expression) {
// TODO(marja): check properly; for now, leave it to parser.
return true;
}
static PreParserExpression MarkExpressionAsLValue(
......@@ -812,14 +813,17 @@ class PreParserTraits {
// Reporting errors.
void ReportMessageAt(Scanner::Location location,
const char* message,
Vector<const char*> args);
Vector<const char*> args,
bool is_reference_error = false);
void ReportMessageAt(Scanner::Location location,
const char* type,
const char* name_opt);
const char* name_opt,
bool is_reference_error = false);
void ReportMessageAt(int start_pos,
int end_pos,
const char* type,
const char* name_opt);
const char* name_opt,
bool is_reference_error = false);
// "null" return type creators.
static PreParserIdentifier EmptyIdentifier() {
......@@ -1606,6 +1610,8 @@ typename Traits::Type::Expression ParserBase<Traits>::ParseAssignmentExpression(
// YieldExpression
// LeftHandSideExpression AssignmentOperator AssignmentExpression
Scanner::Location lhs_location = scanner()->peek_location();
if (peek() == Token::YIELD && is_generator()) {
return this->ParseYieldExpression(ok);
}
......@@ -1620,12 +1626,11 @@ typename Traits::Type::Expression ParserBase<Traits>::ParseAssignmentExpression(
return expression;
}
// Signal a reference error if the expression is an invalid left-hand
// side expression. We could report this as a syntax error here but
// for compatibility with JSC we choose to report the error at
// runtime.
// TODO(ES5): Should change parsing for spec conformance.
expression = this->ValidateAssignmentLeftHandSide(expression);
if (!IsValidLeftHandSide(expression)) {
this->ReportMessageAt(lhs_location, "invalid_lhs_in_assignment", true);
*ok = false;
return this->EmptyExpression();
}
if (strict_mode() == STRICT) {
// Assignment to eval or arguments is disallowed in strict mode.
......
......@@ -1843,13 +1843,9 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
void FullCodeGenerator::VisitAssignment(Assignment* expr) {
ASSERT(expr->target()->IsValidLeftHandSide());
Comment cmnt(masm_, "[ Assignment");
// Invalid left-hand sides are rewritten to have a 'throw ReferenceError'
// on the left-hand side.
if (!expr->target()->IsValidLeftHandSide()) {
VisitForEffect(expr->target());
return;
}
// Left-hand side can only be a property, a global or a (parameter or local)
// slot.
......@@ -2346,12 +2342,7 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
void FullCodeGenerator::EmitAssignment(Expression* expr) {
// Invalid left-hand sides are rewritten by the parser to have a 'throw
// ReferenceError' on the left-hand side.
if (!expr->IsValidLeftHandSide()) {
VisitForEffect(expr);
return;
}
ASSERT(expr->IsValidLeftHandSide());
// Left-hand side can only be a property, a global or a (parameter or local)
// slot.
......@@ -4283,16 +4274,11 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
ASSERT(expr->expression()->IsValidLeftHandSide());
Comment cmnt(masm_, "[ CountOperation");
SetSourcePosition(expr->position());
// Invalid left-hand-sides are rewritten to have a 'throw
// ReferenceError' as the left-hand side.
if (!expr->expression()->IsValidLeftHandSide()) {
VisitForEffect(expr->expression());
return;
}
// Expression can only be a property, a global or a (parameter or local)
// slot.
enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
......
......@@ -2218,7 +2218,6 @@ TEST(NoErrorsNewExpression) {
"new foo[bar].baz(baz)()[bar].baz;",
"new \"foo\"", // Runtime error
"new 1", // Runtime error
"new foo++",
// This even runs:
"(new new Function(\"this.x = 1\")).x;",
"new new Test_Two(String, 2).v(0123).length;",
......@@ -2240,6 +2239,8 @@ TEST(ErrorsNewExpression) {
"new foo bar",
"new ) foo",
"new ++foo",
// TODO(marja): Activate this test once the preparser checks correctly.
// "new foo ++",
NULL
};
......
......@@ -29,37 +29,37 @@
// exceptions are delayed until runtime.
// Normal assignments:
assertThrows("12 = 12");
assertThrows("x++ = 12");
assertThrows("eval('var x') = 12");
assertDoesNotThrow("if (false) eval('var x') = 12");
assertThrows("12 = 12", ReferenceError);
assertThrows("x++ = 12", ReferenceError);
assertThrows("eval('var x') = 12", ReferenceError);
assertThrows("if (false) eval('var x') = 12", ReferenceError);
// Pre- and post-fix operations:
assertThrows("12++");
assertThrows("12--");
assertThrows("--12");
assertThrows("++12");
assertThrows("++(eval('12'))");
assertThrows("(eval('12'))++");
assertDoesNotThrow("if (false) ++(eval('12'))");
assertDoesNotThrow("if (false) (eval('12'))++");
assertThrows("12++", ReferenceError);
assertThrows("12--", ReferenceError);
assertThrows("--12", ReferenceError);
assertThrows("++12", ReferenceError);
assertThrows("++(eval('12'))", ReferenceError);
assertThrows("(eval('12'))++", ReferenceError);
assertThrows("if (false) ++(eval('12'))", ReferenceError);
assertThrows("if (false) (eval('12'))++", ReferenceError);
// For in:
assertThrows("for (12 in [1]) print(12);");
assertThrows("for (eval('var x') in [1]) print(12);");
assertDoesNotThrow("if (false) for (eval('var x') in [1]) print(12);");
assertThrows("for (12 in [1]) print(12);", ReferenceError);
assertThrows("for (eval('var x') in [1]) print(12);", ReferenceError);
assertThrows("if (false) for (eval('0') in [1]) print(12);", ReferenceError);
// For:
assertThrows("for (12 = 1;;) print(12);");
assertThrows("for (eval('var x') = 1;;) print(12);");
assertDoesNotThrow("if (false) for (eval('var x') = 1;;) print(12);");
assertThrows("for (12 = 1;;) print(12);", ReferenceError);
assertThrows("for (eval('var x') = 1;;) print(12);", ReferenceError);
assertThrows("if (false) for (eval('var x') = 1;;) print(12);", ReferenceError);
// Assignments to 'this'.
assertThrows("this = 42");
assertDoesNotThrow("function f() { this = 12; }");
assertThrows("for (this in {x:3, y:4, z:5}) ;");
assertThrows("for (this = 0;;) ;");
assertThrows("this++");
assertThrows("++this");
assertThrows("this--");
assertThrows("--this");
assertThrows("this = 42", ReferenceError);
assertThrows("function f() { this = 12; }", ReferenceError);
assertThrows("for (this in {x:3, y:4, z:5}) ;", ReferenceError);
assertThrows("for (this = 0;;) ;", ReferenceError);
assertThrows("this++", ReferenceError);
assertThrows("++this", ReferenceError);
assertThrows("this--", ReferenceError);
assertThrows("--this", ReferenceError);
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
try {
var f = eval("(function(){0 = y + y})");
%OptimizeFunctionOnNextCall(f);
f();
assertUnreachable();
} catch(e) {
assertTrue(e instanceof ReferenceError);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment