Chromium Code Reviews| Index: test/cctest/test-parsing.cc |
| diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc |
| index d6e05d97cc7c367cea33d0743dd09047abfc110f..ea28058bb7d61c618804c6115442c6b27497ac10 100644 |
| --- a/test/cctest/test-parsing.cc |
| +++ b/test/cctest/test-parsing.cc |
| @@ -3432,6 +3432,104 @@ TEST(InnerAssignment) { |
| } |
| } |
| +TEST(MaybeAssignedParameters) { |
| + i::Isolate* isolate = CcTest::i_isolate(); |
| + i::Factory* factory = isolate->factory(); |
| + i::HandleScope scope(isolate); |
| + LocalContext env; |
| + |
| + struct { |
| + bool arg_assigned; |
| + const char* source; |
| + } tests[] = { |
| + {false, "(function f(arg) {})"}, |
|
marja
2016/12/15 13:35:29
Routing offline discussion here: The two cases you
|
| + {false, "(function f(arg) {g(arg)})"}, |
| + {false, "(function f(arg) {function h() { g(arg) }; h()})"}, |
| + {false, "(function f(arg) {function h() { g(arg) }; return h})"}, |
| + {false, "(function f(arg) {function h() { g(arg) }; return h})"}, |
|
gsathya
2016/12/15 14:05:31
isn't this same as the previous one?
|
| + {false, "(function f(arg=1) {})"}, |
| + {false, "(function f(arg=1) {g(arg)})"}, |
| + {false, |
| + "(function f(arg, arguments) {g(arg); arguments[0] = 42; g(arg)})"}, |
| + {false, |
| + "(function f(arg, ...arguments) {g(arg); arguments[0] = 42; g(arg)})"}, |
| + {false, |
| + "(function f(arg, arguments=[]) {g(arg); arguments[0] = 42; g(arg)})"}, |
| + |
| + // strict arguments object |
| + {false, "(function f(arg, x=1) {g(arg); arguments[0] = 42; g(arg)})"}, |
| + {false, "(function f(arg, ...x) {g(arg); arguments[0] = 42; g(arg)})"}, |
| + {false, "(function f(arg=1) {g(arg); arguments[0] = 42; g(arg)})"}, |
| + {false, |
| + "(function f(arg) {'use strict'; g(arg); arguments[0] = 42; g(arg)})"}, |
| + {false, "(function f(arg) {g(arg); f.arguments[0] = 42; g(arg)})"}, |
| + {false, |
| + "(function f(arg, args=arguments) {g(arg); args[0] = 42; g(arg)})"}, |
| + |
| + {true, "(function f(arg) {g(arg); arg = 42; g(arg)})"}, |
| + {true, "(function f(arg) {g(arg); eval('arg = 42'); g(arg)})"}, |
| + {true, "(function f(arg) {g(arg); var arg = 42; g(arg)})"}, |
| + {true, "(function f(arg, x=1) {g(arg); arg = 42; g(arg)})"}, |
| + {true, "(function f(arg, ...x) {g(arg); arg = 42; g(arg)})"}, |
| + {true, "(function f(arg=1) {g(arg); arg = 42; g(arg)})"}, |
| + {true, "(function f(arg) {'use strict'; g(arg); arg = 42; g(arg)})"}, |
| + {true, "(function f(arg, {a=(g(arg), arg=42)}) {g(arg)})"}, |
| + |
| + // sloppy arguments object |
| + {true, "(function f(arg) {g(arg); arguments[0] = 42; g(arg)})"}, |
| + {true, "(function f(arg) {g(arg); h(arguments); g(arg)})"}, |
| + {true, |
| + "(function f(arg) {((args) => {arguments[0] = 42})(arguments); " |
| + "g(arg)})"}, |
| + {true, "(function f(arg) {g(arg); eval('arguments[0] = 42'); g(arg)})"}, |
|
marja
2016/12/15 13:09:54
Can you add a test where arg is the rest parameter
|
| + }; |
| + |
| + for (unsigned i = 0; i < arraysize(tests); ++i) { |
| + bool assigned = tests[i].arg_assigned; |
| + const char* source = tests[i].source; |
| + int length = Utf8LengthHelper(source); |
| + for (unsigned lazy = 0; lazy < 2; ++lazy) { |
| + i::ScopedVector<char> program(length + 1); |
| + i::SNPrintF(program, "%s", source); |
| + i::Zone zone(isolate->allocator(), ZONE_NAME); |
| + std::unique_ptr<i::ParseInfo> info; |
| + if (lazy) { |
| + printf("%s\n", program.start()); |
| + v8::Local<v8::Value> v = CompileRun(program.start()); |
| + i::Handle<i::Object> o = v8::Utils::OpenHandle(*v); |
| + i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o); |
| + i::Handle<i::SharedFunctionInfo> shared = i::handle(f->shared()); |
| + info = std::unique_ptr<i::ParseInfo>(new i::ParseInfo(&zone, shared)); |
| + CHECK(i::parsing::ParseFunction(info.get())); |
| + } else { |
| + i::Handle<i::String> source = |
| + factory->InternalizeUtf8String(program.start()); |
| + source->PrintOn(stdout); |
| + printf("\n"); |
| + i::Handle<i::Script> script = factory->NewScript(source); |
| + info = std::unique_ptr<i::ParseInfo>(new i::ParseInfo(&zone, script)); |
| + info->set_allow_lazy_parsing(false); |
| + CHECK(i::parsing::ParseProgram(info.get())); |
| + } |
| + CHECK(i::Compiler::Analyze(info.get())); |
| + CHECK_NOT_NULL(info->literal()); |
| + |
| + i::Scope* scope = info->literal()->scope(); |
| + if (!lazy) { |
| + scope = scope->inner_scope(); |
| + } |
| + CHECK_NULL(scope->sibling()); |
| + CHECK(scope->is_function_scope()); |
| + const i::AstRawString* var_name = |
| + info->ast_value_factory()->GetOneByteString("arg"); |
| + i::Variable* var = scope->Lookup(var_name); |
| + CHECK(var->is_used() || !assigned); |
| + bool is_maybe_assigned = var->maybe_assigned() == i::kMaybeAssigned; |
| + CHECK_EQ(is_maybe_assigned, assigned); |
| + } |
| + } |
| +} |
| + |
| namespace { |
| i::Scope* DeserializeFunctionScope(i::Isolate* isolate, i::Zone* zone, |