| Index: test/cctest/test-parsing.cc
|
| diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc
|
| index d6e05d97cc7c367cea33d0743dd09047abfc110f..7a35ebe469b394c52a734fd9a6b36a49ca9c61e3 100644
|
| --- a/test/cctest/test-parsing.cc
|
| +++ b/test/cctest/test-parsing.cc
|
| @@ -3432,6 +3432,95 @@ TEST(InnerAssignment) {
|
| }
|
| }
|
|
|
| +TEST(MaybeAssignedParameters) {
|
| + i::Isolate* isolate = CcTest::i_isolate();
|
| + i::HandleScope scope(isolate);
|
| + LocalContext env;
|
| +
|
| + struct {
|
| + bool arg_assigned;
|
| + const char* source;
|
| + } tests[] = {
|
| + {false, "function f(arg) {}"},
|
| + {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=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)}"},
|
| + {false, "function f(...arg) {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)}"},
|
| + {true, "function f(arg) {g(arg); g(() => arg = 42); g(arg)}"},
|
| + {true, "function f(arg) {g(arg); g(() => eval('arg = 42')); g(arg)}"},
|
| + {true, "function f(arg) {g(arg); g(() => arguments[0] = 42); g(arg)}"},
|
| + {true, "function f(...arg) {g(arg); eval('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)}"},
|
| + };
|
| +
|
| + const char* suffix = "; f";
|
| +
|
| + for (unsigned i = 0; i < arraysize(tests); ++i) {
|
| + bool assigned = tests[i].arg_assigned;
|
| + const char* source = tests[i].source;
|
| + for (unsigned allow_lazy = 0; allow_lazy < 2; ++allow_lazy) {
|
| + i::ScopedVector<char> program(Utf8LengthHelper(source) +
|
| + Utf8LengthHelper(suffix) + 1);
|
| + i::SNPrintF(program, "%s%s", source, suffix);
|
| + i::Zone zone(isolate->allocator(), ZONE_NAME);
|
| + std::unique_ptr<i::ParseInfo> info;
|
| + 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));
|
| + info->set_allow_lazy_parsing(allow_lazy);
|
| + CHECK(i::parsing::ParseFunction(info.get()));
|
| + CHECK(i::Compiler::Analyze(info.get()));
|
| + CHECK_NOT_NULL(info->literal());
|
| +
|
| + i::Scope* scope = info->literal()->scope();
|
| + CHECK(!scope->AsDeclarationScope()->was_lazily_parsed());
|
| + 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,
|
|
|