| Index: test/cctest/test-parsing.cc
|
| diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc
|
| index 8fbd60da9d2c0456f2da11380ce9710210aa37c0..22d5056f8007c4afa1ae0f95cc813d3f22133e6c 100644
|
| --- a/test/cctest/test-parsing.cc
|
| +++ b/test/cctest/test-parsing.cc
|
| @@ -244,8 +244,11 @@ TEST(Preparsing) {
|
| CHECK_EQ(11, error_location.end_pos);
|
| // Should not crash.
|
| const char* message = pre_impl->BuildMessage();
|
| - pre_impl->BuildArgs();
|
| + i::Vector<const char*> args = pre_impl->BuildArgs();
|
| CHECK_GT(strlen(message), 0);
|
| + args.Dispose();
|
| + i::DeleteArray(message);
|
| + delete error_preparse;
|
| }
|
|
|
|
|
| @@ -1019,7 +1022,7 @@ TEST(ScopePositions) {
|
| int kSuffixByteLen = i::StrLength(source_data[i].outer_suffix);
|
| int kProgramSize = kPrefixLen + kInnerLen + kSuffixLen;
|
| int kProgramByteSize = kPrefixByteLen + kInnerByteLen + kSuffixByteLen;
|
| - i::Vector<char> program = i::Vector<char>::New(kProgramByteSize + 1);
|
| + i::ScopedVector<char> program(kProgramByteSize + 1);
|
| i::OS::SNPrintF(program, "%s%s%s",
|
| source_data[i].outer_prefix,
|
| source_data[i].inner_source,
|
| @@ -1099,6 +1102,13 @@ enum ParserFlag {
|
| };
|
|
|
|
|
| +enum ParserSyncTestResult {
|
| + kSuccessOrError,
|
| + kSuccess,
|
| + kError
|
| +};
|
| +
|
| +
|
| void SetParserFlags(i::ParserBase* parser, i::EnumSet<ParserFlag> flags) {
|
| parser->set_allow_lazy(flags.Contains(kAllowLazy));
|
| parser->set_allow_natives_syntax(flags.Contains(kAllowNativesSyntax));
|
| @@ -1112,7 +1122,8 @@ void SetParserFlags(i::ParserBase* parser, i::EnumSet<ParserFlag> flags) {
|
|
|
|
|
| void TestParserSyncWithFlags(i::Handle<i::String> source,
|
| - i::EnumSet<ParserFlag> flags) {
|
| + i::EnumSet<ParserFlag> flags,
|
| + ParserSyncTestResult result) {
|
| i::Isolate* isolate = CcTest::i_isolate();
|
| i::Factory* factory = isolate->factory();
|
|
|
| @@ -1154,6 +1165,17 @@ void TestParserSyncWithFlags(i::Handle<i::String> source,
|
| i::Handle<i::String> message_string =
|
| i::Handle<i::String>::cast(i::GetProperty(exception_handle, "message"));
|
|
|
| + if (result == kSuccess) {
|
| + i::OS::Print(
|
| + "Parser failed on:\n"
|
| + "\t%s\n"
|
| + "with error:\n"
|
| + "\t%s\n"
|
| + "However, we expected no error.",
|
| + source->ToCString().get(), message_string->ToCString().get());
|
| + CHECK(false);
|
| + }
|
| +
|
| if (!data.has_error()) {
|
| i::OS::Print(
|
| "Parser failed on:\n"
|
| @@ -1187,13 +1209,21 @@ void TestParserSyncWithFlags(i::Handle<i::String> source,
|
| "However, the parser succeeded",
|
| source->ToCString().get(), FormatMessage(&data)->ToCString().get());
|
| CHECK(false);
|
| + } else if (result == kError) {
|
| + i::OS::Print(
|
| + "Expected error on:\n"
|
| + "\t%s\n"
|
| + "However, parser and preparser succeeded",
|
| + source->ToCString().get());
|
| + CHECK(false);
|
| }
|
| }
|
|
|
|
|
| void TestParserSync(const char* source,
|
| const ParserFlag* flag_list,
|
| - size_t flag_list_length) {
|
| + size_t flag_list_length,
|
| + ParserSyncTestResult result = kSuccessOrError) {
|
| i::Handle<i::String> str =
|
| CcTest::i_isolate()->factory()->NewStringFromAscii(i::CStrVector(source));
|
| for (int bits = 0; bits < (1 << flag_list_length); bits++) {
|
| @@ -1201,7 +1231,7 @@ void TestParserSync(const char* source,
|
| for (size_t flag_index = 0; flag_index < flag_list_length; flag_index++) {
|
| if ((bits & (1 << flag_index)) != 0) flags.Add(flag_list[flag_index]);
|
| }
|
| - TestParserSyncWithFlags(str, flags);
|
| + TestParserSyncWithFlags(str, flags, result);
|
| }
|
| }
|
|
|
| @@ -1345,3 +1375,641 @@ TEST(PreparserStrictOctal) {
|
| CHECK_EQ("SyntaxError: Octal literals are not allowed in strict mode.",
|
| *exception);
|
| }
|
| +
|
| +
|
| +void RunParserSyncTest(const char* context_data[][2],
|
| + const char* statement_data[],
|
| + ParserSyncTestResult result) {
|
| + v8::HandleScope handles(CcTest::isolate());
|
| + v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate());
|
| + v8::Context::Scope context_scope(context);
|
| +
|
| + int marker;
|
| + CcTest::i_isolate()->stack_guard()->SetStackLimit(
|
| + reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
|
| +
|
| + static const ParserFlag flags[] = {
|
| + kAllowLazy, kAllowHarmonyScoping, kAllowModules, kAllowGenerators,
|
| + kAllowForOf
|
| + };
|
| + for (int i = 0; context_data[i][0] != NULL; ++i) {
|
| + for (int j = 0; statement_data[j] != NULL; ++j) {
|
| + int kPrefixLen = i::StrLength(context_data[i][0]);
|
| + int kStatementLen = i::StrLength(statement_data[j]);
|
| + int kSuffixLen = i::StrLength(context_data[i][1]);
|
| + int kProgramSize = kPrefixLen + kStatementLen + kSuffixLen;
|
| +
|
| + // Plug the source code pieces together.
|
| + i::ScopedVector<char> program(kProgramSize + 1);
|
| + int length = i::OS::SNPrintF(program,
|
| + "%s%s%s",
|
| + context_data[i][0],
|
| + statement_data[j],
|
| + context_data[i][1]);
|
| + CHECK(length == kProgramSize);
|
| + TestParserSync(program.start(),
|
| + flags,
|
| + ARRAY_SIZE(flags),
|
| + result);
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(ErrorsEvalAndArguments) {
|
| + // Tests that both preparsing and parsing produce the right kind of errors for
|
| + // using "eval" and "arguments" as identifiers. Without the strict mode, it's
|
| + // ok to use "eval" or "arguments" as identifiers. With the strict mode, it
|
| + // isn't.
|
| + const char* context_data[][2] = {
|
| + { "\"use strict\";", "" },
|
| + { "var eval; function test_func() {\"use strict\"; ", "}"},
|
| + { NULL, NULL }
|
| + };
|
| +
|
| + const char* statement_data[] = {
|
| + "var eval;",
|
| + "var arguments",
|
| + "var foo, eval;",
|
| + "var foo, arguments;",
|
| + "try { } catch (eval) { }",
|
| + "try { } catch (arguments) { }",
|
| + "function eval() { }",
|
| + "function arguments() { }",
|
| + "function foo(eval) { }",
|
| + "function foo(arguments) { }",
|
| + "function foo(bar, eval) { }",
|
| + "function foo(bar, arguments) { }",
|
| + "eval = 1;",
|
| + "arguments = 1;",
|
| + "var foo = eval = 1;",
|
| + "var foo = arguments = 1;",
|
| + "++eval;",
|
| + "++arguments;",
|
| + "eval++;",
|
| + "arguments++;",
|
| + NULL
|
| + };
|
| +
|
| + RunParserSyncTest(context_data, statement_data, kError);
|
| +}
|
| +
|
| +
|
| +TEST(NoErrorsEvalAndArgumentsClassic) {
|
| + // Tests that both preparsing and parsing accept "eval" and "arguments" as
|
| + // identifiers when needed.
|
| + const char* context_data[][2] = {
|
| + { "", "" },
|
| + { "function test_func() {", "}"},
|
| + { NULL, NULL }
|
| + };
|
| +
|
| + const char* statement_data[] = {
|
| + "var eval;",
|
| + "var arguments",
|
| + "var foo, eval;",
|
| + "var foo, arguments;",
|
| + "try { } catch (eval) { }",
|
| + "try { } catch (arguments) { }",
|
| + "function eval() { }",
|
| + "function arguments() { }",
|
| + "function foo(eval) { }",
|
| + "function foo(arguments) { }",
|
| + "function foo(bar, eval) { }",
|
| + "function foo(bar, arguments) { }",
|
| + "eval = 1;",
|
| + "arguments = 1;",
|
| + "var foo = eval = 1;",
|
| + "var foo = arguments = 1;",
|
| + "++eval;",
|
| + "++arguments;",
|
| + "eval++;",
|
| + "arguments++;",
|
| + NULL
|
| + };
|
| +
|
| + RunParserSyncTest(context_data, statement_data, kSuccess);
|
| +}
|
| +
|
| +
|
| +TEST(NoErrorsEvalAndArgumentsStrict) {
|
| + const char* context_data[][2] = {
|
| + { "\"use strict\";", "" },
|
| + { "function test_func() { \"use strict\";", "}" },
|
| + { NULL, NULL }
|
| + };
|
| +
|
| + const char* statement_data[] = {
|
| + "eval;",
|
| + "arguments;",
|
| + "var foo = eval;",
|
| + "var foo = arguments;",
|
| + "var foo = { eval: 1 };",
|
| + "var foo = { arguments: 1 };",
|
| + "var foo = { }; foo.eval = {};",
|
| + "var foo = { }; foo.arguments = {};",
|
| + NULL
|
| + };
|
| +
|
| + RunParserSyncTest(context_data, statement_data, kSuccess);
|
| +}
|
| +
|
| +
|
| +TEST(ErrorsFutureStrictReservedWords) {
|
| + // Tests that both preparsing and parsing produce the right kind of errors for
|
| + // using future strict reserved words as identifiers. Without the strict mode,
|
| + // it's ok to use future strict reserved words as identifiers. With the strict
|
| + // mode, it isn't.
|
| + const char* context_data[][2] = {
|
| + { "\"use strict\";", "" },
|
| + { "function test_func() {\"use strict\"; ", "}"},
|
| + { NULL, NULL }
|
| + };
|
| +
|
| + const char* statement_data[] = {
|
| + "var interface;",
|
| + "var foo, interface;",
|
| + "try { } catch (interface) { }",
|
| + "function interface() { }",
|
| + "function foo(interface) { }",
|
| + "function foo(bar, interface) { }",
|
| + "interface = 1;",
|
| + "var foo = interface = 1;",
|
| + "++interface;",
|
| + "interface++;",
|
| + NULL
|
| + };
|
| +
|
| + RunParserSyncTest(context_data, statement_data, kError);
|
| +}
|
| +
|
| +
|
| +TEST(NoErrorsFutureStrictReservedWords) {
|
| + const char* context_data[][2] = {
|
| + { "", "" },
|
| + { "function test_func() {", "}"},
|
| + { NULL, NULL }
|
| + };
|
| +
|
| + const char* statement_data[] = {
|
| + "var interface;",
|
| + "var foo, interface;",
|
| + "try { } catch (interface) { }",
|
| + "function interface() { }",
|
| + "function foo(interface) { }",
|
| + "function foo(bar, interface) { }",
|
| + "interface = 1;",
|
| + "var foo = interface = 1;",
|
| + "++interface;",
|
| + "interface++;",
|
| + NULL
|
| + };
|
| +
|
| + RunParserSyncTest(context_data, statement_data, kSuccess);
|
| +}
|
| +
|
| +
|
| +TEST(ErrorsReservedWords) {
|
| + // Tests that both preparsing and parsing produce the right kind of errors for
|
| + // using future reserved words as identifiers. These tests don't depend on the
|
| + // strict mode.
|
| + const char* context_data[][2] = {
|
| + { "", "" },
|
| + { "\"use strict\";", "" },
|
| + { "var eval; function test_func() {", "}"},
|
| + { "var eval; function test_func() {\"use strict\"; ", "}"},
|
| + { NULL, NULL }
|
| + };
|
| +
|
| + const char* statement_data[] = {
|
| + "var super;",
|
| + "var foo, super;",
|
| + "try { } catch (super) { }",
|
| + "function super() { }",
|
| + "function foo(super) { }",
|
| + "function foo(bar, super) { }",
|
| + "super = 1;",
|
| + "var foo = super = 1;",
|
| + "++super;",
|
| + "super++;",
|
| + "function foo super",
|
| + NULL
|
| + };
|
| +
|
| + RunParserSyncTest(context_data, statement_data, kError);
|
| +}
|
| +
|
| +
|
| +TEST(NoErrorsYieldClassic) {
|
| + // In classic mode, it's okay to use "yield" as identifier, *except* inside a
|
| + // generator (see next test).
|
| + const char* context_data[][2] = {
|
| + { "", "" },
|
| + { "function is_not_gen() {", "}" },
|
| + { NULL, NULL }
|
| + };
|
| +
|
| + const char* statement_data[] = {
|
| + "var yield;",
|
| + "var foo, yield;",
|
| + "try { } catch (yield) { }",
|
| + "function yield() { }",
|
| + "function foo(yield) { }",
|
| + "function foo(bar, yield) { }",
|
| + "yield = 1;",
|
| + "var foo = yield = 1;",
|
| + "++yield;",
|
| + "yield++;",
|
| + NULL
|
| + };
|
| +
|
| + RunParserSyncTest(context_data, statement_data, kSuccess);
|
| +}
|
| +
|
| +
|
| +TEST(ErrorsYieldClassicGenerator) {
|
| + const char* context_data[][2] = {
|
| + { "function * is_gen() {", "}" },
|
| + { NULL, NULL }
|
| + };
|
| +
|
| + const char* statement_data[] = {
|
| + "var yield;",
|
| + "var foo, yield;",
|
| + "try { } catch (yield) { }",
|
| + "function yield() { }",
|
| + // BUG: These should not be allowed, but they are (if kAllowGenerators is
|
| + // set)
|
| + // "function foo(yield) { }",
|
| + // "function foo(bar, yield) { }",
|
| + "yield = 1;",
|
| + "var foo = yield = 1;",
|
| + "++yield;",
|
| + "yield++;",
|
| + NULL
|
| + };
|
| +
|
| + // If generators are not allowed, the error will be produced at the '*' token,
|
| + // so this test works both with and without the kAllowGenerators flag.
|
| + RunParserSyncTest(context_data, statement_data, kError);
|
| +}
|
| +
|
| +
|
| +TEST(ErrorsYieldStrict) {
|
| + const char* context_data[][2] = {
|
| + { "\"use strict\";", "" },
|
| + { "\"use strict\"; function is_not_gen() {", "}" },
|
| + { "function test_func() {\"use strict\"; ", "}"},
|
| + { NULL, NULL }
|
| + };
|
| +
|
| + const char* statement_data[] = {
|
| + "var yield;",
|
| + "var foo, yield;",
|
| + "try { } catch (yield) { }",
|
| + "function yield() { }",
|
| + "function foo(yield) { }",
|
| + "function foo(bar, yield) { }",
|
| + "yield = 1;",
|
| + "var foo = yield = 1;",
|
| + "++yield;",
|
| + "yield++;",
|
| + NULL
|
| + };
|
| +
|
| + RunParserSyncTest(context_data, statement_data, kError);
|
| +}
|
| +
|
| +
|
| +TEST(ErrorsYield) {
|
| + const char* context_data[][2] = {
|
| + { "function * is_gen() {", "}" },
|
| + { NULL, NULL }
|
| + };
|
| +
|
| + const char* statement_data[] = {
|
| + "yield 2;", // this is legal inside generator
|
| + "yield * 2;", // this is legal inside generator
|
| + NULL
|
| + };
|
| +
|
| + // Here we cannot assert that there is no error, since there will be without
|
| + // the kAllowGenerators flag. However, we test that Parser and PreParser
|
| + // produce the same errors.
|
| + RunParserSyncTest(context_data, statement_data, kSuccessOrError);
|
| +}
|
| +
|
| +
|
| +TEST(ErrorsNameOfStrictFunction) {
|
| + // Tests that illegal tokens as names of a strict function produce the correct
|
| + // errors.
|
| + const char* context_data[][2] = {
|
| + { "", ""},
|
| + { "\"use strict\";", ""},
|
| + { NULL, NULL }
|
| + };
|
| +
|
| + const char* statement_data[] = {
|
| + "function eval() {\"use strict\";}",
|
| + "function arguments() {\"use strict\";}",
|
| + "function interface() {\"use strict\";}",
|
| + "function yield() {\"use strict\";}",
|
| + // Future reserved words are always illegal
|
| + "function super() { }",
|
| + "function super() {\"use strict\";}",
|
| + NULL
|
| + };
|
| +
|
| + RunParserSyncTest(context_data, statement_data, kError);
|
| +}
|
| +
|
| +
|
| +TEST(NoErrorsNameOfStrictFunction) {
|
| + const char* context_data[][2] = {
|
| + { "", ""},
|
| + { NULL, NULL }
|
| + };
|
| +
|
| + const char* statement_data[] = {
|
| + "function eval() { }",
|
| + "function arguments() { }",
|
| + "function interface() { }",
|
| + "function yield() { }",
|
| + NULL
|
| + };
|
| +
|
| + RunParserSyncTest(context_data, statement_data, kSuccess);
|
| +}
|
| +
|
| +
|
| +
|
| +TEST(ErrorsIllegalWordsAsLabelsClassic) {
|
| + // Using future reserved words as labels is always an error.
|
| + const char* context_data[][2] = {
|
| + { "", ""},
|
| + { "function test_func() {", "}" },
|
| + { NULL, NULL }
|
| + };
|
| +
|
| + const char* statement_data[] = {
|
| + "super: while(true) { break super; }",
|
| + NULL
|
| + };
|
| +
|
| + RunParserSyncTest(context_data, statement_data, kError);
|
| +}
|
| +
|
| +
|
| +TEST(ErrorsIllegalWordsAsLabelsStrict) {
|
| + // Tests that illegal tokens as labels produce the correct errors.
|
| + const char* context_data[][2] = {
|
| + { "\"use strict\";", "" },
|
| + { "function test_func() {\"use strict\"; ", "}"},
|
| + { NULL, NULL }
|
| + };
|
| +
|
| + const char* statement_data[] = {
|
| + "super: while(true) { break super; }",
|
| + "interface: while(true) { break interface; }",
|
| + "yield: while(true) { break yield; }",
|
| + NULL
|
| + };
|
| +
|
| + RunParserSyncTest(context_data, statement_data, kError);
|
| +}
|
| +
|
| +
|
| +TEST(NoErrorsIllegalWordsAsLabels) {
|
| + // Using eval and arguments as labels is legal even in strict mode.
|
| + const char* context_data[][2] = {
|
| + { "", ""},
|
| + { "function test_func() {", "}" },
|
| + { "\"use strict\";", "" },
|
| + { "\"use strict\"; function test_func() {", "}" },
|
| + { NULL, NULL }
|
| + };
|
| +
|
| + const char* statement_data[] = {
|
| + "mylabel: while(true) { break mylabel; }",
|
| + "eval: while(true) { break eval; }",
|
| + "arguments: while(true) { break arguments; }",
|
| + NULL
|
| + };
|
| +
|
| + RunParserSyncTest(context_data, statement_data, kSuccess);
|
| +}
|
| +
|
| +
|
| +TEST(ErrorsParenthesizedLabels) {
|
| + // Parenthesized identifiers shouldn't be recognized as labels.
|
| + const char* context_data[][2] = {
|
| + { "", ""},
|
| + { "function test_func() {", "}" },
|
| + { NULL, NULL }
|
| + };
|
| +
|
| + const char* statement_data[] = {
|
| + "(mylabel): while(true) { break mylabel; }",
|
| + NULL
|
| + };
|
| +
|
| + RunParserSyncTest(context_data, statement_data, kError);
|
| +}
|
| +
|
| +
|
| +TEST(NoErrorsParenthesizedDirectivePrologue) {
|
| + // Parenthesized directive prologue shouldn't be recognized.
|
| + const char* context_data[][2] = {
|
| + { "", ""},
|
| + { NULL, NULL }
|
| + };
|
| +
|
| + const char* statement_data[] = {
|
| + "(\"use strict\"); var eval;",
|
| + NULL
|
| + };
|
| +
|
| + RunParserSyncTest(context_data, statement_data, kSuccess);
|
| +}
|
| +
|
| +
|
| +TEST(ErrorsNotAnIdentifierName) {
|
| + const char* context_data[][2] = {
|
| + { "", ""},
|
| + { "\"use strict\";", ""},
|
| + { NULL, NULL }
|
| + };
|
| +
|
| + const char* statement_data[] = {
|
| + "var foo = {}; foo.{;",
|
| + "var foo = {}; foo.};",
|
| + "var foo = {}; foo.=;",
|
| + "var foo = {}; foo.888;",
|
| + "var foo = {}; foo.-;",
|
| + "var foo = {}; foo.--;",
|
| + NULL
|
| + };
|
| +
|
| + RunParserSyncTest(context_data, statement_data, kError);
|
| +}
|
| +
|
| +
|
| +TEST(NoErrorsIdentifierNames) {
|
| + // Keywords etc. are valid as property names.
|
| + const char* context_data[][2] = {
|
| + { "", ""},
|
| + { "\"use strict\";", ""},
|
| + { NULL, NULL }
|
| + };
|
| +
|
| + const char* statement_data[] = {
|
| + "var foo = {}; foo.if;",
|
| + "var foo = {}; foo.yield;",
|
| + "var foo = {}; foo.super;",
|
| + "var foo = {}; foo.interface;",
|
| + "var foo = {}; foo.eval;",
|
| + "var foo = {}; foo.arguments;",
|
| + NULL
|
| + };
|
| +
|
| + RunParserSyncTest(context_data, statement_data, kSuccess);
|
| +}
|
| +
|
| +
|
| +TEST(DontRegressPreParserDataSizes) {
|
| + // These tests make sure that PreParser doesn't start producing less data.
|
| +
|
| + v8::V8::Initialize();
|
| +
|
| + int marker;
|
| + CcTest::i_isolate()->stack_guard()->SetStackLimit(
|
| + reinterpret_cast<uintptr_t>(&marker) - 128 * 1024);
|
| +
|
| + struct TestCase {
|
| + const char* program;
|
| + int symbols;
|
| + int functions;
|
| + } test_cases[] = {
|
| + // Labels, variables and functions are recorded as symbols.
|
| + {"{label: 42}", 1, 0}, {"{label: 42; label2: 43}", 2, 0},
|
| + {"var x = 42;", 1, 0}, {"var x = 42, y = 43;", 2, 0},
|
| + {"function foo() {}", 1, 1}, {"function foo() {} function bar() {}", 2, 2},
|
| + // Labels, variables and functions insize lazy functions are not recorded.
|
| + {"function lazy() { var a, b, c; }", 1, 1},
|
| + {"function lazy() { a: 1; b: 2; c: 3; }", 1, 1},
|
| + {"function lazy() { function a() {} function b() {} function c() {} }", 1,
|
| + 1},
|
| + {NULL, 0, 0}
|
| + };
|
| + // Each function adds 5 elements to the preparse function data.
|
| + const int kDataPerFunction = 5;
|
| +
|
| + uintptr_t stack_limit = CcTest::i_isolate()->stack_guard()->real_climit();
|
| + for (int i = 0; test_cases[i].program; i++) {
|
| + const char* program = test_cases[i].program;
|
| + i::Utf8ToUtf16CharacterStream stream(
|
| + reinterpret_cast<const i::byte*>(program),
|
| + static_cast<unsigned>(strlen(program)));
|
| + i::CompleteParserRecorder log;
|
| + i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
|
| + scanner.Initialize(&stream);
|
| +
|
| + i::PreParser preparser(&scanner, &log, stack_limit);
|
| + preparser.set_allow_lazy(true);
|
| + preparser.set_allow_natives_syntax(true);
|
| + i::PreParser::PreParseResult result = preparser.PreParseProgram();
|
| + CHECK_EQ(i::PreParser::kPreParseSuccess, result);
|
| + if (log.symbol_ids() != test_cases[i].symbols) {
|
| + i::OS::Print(
|
| + "Expected preparse data for program:\n"
|
| + "\t%s\n"
|
| + "to contain %d symbols, however, received %d symbols.\n",
|
| + program, test_cases[i].symbols, log.symbol_ids());
|
| + CHECK(false);
|
| + }
|
| + if (log.function_position() != test_cases[i].functions * kDataPerFunction) {
|
| + i::OS::Print(
|
| + "Expected preparse data for program:\n"
|
| + "\t%s\n"
|
| + "to contain %d functions, however, received %d functions.\n",
|
| + program, test_cases[i].functions,
|
| + log.function_position() / kDataPerFunction);
|
| + CHECK(false);
|
| + }
|
| + i::ScriptDataImpl data(log.ExtractData());
|
| + CHECK(!data.has_error());
|
| + }
|
| +}
|
| +
|
| +
|
| +TEST(FunctionDeclaresItselfStrict) {
|
| + // Tests that we produce the right kinds of errors when a function declares
|
| + // itself strict (we cannot produce there errors as soon as we see the
|
| + // offending identifiers, because we don't know at that point whether the
|
| + // function is strict or not).
|
| + const char* context_data[][2] = {
|
| + {"function eval() {", "}"},
|
| + {"function arguments() {", "}"},
|
| + {"function yield() {", "}"},
|
| + {"function interface() {", "}"},
|
| + {"function foo(eval) {", "}"},
|
| + {"function foo(arguments) {", "}"},
|
| + {"function foo(yield) {", "}"},
|
| + {"function foo(interface) {", "}"},
|
| + {"function foo(bar, eval) {", "}"},
|
| + {"function foo(bar, arguments) {", "}"},
|
| + {"function foo(bar, yield) {", "}"},
|
| + {"function foo(bar, interface) {", "}"},
|
| + {"function foo(bar, bar) {", "}"},
|
| + { NULL, NULL }
|
| + };
|
| +
|
| + const char* strict_statement_data[] = {
|
| + "\"use strict\";",
|
| + NULL
|
| + };
|
| +
|
| + const char* non_strict_statement_data[] = {
|
| + ";",
|
| + NULL
|
| + };
|
| +
|
| + RunParserSyncTest(context_data, strict_statement_data, kError);
|
| + RunParserSyncTest(context_data, non_strict_statement_data, kSuccess);
|
| +}
|
| +
|
| +
|
| +TEST(ErrorsTryWithoutCatchOrFinally) {
|
| + const char* context_data[][2] = {
|
| + {"", ""},
|
| + { NULL, NULL }
|
| + };
|
| +
|
| + const char* statement_data[] = {
|
| + "try { }",
|
| + "try { } foo();",
|
| + "try { } catch (e) foo();",
|
| + "try { } catch { }",
|
| + "try { } finally foo();",
|
| + NULL
|
| + };
|
| +
|
| + RunParserSyncTest(context_data, statement_data, kError);
|
| +}
|
| +
|
| +
|
| +TEST(NoErrorsTryCatchFinally) {
|
| + const char* context_data[][2] = {
|
| + {"", ""},
|
| + { NULL, NULL }
|
| + };
|
| +
|
| + const char* statement_data[] = {
|
| + "try { } catch (e) { }",
|
| + "try { } catch (e) { } finally { }",
|
| + "try { } finally { }",
|
| + NULL
|
| + };
|
| +
|
| + RunParserSyncTest(context_data, statement_data, kSuccess);
|
| +}
|
|
|