Commit df179704 authored by gsathya's avatar gsathya Committed by Commit bot

[promisehook] Fire init hook for promise subclass

Add test as well.
Add regression test for passing uninitialized promises to init hook

BUG=v8:4643

Review-Url: https://codereview.chromium.org/2578173004
Cr-Commit-Position: refs/heads/master@{#41982}
parent 224d3764
...@@ -672,7 +672,7 @@ TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) { ...@@ -672,7 +672,7 @@ TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) {
Node* const is_debug_active = IsDebugActive(); Node* const is_debug_active = IsDebugActive();
Label if_targetisnotmodified(this), Label if_targetisnotmodified(this),
if_targetismodified(this, Label::kDeferred), run_executor(this), if_targetismodified(this, Label::kDeferred), run_executor(this),
debug_push(this, Label::kDeferred), init(this); debug_push(this), init(this);
Branch(WordEqual(promise_fun, new_target), &if_targetisnotmodified, Branch(WordEqual(promise_fun, new_target), &if_targetisnotmodified,
&if_targetismodified); &if_targetismodified);
...@@ -685,9 +685,6 @@ TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) { ...@@ -685,9 +685,6 @@ TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) {
{ {
Node* const instance = AllocateJSPromise(context); Node* const instance = AllocateJSPromise(context);
var_result.Bind(instance); var_result.Bind(instance);
GotoUnless(IsPromiseHookEnabled(), &init);
CallRuntime(Runtime::kPromiseHookInit, context, instance,
UndefinedConstant());
Goto(&init); Goto(&init);
} }
...@@ -704,11 +701,15 @@ TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) { ...@@ -704,11 +701,15 @@ TF_BUILTIN(PromiseConstructor, PromiseBuiltinsAssembler) {
Bind(&init); Bind(&init);
{ {
PromiseInit(var_result.value()); PromiseInit(var_result.value());
Branch(is_debug_active, &debug_push, &run_executor); GotoUnless(IsPromiseHookEnabled(), &debug_push);
CallRuntime(Runtime::kPromiseHookInit, context, var_result.value(),
UndefinedConstant());
Goto(&debug_push);
} }
Bind(&debug_push); Bind(&debug_push);
{ {
GotoUnless(is_debug_active, &run_executor);
CallRuntime(Runtime::kDebugPushPromise, context, var_result.value()); CallRuntime(Runtime::kDebugPushPromise, context, var_result.value());
Goto(&run_executor); Goto(&run_executor);
} }
......
...@@ -18225,15 +18225,27 @@ TEST(PromiseHook) { ...@@ -18225,15 +18225,27 @@ TEST(PromiseHook) {
v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext(); v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
promise_hook_data = new PromiseHookData(); promise_hook_data = new PromiseHookData();
isolate->SetPromiseHook(CustomPromiseHook);
// Test that an initialized promise is passed to init. Other hooks
// can not have un initialized promise.
promise_hook_data->check_value = false;
CompileRun("var p = new Promise(() => {});");
auto init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust());
auto init_promise_obj = v8::Local<v8::Promise>::Cast(init_promise);
CHECK(init_promise_obj->State() == v8::Promise::PromiseState::kPending);
CHECK_EQ(false, init_promise_obj->HasHandler());
promise_hook_data->Reset();
promise_hook_data->promise_hook_value = "fulfilled"; promise_hook_data->promise_hook_value = "fulfilled";
const char* source = const char* source =
"var resolve, value = ''; \n" "var resolve, value = ''; \n"
"var p = new Promise(r => resolve = r); \n"; "var p = new Promise(r => resolve = r); \n";
isolate->SetPromiseHook(CustomPromiseHook);
CompileRun(source); CompileRun(source);
auto init_promise = global->Get(context, v8_str("init")).ToLocalChecked(); init_promise = global->Get(context, v8_str("init")).ToLocalChecked();
CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust()); CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust());
CHECK_EQ(1, promise_hook_data->promise_hook_count); CHECK_EQ(1, promise_hook_data->promise_hook_count);
CHECK_EQ(0, promise_hook_data->parent_promise_count); CHECK_EQ(0, promise_hook_data->parent_promise_count);
...@@ -18426,7 +18438,40 @@ TEST(PromiseHook) { ...@@ -18426,7 +18438,40 @@ TEST(PromiseHook) {
v8_str(promise_hook_data->promise_hook_value.c_str())) v8_str(promise_hook_data->promise_hook_value.c_str()))
.FromJust()); .FromJust());
promise_hook_data->Reset();
promise_hook_data->promise_hook_value = "subclass";
source =
"var resolve, value = '';\n"
"class MyPromise extends Promise { \n"
" then(onFulfilled, onRejected) { \n"
" return super.then(onFulfilled, onRejected); \n"
" };\n"
"};\n"
"var p = new MyPromise(r => resolve = r);\n";
CompileRun(source);
// 1) init hook (p)
CHECK_EQ(1, promise_hook_data->promise_hook_count);
CompileRun("var p1 = p.then(() => value = 'subclass');\n");
// 2) init hook (p1)
CHECK_EQ(2, promise_hook_data->promise_hook_count);
CompileRun("resolve();\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());
// 3) resolve hook (p)
// 4) before hook (p)
// 5) after hook (p)
// 6) resolve hook (p1)
CHECK_EQ(6, promise_hook_data->promise_hook_count);
delete promise_hook_data; delete promise_hook_data;
isolate->SetPromiseHook(nullptr);
} }
void AnalyzeStackOfDynamicScriptWithSourceURL( void AnalyzeStackOfDynamicScriptWithSourceURL(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment