Chromium Code Reviews| Index: test/cctest/test-api.cc |
| diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc |
| index 1fb5e5620a684dba9a23af511eaffcf54e10a47b..edbdd87b2d785c85a373ec5c440edbfcad9e443a 100644 |
| --- a/test/cctest/test-api.cc |
| +++ b/test/cctest/test-api.cc |
| @@ -18139,6 +18139,172 @@ TEST(InlineScriptWithSourceURLInStackTrace) { |
| CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined()); |
| } |
| +void SetPromise(const char* name, v8::Local<v8::Promise> promise) { |
| + CcTest::global() |
| + ->Set(CcTest::isolate()->GetCurrentContext(), v8_str(name), promise) |
| + .FromJust(); |
| +} |
| + |
| +class PromiseHookData { |
| + public: |
| + int before_hook_count = 0; |
| + int after_hook_count = 0; |
| + int promise_hook_count = 0; |
| + int parent_promise_count = 0; |
| + std::string promise_hook_value; |
| + |
| + void Reset() { |
| + before_hook_count = 0; |
| + after_hook_count = 0; |
| + promise_hook_count = 0; |
| + parent_promise_count = 0; |
| + promise_hook_value = ""; |
| + } |
| +}; |
| + |
| +PromiseHookData* promise_hook_data; |
| + |
| +void CustomPromiseHook(v8::PromiseHookType type, v8::Local<v8::Promise> promise, |
| + v8::Local<v8::Value> parentPromise) { |
| + promise_hook_data->promise_hook_count++; |
| + switch (type) { |
| + case v8::PromiseHookType::kInit: |
| + SetPromise("init", promise); |
| + |
| + if (!parentPromise->IsUndefined()) { |
| + promise_hook_data->parent_promise_count++; |
| + SetPromise("parent", v8::Local<v8::Promise>::Cast(parentPromise)); |
| + } |
| + |
| + break; |
| + case v8::PromiseHookType::kResolve: |
| + SetPromise("resolve", promise); |
| + break; |
| + case v8::PromiseHookType::kBefore: |
| + promise_hook_data->before_hook_count++; |
| + CHECK(promise_hook_data->before_hook_count > |
| + promise_hook_data->after_hook_count); |
| + CHECK(CcTest::global() |
| + ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("value")) |
| + .ToLocalChecked() |
| + ->Equals(CcTest::isolate()->GetCurrentContext(), v8_str("")) |
| + .FromJust()); |
| + SetPromise("before", promise); |
| + break; |
| + case v8::PromiseHookType::kAfter: |
| + promise_hook_data->after_hook_count++; |
| + CHECK(promise_hook_data->after_hook_count <= |
| + promise_hook_data->before_hook_count); |
| + CHECK(CcTest::global() |
| + ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("value")) |
| + .ToLocalChecked() |
| + ->Equals(CcTest::isolate()->GetCurrentContext(), |
| + v8_str(promise_hook_data->promise_hook_value.c_str())) |
| + .FromJust()); |
| + SetPromise("after", promise); |
| + break; |
| + } |
| +} |
| + |
| +TEST(PromiseHook) { |
| + LocalContext env; |
| + v8::Isolate* isolate = env->GetIsolate(); |
| + v8::HandleScope scope(isolate); |
| + |
| + v8::Local<v8::Object> global = CcTest::global(); |
| + v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext(); |
| + |
| + promise_hook_data = new PromiseHookData(); |
| + promise_hook_data->promise_hook_value = "fulfilled"; |
| + const char* source = |
| + "var resolve, value = ''; \n" |
| + "var p = new Promise(r => resolve = r); \n"; |
| + |
| + isolate->SetPromiseHook(CustomPromiseHook); |
| + |
| + CompileRun(source); |
| + auto init_promise = global->Get(context, v8_str("init")).ToLocalChecked(); |
| + CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust()); |
| + CHECK_EQ(1, promise_hook_data->promise_hook_count); |
| + CHECK_EQ(0, promise_hook_data->parent_promise_count); |
| + |
| + CompileRun("var p1 = p.then(() => { value = 'fulfilled'; }); \n"); |
| + init_promise = global->Get(context, v8_str("init")).ToLocalChecked(); |
| + auto parent_promise = global->Get(context, v8_str("parent")).ToLocalChecked(); |
| + CHECK(GetPromise("p1")->Equals(env.local(), init_promise).FromJust()); |
| + CHECK(GetPromise("p")->Equals(env.local(), parent_promise).FromJust()); |
| + CHECK_EQ(2, promise_hook_data->promise_hook_count); |
| + CHECK_EQ(1, promise_hook_data->parent_promise_count); |
| + |
| + CompileRun("resolve(); \n"); |
| + auto resolve_promise = |
| + global->Get(context, v8_str("resolve")).ToLocalChecked(); |
| + auto before_promise = global->Get(context, v8_str("before")).ToLocalChecked(); |
| + auto after_promise = global->Get(context, v8_str("after")).ToLocalChecked(); |
| + CHECK(GetPromise("p")->Equals(env.local(), before_promise).FromJust()); |
| + CHECK(GetPromise("p")->Equals(env.local(), after_promise).FromJust()); |
| + CHECK(GetPromise("p1")->Equals(env.local(), resolve_promise).FromJust()); |
| + CHECK_EQ(6, promise_hook_data->promise_hook_count); |
| + |
| + promise_hook_data->Reset(); |
| + promise_hook_data->promise_hook_value = "rejected"; |
| + source = |
| + "var reject, value = ''; \n" |
| + "var p = new Promise((_, r) => reject = r); \n"; |
| + |
| + CompileRun(source); |
| + init_promise = global->Get(context, v8_str("init")).ToLocalChecked(); |
| + CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust()); |
| + CHECK_EQ(1, promise_hook_data->promise_hook_count); |
| + CHECK_EQ(0, promise_hook_data->parent_promise_count); |
| + |
| + CompileRun("var p1 = p.catch(() => { value = 'rejected'; }); \n"); |
| + init_promise = global->Get(context, v8_str("init")).ToLocalChecked(); |
| + parent_promise = global->Get(context, v8_str("parent")).ToLocalChecked(); |
| + CHECK(GetPromise("p1")->Equals(env.local(), init_promise).FromJust()); |
| + CHECK(GetPromise("p")->Equals(env.local(), parent_promise).FromJust()); |
| + CHECK_EQ(2, promise_hook_data->promise_hook_count); |
| + CHECK_EQ(1, promise_hook_data->parent_promise_count); |
| + |
| + CompileRun("reject(); \n"); |
| + resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked(); |
| + before_promise = global->Get(context, v8_str("before")).ToLocalChecked(); |
| + after_promise = global->Get(context, v8_str("after")).ToLocalChecked(); |
| + CHECK(GetPromise("p")->Equals(env.local(), before_promise).FromJust()); |
| + CHECK(GetPromise("p")->Equals(env.local(), after_promise).FromJust()); |
| + CHECK(GetPromise("p1")->Equals(env.local(), resolve_promise).FromJust()); |
| + CHECK_EQ(6, promise_hook_data->promise_hook_count); |
| + |
| + promise_hook_data->Reset(); |
| + promise_hook_data->promise_hook_value = "Promise.resolve"; |
| + source = |
| + "var value = ''; \n" |
| + "var p = Promise.resolve('Promise.resolve'); \n"; |
| + |
| + CompileRun(source); |
| + init_promise = global->Get(context, v8_str("init")).ToLocalChecked(); |
| + CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust()); |
| + // init hook and resolve hook |
| + CHECK_EQ(2, promise_hook_data->promise_hook_count); |
| + CHECK_EQ(0, promise_hook_data->parent_promise_count); |
| + resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked(); |
| + CHECK(GetPromise("p")->Equals(env.local(), resolve_promise).FromJust()); |
| + |
| + CompileRun("var p1 = p.then((v) => { value = v; }); \n"); |
| + init_promise = global->Get(context, v8_str("init")).ToLocalChecked(); |
| + resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked(); |
| + parent_promise = global->Get(context, v8_str("parent")).ToLocalChecked(); |
| + before_promise = global->Get(context, v8_str("before")).ToLocalChecked(); |
| + after_promise = global->Get(context, v8_str("after")).ToLocalChecked(); |
| + CHECK(GetPromise("p1")->Equals(env.local(), init_promise).FromJust()); |
| + CHECK(GetPromise("p1")->Equals(env.local(), resolve_promise).FromJust()); |
| + CHECK(GetPromise("p")->Equals(env.local(), parent_promise).FromJust()); |
| + CHECK(GetPromise("p")->Equals(env.local(), before_promise).FromJust()); |
| + CHECK(GetPromise("p")->Equals(env.local(), after_promise).FromJust()); |
| + CHECK_EQ(6, promise_hook_data->promise_hook_count); |
| + CHECK_EQ(1, promise_hook_data->parent_promise_count); |
| + delete promise_hook_data; |
| +} |
|
Dan Ehrenberg
2016/12/15 22:21:48
Do you think it might be useful to have an integra
gsathya
2016/12/16 00:55:16
Yes will do in a follow on patch.
|
| void AnalyzeStackOfDynamicScriptWithSourceURL( |
| const v8::FunctionCallbackInfo<v8::Value>& args) { |