| Index: test/cctest/test-parsing.cc
|
| diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc
|
| index 3556c649f11bcc9bfef78dbc70d1210749e22f97..d33d0377c939b1de6bd4271f382b91cde5d9b257 100644
|
| --- a/test/cctest/test-parsing.cc
|
| +++ b/test/cctest/test-parsing.cc
|
| @@ -917,6 +917,122 @@ static int Utf8LengthHelper(const char* s) {
|
| }
|
|
|
|
|
| +TEST(ScopeUsesThisAndArguments) {
|
| + static const struct {
|
| + const char* prefix;
|
| + const char* suffix;
|
| + } surroundings[] = {
|
| + { "function f() {", "}" },
|
| + { "var f = () => {", "}" },
|
| + };
|
| +
|
| + static const struct {
|
| + const char* body;
|
| + bool uses_this;
|
| + bool uses_arguments;
|
| + bool inner_uses_this;
|
| + bool inner_uses_arguments;
|
| + } source_data[] = {
|
| + { "",
|
| + false, false, false, false },
|
| + { "return this",
|
| + true, false, false, false },
|
| + { "return arguments",
|
| + false, true, false, false },
|
| + { "return arguments[0]",
|
| + false, true, false, false },
|
| + { "return this + arguments[0]",
|
| + true, true, false, false },
|
| + { "return x => this + x",
|
| + false, false, true, false },
|
| + { "this.foo = 42;",
|
| + true, false, false, false },
|
| + { "this.foo();",
|
| + true, false, false, false },
|
| + { "if (foo()) { this.f() }",
|
| + true, false, false, false },
|
| + { "if (arguments.length) { this.f() }",
|
| + true, true, false, false },
|
| + { "while (true) { this.f() }",
|
| + true, false, false, false },
|
| + { "if (true) { while (true) this.foo(arguments) }",
|
| + true, true, false, false },
|
| + // Multiple nesting levels must work as well.
|
| + { "while (true) { while (true) { while (true) return this } }",
|
| + true, false, false, false },
|
| + { "if (1) { return () => { while (true) new this() } }",
|
| + false, false, true, false },
|
| + // Note that propagation of the inner_uses_this() value does not
|
| + // cross boundaries of normal functions onto parent scopes.
|
| + { "return function (x) { return this + x }",
|
| + false, false, false, false },
|
| + { "var x = function () { this.foo = 42 };",
|
| + false, false, false, false },
|
| + { "if (1) { return function () { while (true) new this() } }",
|
| + false, false, false, false },
|
| + { "return function (x) { return () => this }",
|
| + false, false, false, false },
|
| + // Flags must be correctly set when using block scoping.
|
| + { "\"use strict\"; while (true) { let x; this, arguments; }",
|
| + false, false, true, true },
|
| + { "\"use strict\"; if (foo()) { let x; this.f() }",
|
| + false, false, true, false },
|
| + { "\"use strict\"; if (1) {"
|
| + " let x; return function () { return this + arguments }"
|
| + "}",
|
| + false, false, false, false },
|
| + };
|
| +
|
| + i::Isolate* isolate = CcTest::i_isolate();
|
| + i::Factory* factory = isolate->factory();
|
| +
|
| + v8::HandleScope handles(CcTest::isolate());
|
| + v8::Handle<v8::Context> context = v8::Context::New(CcTest::isolate());
|
| + v8::Context::Scope context_scope(context);
|
| +
|
| + isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
|
| + 128 * 1024);
|
| +
|
| + for (unsigned j = 0; j < arraysize(surroundings); ++j) {
|
| + for (unsigned i = 0; i < arraysize(source_data); ++i) {
|
| + int kProgramByteSize = i::StrLength(surroundings[j].prefix) +
|
| + i::StrLength(surroundings[j].suffix) +
|
| + i::StrLength(source_data[i].body);
|
| + i::ScopedVector<char> program(kProgramByteSize + 1);
|
| + i::SNPrintF(program, "%s%s%s", surroundings[j].prefix,
|
| + source_data[i].body, surroundings[j].suffix);
|
| + i::Handle<i::String> source =
|
| + factory->NewStringFromUtf8(i::CStrVector(program.start()))
|
| + .ToHandleChecked();
|
| + i::Handle<i::Script> script = factory->NewScript(source);
|
| + i::CompilationInfoWithZone info(script);
|
| + i::Parser::ParseInfo parse_info = {isolate->stack_guard()->real_climit(),
|
| + isolate->heap()->HashSeed(),
|
| + isolate->unicode_cache()};
|
| + i::Parser parser(&info, &parse_info);
|
| + parser.set_allow_arrow_functions(true);
|
| + parser.set_allow_harmony_scoping(true);
|
| + info.MarkAsGlobal();
|
| + parser.Parse();
|
| + CHECK(i::Rewriter::Rewrite(&info));
|
| + CHECK(i::Scope::Analyze(&info));
|
| + CHECK(info.function() != NULL);
|
| +
|
| + i::Scope* global_scope = info.function()->scope();
|
| + CHECK(global_scope->is_global_scope());
|
| + CHECK_EQ(1, global_scope->inner_scopes()->length());
|
| +
|
| + i::Scope* scope = global_scope->inner_scopes()->at(0);
|
| + CHECK_EQ(source_data[i].uses_this, scope->uses_this());
|
| + CHECK_EQ(source_data[i].uses_arguments, scope->uses_arguments());
|
| + CHECK_EQ(source_data[i].inner_uses_this, scope->inner_uses_this());
|
| + CHECK_EQ(source_data[i].inner_uses_arguments,
|
| + scope->inner_uses_arguments());
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| TEST(ScopePositions) {
|
| v8::internal::FLAG_harmony_scoping = true;
|
|
|
| @@ -974,11 +1090,10 @@ TEST(ScopePositions) {
|
| " infunction;\n"
|
| " }", "\n"
|
| " more;", i::FUNCTION_SCOPE, i::SLOPPY },
|
| - // TODO(aperez): Change to use i::ARROW_SCOPE when implemented
|
| { " start;\n", "(a,b) => a + b", "; more;",
|
| - i::FUNCTION_SCOPE, i::SLOPPY },
|
| + i::ARROW_SCOPE, i::SLOPPY },
|
| { " start;\n", "(a,b) => { return a+b; }", "\nmore;",
|
| - i::FUNCTION_SCOPE, i::SLOPPY },
|
| + i::ARROW_SCOPE, i::SLOPPY },
|
| { " start;\n"
|
| " (function fun", "(a,b) { infunction; }", ")();",
|
| i::FUNCTION_SCOPE, i::SLOPPY },
|
|
|