DONT_OPTIMIZE_NODE(TryFinallyStatement)
DONT_OPTIMIZE_NODE(DebuggerStatement)
DONT_OPTIMIZE_NODE(NativeFunctionLiteral)
+DONT_OPTIMIZE_NODE(SuperReference)
DONT_OPTIMIZE_NODE_WITH_FEEDBACK_SLOTS(Yield)
V(BinaryOperation) \
V(CompareOperation) \
V(ThisFunction) \
+ V(SuperReference) \
V(CaseClause)
#define AST_NODE_LIST(V) \
void mark_for_call() { is_for_call_ = true; }
bool IsForCall() { return is_for_call_; }
+ bool IsSuperAccess() {
+ return obj()->IsSuperReference();
+ }
+
TypeFeedbackId PropertyFeedbackId() { return reuse(id()); }
virtual int ComputeFeedbackSlotCount() { return FLAG_vector_ics ? 1 : 0; }
explicit ThisFunction(Zone* zone, int pos): Expression(zone, pos) {}
};
+
+class SuperReference V8_FINAL : public Expression {
+ public:
+ DECLARE_NODE_TYPE(SuperReference)
+
+ VariableProxy* this_var() const { return this_var_; }
+
+ TypeFeedbackId HomeObjectFeedbackId() { return reuse(id()); }
+
+ protected:
+ explicit SuperReference(Zone* zone, VariableProxy* this_var, int pos)
+ : Expression(zone, pos), this_var_(this_var) {
+ DCHECK(this_var->is_this());
+ }
+
+ VariableProxy* this_var_;
+};
+
+
#undef DECLARE_NODE_TYPE
VISIT_AND_RETURN(ThisFunction, fun)
}
+ SuperReference* NewSuperReference(VariableProxy* this_var, int pos) {
+ SuperReference* super = new (zone_) SuperReference(zone_, this_var, pos);
+ VISIT_AND_RETURN(SuperReference, super);
+ }
+
#undef VISIT_AND_RETURN
private:
}
+void AstGraphBuilder::VisitSuperReference(SuperReference* expr) {
+ UNREACHABLE();
+}
+
+
void AstGraphBuilder::VisitCaseClause(CaseClause* expr) { UNREACHABLE(); }
DEFINE_BOOL(harmony_strings, false, "enable harmony string")
DEFINE_BOOL(harmony_arrays, false, "enable harmony arrays")
DEFINE_BOOL(harmony_arrow_functions, false, "enable harmony arrow functions")
+DEFINE_BOOL(harmony_classes, false, "enable harmony classes")
DEFINE_BOOL(harmony, false, "enable all harmony features (except proxies)")
DEFINE_IMPLICATION(harmony, harmony_scoping)
DEFINE_IMPLICATION(harmony, harmony_strings)
DEFINE_IMPLICATION(harmony, harmony_arrays)
DEFINE_IMPLICATION(harmony, harmony_arrow_functions)
+DEFINE_IMPLICATION(harmony, harmony_classes)
DEFINE_IMPLICATION(harmony_modules, harmony_scoping)
DEFINE_IMPLICATION(harmony, es_staging)
}
+void BreakableStatementChecker::VisitSuperReference(SuperReference* expr) {}
+
+
#define __ ACCESS_MASM(masm())
bool FullCodeGenerator::MakeCode(CompilationInfo* info) {
}
+void FullCodeGenerator::VisitSuperReference(SuperReference* super) {
+ DCHECK(FLAG_harmony_classes);
+ UNIMPLEMENTED();
+}
+
+
void FullCodeGenerator::SetExpressionPosition(Expression* expr) {
if (!info_->is_debug()) {
CodeGenerator::RecordPositions(masm_, expr->position());
}
+void HOptimizedGraphBuilder::VisitSuperReference(SuperReference* expr) {
+ UNREACHABLE();
+}
+
+
void HOptimizedGraphBuilder::VisitDeclarations(
ZoneList<Declaration*>* declarations) {
DCHECK(globals_.is_empty());
symbol_to_number: ["Cannot convert a Symbol value to a number"],
invalid_module_path: ["Module does not export '", "%0", "', or export is not itself a module"],
module_type_error: ["Module '", "%0", "' used improperly"],
- module_export_undefined: ["Export '", "%0", "' is not defined in module"]
+ module_export_undefined: ["Export '", "%0", "' is not defined in module"],
+ unexpected_super: ["'super' keyword unexpected here"]
};
V(OrderedHashTable)
-#define ERROR_MESSAGES_LIST(V) \
+#define ERROR_MESSAGES_LIST(V) \
V(kNoReason, "no reason") \
\
V(k32BitValueInRegisterIsNotZeroExtended, \
V(kExpectedNonIdenticalObjects, "Expected non-identical objects") \
V(kExpectedNonNullContext, "Expected non-null context") \
V(kExpectedPositiveZero, "Expected +0.0") \
- V(kExpectedAllocationSiteInCell, \
- "Expected AllocationSite in property cell") \
+ V(kExpectedAllocationSiteInCell, "Expected AllocationSite in property cell")\
V(kExpectedFixedArrayInFeedbackVector, \
"Expected fixed array in feedback vector") \
- V(kExpectedFixedArrayInRegisterA2, \
- "Expected fixed array in register a2") \
- V(kExpectedFixedArrayInRegisterEbx, \
- "Expected fixed array in register ebx") \
- V(kExpectedFixedArrayInRegisterR2, \
- "Expected fixed array in register r2") \
- V(kExpectedFixedArrayInRegisterRbx, \
- "Expected fixed array in register rbx") \
+ V(kExpectedFixedArrayInRegisterA2, "Expected fixed array in register a2") \
+ V(kExpectedFixedArrayInRegisterEbx, "Expected fixed array in register ebx") \
+ V(kExpectedFixedArrayInRegisterR2, "Expected fixed array in register r2") \
+ V(kExpectedFixedArrayInRegisterRbx, "Expected fixed array in register rbx") \
V(kExpectedNewSpaceObject, "Expected new space object") \
V(kExpectedSmiOrHeapNumber, "Expected smi or HeapNumber") \
- V(kExpectedUndefinedOrCell, \
- "Expected undefined or cell in register") \
- V(kExpectingAlignmentForCopyBytes, \
- "Expecting alignment for CopyBytes") \
+ V(kExpectedUndefinedOrCell, "Expected undefined or cell in register") \
+ V(kExpectingAlignmentForCopyBytes, "Expecting alignment for CopyBytes") \
V(kExportDeclaration, "Export declaration") \
V(kExternalStringExpectedButNotFound, \
"External string expected, but not found") \
V(kLhsHasBeenClobbered, "lhs has been clobbered") \
V(kLiveBytesCountOverflowChunkSize, "Live Bytes Count overflow chunk size") \
V(kLiveEdit, "LiveEdit") \
- V(kLookupVariableInCountOperation, \
- "Lookup variable in count operation") \
+ V(kLookupVariableInCountOperation, "Lookup variable in count operation") \
V(kMapBecameDeprecated, "Map became deprecated") \
V(kMapBecameUnstable, "Map became unstable") \
V(kMapIsNoLongerInEax, "Map is no longer in eax") \
V(kModuleVariable, "Module variable") \
V(kModuleUrl, "Module url") \
V(kNativeFunctionLiteral, "Native function literal") \
+ V(kSuperReference, "Super reference") \
V(kNeedSmiLiteral, "Need a Smi literal here") \
V(kNoCasesLeft, "No cases left") \
V(kNoEmptyArraysHereInEmitFastAsciiArrayJoin, \
"No empty arrays here in EmitFastAsciiArrayJoin") \
- V(kNonInitializerAssignmentToConst, \
- "Non-initializer assignment to const") \
+ V(kNonInitializerAssignmentToConst, "Non-initializer assignment to const") \
V(kNonSmiIndex, "Non-smi index") \
V(kNonSmiKeyInArrayLiteral, "Non-smi key in array literal") \
V(kNonSmiValue, "Non-smi value") \
V(kNonObject, "Non-object value") \
V(kNotEnoughVirtualRegistersForValues, \
"Not enough virtual registers for values") \
- V(kNotEnoughSpillSlotsForOsr, \
- "Not enough spill slots for OSR") \
+ V(kNotEnoughSpillSlotsForOsr, "Not enough spill slots for OSR") \
V(kNotEnoughVirtualRegistersRegalloc, \
"Not enough virtual registers (regalloc)") \
V(kObjectFoundInSmiOnlyArray, "Object found in smi-only array") \
- V(kObjectLiteralWithComplexProperty, \
- "Object literal with complex property") \
+ V(kObjectLiteralWithComplexProperty, "Object literal with complex property")\
V(kOddballInStringTableIsNotUndefinedOrTheHole, \
"Oddball in string table is not undefined or the hole") \
V(kOffsetOutOfRange, "Offset out of range") \
V(kReceivedInvalidReturnAddress, "Received invalid return address") \
V(kReferenceToAVariableWhichRequiresDynamicLookup, \
"Reference to a variable which requires dynamic lookup") \
- V(kReferenceToGlobalLexicalVariable, \
- "Reference to global lexical variable") \
+ V(kReferenceToGlobalLexicalVariable, "Reference to global lexical variable")\
V(kReferenceToUninitializedVariable, "Reference to uninitialized variable") \
V(kRegisterDidNotMatchExpectedRoot, "Register did not match expected root") \
V(kRegisterWasClobbered, "Register was clobbered") \
- V(kRememberedSetPointerInNewSpace, "Remembered set pointer is in new space") \
+ V(kRememberedSetPointerInNewSpace, "Remembered set pointer is in new space")\
V(kReturnAddressNotFoundInFrame, "Return address not found in frame") \
V(kRhsHasBeenClobbered, "Rhs has been clobbered") \
V(kScopedBlock, "ScopedBlock") \
return factory->NewVariableProxy(scope->receiver(), pos);
}
+Expression* ParserTraits::SuperReference(
+ Scope* scope, AstNodeFactory<AstConstructionVisitor>* factory, int pos) {
+ return factory->NewSuperReference(
+ ThisExpression(scope, factory, pos)->AsVariableProxy(),
+ pos);
+}
Literal* ParserTraits::ExpressionFromLiteral(
Token::Value token, int pos,
set_allow_generators(FLAG_harmony_generators);
set_allow_arrow_functions(FLAG_harmony_arrow_functions);
set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals);
+ set_allow_classes(FLAG_harmony_classes);
for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
++feature) {
use_counts_[feature] = 0;
Expression* ThisExpression(Scope* scope,
AstNodeFactory<AstConstructionVisitor>* factory,
int pos = RelocInfo::kNoPosition);
+ Expression* SuperReference(Scope* scope,
+ AstNodeFactory<AstConstructionVisitor>* factory,
+ int pos = RelocInfo::kNoPosition);
Literal* ExpressionFromLiteral(
Token::Value token, int pos, Scanner* scanner,
AstNodeFactory<AstConstructionVisitor>* factory);
bool allow_harmony_numeric_literals() const {
return scanner()->HarmonyNumericLiterals();
}
+ bool allow_classes() const { return scanner()->HarmonyClasses(); }
// Setters that determine whether certain syntactical constructs are
// allowed to be parsed by this instance of the parser.
void set_allow_harmony_numeric_literals(bool allow) {
scanner()->SetHarmonyNumericLiterals(allow);
}
+ void set_allow_classes(bool allow) {
+ scanner()->SetHarmonyClasses(allow);
+ }
protected:
friend class Traits::Type::Checkpoint;
return PreParserExpression(kThisExpression);
}
+ static PreParserExpression Super() {
+ return PreParserExpression(kSuperExpression);
+ }
+
static PreParserExpression ThisProperty() {
return PreParserExpression(kThisPropertyExpression);
}
kThisExpression = (1 << 4),
kThisPropertyExpression = (2 << 4),
kPropertyExpression = (3 << 4),
- kCallExpression = (4 << 4)
+ kCallExpression = (4 << 4),
+ kSuperExpression = (5 << 4)
};
explicit PreParserExpression(int expression_code) : code_(expression_code) {}
return PreParserExpression::This();
}
+ static PreParserExpression SuperReference(PreParserScope* scope,
+ PreParserFactory* factory) {
+ return PreParserExpression::Super();
+ }
+
static PreParserExpression ExpressionFromLiteral(
Token::Value token, int pos, Scanner* scanner,
PreParserFactory* factory) {
if (peek() == Token::NEW) {
Consume(Token::NEW);
int new_pos = position();
- ExpressionT result = this->ParseMemberWithNewPrefixesExpression(CHECK_OK);
+ ExpressionT result = this->EmptyExpression();
+ if (Check(Token::SUPER)) {
+ result = this->SuperReference(scope_, factory());
+ } else {
+ result = this->ParseMemberWithNewPrefixesExpression(CHECK_OK);
+ }
if (peek() == Token::LPAREN) {
// NewExpression with arguments.
typename Traits::Type::ExpressionList args =
return factory()->NewCallNew(result, this->NewExpressionList(0, zone_),
new_pos);
}
- // No 'new' keyword.
+ // No 'new' or 'super' keyword.
return this->ParseMemberExpression(ok);
}
function_type,
FunctionLiteral::NORMAL_ARITY,
CHECK_OK);
+ } else if (peek() == Token::SUPER) {
+ int beg_pos = position();
+ Consume(Token::SUPER);
+ Token::Value next = peek();
+ if (next == Token::PERIOD || next == Token::LBRACK ||
+ next == Token::LPAREN) {
+ result = this->SuperReference(scope_, factory());
+ } else {
+ ReportMessageAt(Scanner::Location(beg_pos, position()),
+ "unexpected_super");
+ *ok = false;
+ return this->EmptyExpression();
+ }
} else {
result = ParsePrimaryExpression(CHECK_OK);
}
}
+void PrettyPrinter::VisitSuperReference(SuperReference* node) {
+ Print("<super-reference>");
+}
+
+
const char* PrettyPrinter::Print(AstNode* node) {
Init();
Visit(node);
IndentedScope indent(this, "THIS-FUNCTION");
}
+
+void AstPrinter::VisitSuperReference(SuperReference* node) {
+ IndentedScope indent(this, "SUPER-REFERENCE");
+}
+
#endif // DEBUG
} } // namespace v8::internal
octal_pos_(Location::invalid()),
harmony_scoping_(false),
harmony_modules_(false),
- harmony_numeric_literals_(false) { }
+ harmony_numeric_literals_(false),
+ harmony_classes_(false) { }
void Scanner::Initialize(Utf16CharacterStream* source) {
// ----------------------------------------------------------------------------
// Keyword Matcher
-#define KEYWORDS(KEYWORD_GROUP, KEYWORD) \
- KEYWORD_GROUP('b') \
- KEYWORD("break", Token::BREAK) \
- KEYWORD_GROUP('c') \
- KEYWORD("case", Token::CASE) \
- KEYWORD("catch", Token::CATCH) \
- KEYWORD("class", Token::FUTURE_RESERVED_WORD) \
- KEYWORD("const", Token::CONST) \
- KEYWORD("continue", Token::CONTINUE) \
- KEYWORD_GROUP('d') \
- KEYWORD("debugger", Token::DEBUGGER) \
- KEYWORD("default", Token::DEFAULT) \
- KEYWORD("delete", Token::DELETE) \
- KEYWORD("do", Token::DO) \
- KEYWORD_GROUP('e') \
- KEYWORD("else", Token::ELSE) \
- KEYWORD("enum", Token::FUTURE_RESERVED_WORD) \
- KEYWORD("export", harmony_modules \
- ? Token::EXPORT : Token::FUTURE_RESERVED_WORD) \
- KEYWORD("extends", Token::FUTURE_RESERVED_WORD) \
- KEYWORD_GROUP('f') \
- KEYWORD("false", Token::FALSE_LITERAL) \
- KEYWORD("finally", Token::FINALLY) \
- KEYWORD("for", Token::FOR) \
- KEYWORD("function", Token::FUNCTION) \
- KEYWORD_GROUP('i') \
- KEYWORD("if", Token::IF) \
- KEYWORD("implements", Token::FUTURE_STRICT_RESERVED_WORD) \
- KEYWORD("import", harmony_modules \
- ? Token::IMPORT : Token::FUTURE_RESERVED_WORD) \
- KEYWORD("in", Token::IN) \
- KEYWORD("instanceof", Token::INSTANCEOF) \
- KEYWORD("interface", Token::FUTURE_STRICT_RESERVED_WORD) \
- KEYWORD_GROUP('l') \
- KEYWORD("let", harmony_scoping \
- ? Token::LET : Token::FUTURE_STRICT_RESERVED_WORD) \
- KEYWORD_GROUP('n') \
- KEYWORD("new", Token::NEW) \
- KEYWORD("null", Token::NULL_LITERAL) \
- KEYWORD_GROUP('p') \
- KEYWORD("package", Token::FUTURE_STRICT_RESERVED_WORD) \
- KEYWORD("private", Token::FUTURE_STRICT_RESERVED_WORD) \
- KEYWORD("protected", Token::FUTURE_STRICT_RESERVED_WORD) \
- KEYWORD("public", Token::FUTURE_STRICT_RESERVED_WORD) \
- KEYWORD_GROUP('r') \
- KEYWORD("return", Token::RETURN) \
- KEYWORD_GROUP('s') \
- KEYWORD("static", Token::FUTURE_STRICT_RESERVED_WORD) \
- KEYWORD("super", Token::FUTURE_RESERVED_WORD) \
- KEYWORD("switch", Token::SWITCH) \
- KEYWORD_GROUP('t') \
- KEYWORD("this", Token::THIS) \
- KEYWORD("throw", Token::THROW) \
- KEYWORD("true", Token::TRUE_LITERAL) \
- KEYWORD("try", Token::TRY) \
- KEYWORD("typeof", Token::TYPEOF) \
- KEYWORD_GROUP('v') \
- KEYWORD("var", Token::VAR) \
- KEYWORD("void", Token::VOID) \
- KEYWORD_GROUP('w') \
- KEYWORD("while", Token::WHILE) \
- KEYWORD("with", Token::WITH) \
- KEYWORD_GROUP('y') \
+#define KEYWORDS(KEYWORD_GROUP, KEYWORD) \
+ KEYWORD_GROUP('b') \
+ KEYWORD("break", Token::BREAK) \
+ KEYWORD_GROUP('c') \
+ KEYWORD("case", Token::CASE) \
+ KEYWORD("catch", Token::CATCH) \
+ KEYWORD("class", Token::FUTURE_RESERVED_WORD) \
+ KEYWORD("const", Token::CONST) \
+ KEYWORD("continue", Token::CONTINUE) \
+ KEYWORD_GROUP('d') \
+ KEYWORD("debugger", Token::DEBUGGER) \
+ KEYWORD("default", Token::DEFAULT) \
+ KEYWORD("delete", Token::DELETE) \
+ KEYWORD("do", Token::DO) \
+ KEYWORD_GROUP('e') \
+ KEYWORD("else", Token::ELSE) \
+ KEYWORD("enum", Token::FUTURE_RESERVED_WORD) \
+ KEYWORD("export", \
+ harmony_modules ? Token::EXPORT : Token::FUTURE_RESERVED_WORD) \
+ KEYWORD("extends", Token::FUTURE_RESERVED_WORD) \
+ KEYWORD_GROUP('f') \
+ KEYWORD("false", Token::FALSE_LITERAL) \
+ KEYWORD("finally", Token::FINALLY) \
+ KEYWORD("for", Token::FOR) \
+ KEYWORD("function", Token::FUNCTION) \
+ KEYWORD_GROUP('i') \
+ KEYWORD("if", Token::IF) \
+ KEYWORD("implements", Token::FUTURE_STRICT_RESERVED_WORD) \
+ KEYWORD("import", \
+ harmony_modules ? Token::IMPORT : Token::FUTURE_RESERVED_WORD) \
+ KEYWORD("in", Token::IN) \
+ KEYWORD("instanceof", Token::INSTANCEOF) \
+ KEYWORD("interface", Token::FUTURE_STRICT_RESERVED_WORD) \
+ KEYWORD_GROUP('l') \
+ KEYWORD("let", \
+ harmony_scoping ? Token::LET : Token::FUTURE_STRICT_RESERVED_WORD) \
+ KEYWORD_GROUP('n') \
+ KEYWORD("new", Token::NEW) \
+ KEYWORD("null", Token::NULL_LITERAL) \
+ KEYWORD_GROUP('p') \
+ KEYWORD("package", Token::FUTURE_STRICT_RESERVED_WORD) \
+ KEYWORD("private", Token::FUTURE_STRICT_RESERVED_WORD) \
+ KEYWORD("protected", Token::FUTURE_STRICT_RESERVED_WORD) \
+ KEYWORD("public", Token::FUTURE_STRICT_RESERVED_WORD) \
+ KEYWORD_GROUP('r') \
+ KEYWORD("return", Token::RETURN) \
+ KEYWORD_GROUP('s') \
+ KEYWORD("static", Token::FUTURE_STRICT_RESERVED_WORD) \
+ KEYWORD("super", \
+ harmony_classes ? Token::SUPER : Token::FUTURE_RESERVED_WORD) \
+ KEYWORD("switch", Token::SWITCH) \
+ KEYWORD_GROUP('t') \
+ KEYWORD("this", Token::THIS) \
+ KEYWORD("throw", Token::THROW) \
+ KEYWORD("true", Token::TRUE_LITERAL) \
+ KEYWORD("try", Token::TRY) \
+ KEYWORD("typeof", Token::TYPEOF) \
+ KEYWORD_GROUP('v') \
+ KEYWORD("var", Token::VAR) \
+ KEYWORD("void", Token::VOID) \
+ KEYWORD_GROUP('w') \
+ KEYWORD("while", Token::WHILE) \
+ KEYWORD("with", Token::WITH) \
+ KEYWORD_GROUP('y') \
KEYWORD("yield", Token::YIELD)
static Token::Value KeywordOrIdentifierToken(const uint8_t* input,
int input_length,
bool harmony_scoping,
- bool harmony_modules) {
+ bool harmony_modules,
+ bool harmony_classes) {
DCHECK(input_length >= 1);
const int kMinLength = 2;
const int kMaxLength = 10;
return string->is_one_byte() &&
Token::FUTURE_STRICT_RESERVED_WORD ==
KeywordOrIdentifierToken(string->raw_data(), string->length(),
- harmony_scoping_, harmony_modules_);
+ harmony_scoping_, harmony_modules_,
+ harmony_classes_);
}
return KeywordOrIdentifierToken(chars.start(),
chars.length(),
harmony_scoping_,
- harmony_modules_);
+ harmony_modules_,
+ harmony_classes_);
}
return Token::IDENTIFIER;
void SetHarmonyNumericLiterals(bool numeric_literals) {
harmony_numeric_literals_ = numeric_literals;
}
+ bool HarmonyClasses() const {
+ return harmony_classes_;
+ }
+ void SetHarmonyClasses(bool classes) {
+ harmony_classes_ = classes;
+ }
// Returns true if there was a line terminator before the peek'ed token,
// possibly inside a multi-line comment.
bool harmony_modules_;
// Whether we scan 0o777 and 0b111 as numbers.
bool harmony_numeric_literals_;
+ // Whether we scan 'super' as keyword.
+ bool harmony_classes_;
};
} } // namespace v8::internal
K(IMPORT, "import", 0) \
K(LET, "let", 0) \
K(YIELD, "yield", 0) \
+ K(SUPER, "super", 0) \
\
/* Illegal token - not able to scan. */ \
T(ILLEGAL, "ILLEGAL", 0) \
}
+void AstTyper::VisitSuperReference(SuperReference* expr) {}
+
+
void AstTyper::VisitDeclarations(ZoneList<Declaration*>* decls) {
for (int i = 0; i < decls->length(); ++i) {
Declaration* decl = decls->at(i);
// The scanner should parse Harmony keywords for this test.
scanner.SetHarmonyScoping(true);
scanner.SetHarmonyModules(true);
+ scanner.SetHarmonyClasses(true);
scanner.Initialize(&stream);
CHECK_EQ(key_token.token, scanner.Next());
CHECK_EQ(i::Token::EOS, scanner.Next());
kAllowModules,
kAllowGenerators,
kAllowHarmonyNumericLiterals,
- kAllowArrowFunctions
+ kAllowArrowFunctions,
+ kAllowClasses
};
parser->set_allow_harmony_numeric_literals(
flags.Contains(kAllowHarmonyNumericLiterals));
parser->set_allow_arrow_functions(flags.Contains(kAllowArrowFunctions));
+ parser->set_allow_classes(flags.Contains(kAllowClasses));
}
static const ParserFlag default_flags[] = {
kAllowLazy, kAllowHarmonyScoping, kAllowModules,
- kAllowGenerators, kAllowNativesSyntax, kAllowArrowFunctions};
+ kAllowGenerators, kAllowNativesSyntax, kAllowArrowFunctions,
+ kAllowClasses};
ParserFlag* generated_flags = NULL;
if (flags == NULL) {
flags = default_flags;
RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
always_flags, ARRAY_SIZE(always_flags));
}
+
+
+TEST(NoErrorsSuper) {
+ // Tests that parser and preparser accept 'super' keyword in right places.
+ const char* context_data[][2] = {{"", ";"},
+ {"k = ", ";"},
+ {"foo(", ");"},
+ {NULL, NULL}};
+
+ const char* statement_data[] = {
+ "super.x",
+ "super[27]",
+ "new super",
+ "new super()",
+ "new super(12, 45)",
+ "new new super",
+ "new new super()",
+ "new new super()()",
+ "z.super", // Ok, property lookup.
+ NULL};
+
+ static const ParserFlag always_flags[] = {kAllowClasses};
+ RunParserSyncTest(context_data, statement_data, kSuccess, NULL, 0,
+ always_flags, ARRAY_SIZE(always_flags));
+}
+
+
+TEST(ErrorsSuper) {
+ // Tests that parser and preparser generate same errors for 'super'.
+ const char* context_data[][2] = {{"", ";"},
+ {"k = ", ";"},
+ {"foo(", ");"},
+ {NULL, NULL}};
+
+ const char* statement_data[] = {
+ "super = x",
+ "y = super",
+ "f(super)",
+ NULL};
+
+ static const ParserFlag always_flags[] = {kAllowClasses};
+ RunParserSyncTest(context_data, statement_data, kError, NULL, 0,
+ always_flags, ARRAY_SIZE(always_flags));
+}