Commit 0e9ea48c authored by dgozman's avatar dgozman Committed by Commit bot

Introduce BeforeCallEnteredCallback.

This new callback is similar to CallCompletedCallback, but is executed before the call has been made.
Added Isolate* parameter to CallCompletedCallback, marking previous one as deprecated.

BUG=chromium:585949
LOG=Y

Review URL: https://codereview.chromium.org/1689863002

Cr-Commit-Position: refs/heads/master@{#34167}
parent b62bf1e6
......@@ -5009,8 +5009,10 @@ typedef void (*MemoryAllocationCallback)(ObjectSpace space,
AllocationAction action,
int size);
// --- Leave Script Callback ---
typedef void (*CallCompletedCallback)();
// --- Enter/Leave Script Callback ---
typedef void (*BeforeCallEnteredCallback)(Isolate*);
typedef void (*CallCompletedCallback)(Isolate*);
typedef void (*DeprecatedCallCompletedCallback)();
// --- Promise Reject Callback ---
enum PromiseRejectEvent {
......@@ -5812,6 +5814,19 @@ class V8_EXPORT Isolate {
*/
void SetEventLogger(LogEventCallback that);
/**
* Adds a callback to notify the host application right before a script
* is about to run. If a script re-enters the runtime during executing, the
* BeforeCallEnteredCallback is invoked for each re-entrance.
* Executing scripts inside the callback will re-trigger the callback.
*/
void AddBeforeCallEnteredCallback(BeforeCallEnteredCallback callback);
/**
* Removes callback that was installed by AddBeforeCallEnteredCallback.
*/
void RemoveBeforeCallEnteredCallback(BeforeCallEnteredCallback callback);
/**
* Adds a callback to notify the host application when a script finished
* running. If a script re-enters the runtime during executing, the
......@@ -5820,12 +5835,18 @@ class V8_EXPORT Isolate {
* further callbacks.
*/
void AddCallCompletedCallback(CallCompletedCallback callback);
V8_DEPRECATE_SOON(
"Use callback with parameter",
void AddCallCompletedCallback(DeprecatedCallCompletedCallback callback));
/**
* Removes callback that was installed by AddCallCompletedCallback.
*/
void RemoveCallCompletedCallback(CallCompletedCallback callback);
V8_DEPRECATE_SOON(
"Use callback with parameter",
void RemoveCallCompletedCallback(
DeprecatedCallCompletedCallback callback));
/**
* Set callback to notify about promise reject with no handler, or
......
......@@ -168,6 +168,7 @@ class CallDepthScope {
isolate_->IncrementJsCallsFromApiCounter();
isolate_->handle_scope_implementer()->IncrementCallDepth();
if (!context_.IsEmpty()) context_->Enter();
if (do_callback_) isolate_->FireBeforeCallEnteredCallback();
}
~CallDepthScope() {
if (!context_.IsEmpty()) context_->Exit();
......@@ -7372,6 +7373,20 @@ void Isolate::SetEventLogger(LogEventCallback that) {
}
void Isolate::AddBeforeCallEnteredCallback(BeforeCallEnteredCallback callback) {
if (callback == NULL) return;
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
isolate->AddBeforeCallEnteredCallback(callback);
}
void Isolate::RemoveBeforeCallEnteredCallback(
BeforeCallEnteredCallback callback) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
isolate->RemoveBeforeCallEnteredCallback(callback);
}
void Isolate::AddCallCompletedCallback(CallCompletedCallback callback) {
if (callback == NULL) return;
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
......@@ -7385,6 +7400,19 @@ void Isolate::RemoveCallCompletedCallback(CallCompletedCallback callback) {
}
void Isolate::AddCallCompletedCallback(
DeprecatedCallCompletedCallback callback) {
AddCallCompletedCallback(reinterpret_cast<CallCompletedCallback>(callback));
}
void Isolate::RemoveCallCompletedCallback(
DeprecatedCallCompletedCallback callback) {
RemoveCallCompletedCallback(
reinterpret_cast<CallCompletedCallback>(callback));
}
void Isolate::SetPromiseRejectCallback(PromiseRejectCallback callback) {
if (callback == NULL) return;
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
......
......@@ -2608,6 +2608,31 @@ Handle<JSObject> Isolate::GetSymbolRegistry() {
}
void Isolate::AddBeforeCallEnteredCallback(BeforeCallEnteredCallback callback) {
for (int i = 0; i < before_call_entered_callbacks_.length(); i++) {
if (callback == before_call_entered_callbacks_.at(i)) return;
}
before_call_entered_callbacks_.Add(callback);
}
void Isolate::RemoveBeforeCallEnteredCallback(
BeforeCallEnteredCallback callback) {
for (int i = 0; i < before_call_entered_callbacks_.length(); i++) {
if (callback == before_call_entered_callbacks_.at(i)) {
before_call_entered_callbacks_.Remove(i);
}
}
}
void Isolate::FireBeforeCallEnteredCallback() {
for (int i = 0; i < before_call_entered_callbacks_.length(); i++) {
before_call_entered_callbacks_.at(i)(reinterpret_cast<v8::Isolate*>(this));
}
}
void Isolate::AddCallCompletedCallback(CallCompletedCallback callback) {
for (int i = 0; i < call_completed_callbacks_.length(); i++) {
if (callback == call_completed_callbacks_.at(i)) return;
......@@ -2633,10 +2658,10 @@ void Isolate::FireCallCompletedCallback() {
if (!handle_scope_implementer()->CallDepthIsZero()) return;
if (run_microtasks) RunMicrotasks();
// Fire callbacks. Increase call depth to prevent recursive callbacks.
v8::Isolate::SuppressMicrotaskExecutionScope suppress(
reinterpret_cast<v8::Isolate*>(this));
v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(this);
v8::Isolate::SuppressMicrotaskExecutionScope suppress(isolate);
for (int i = 0; i < call_completed_callbacks_.length(); i++) {
call_completed_callbacks_.at(i)();
call_completed_callbacks_.at(i)(isolate);
}
}
......
......@@ -1055,6 +1055,10 @@ class Isolate {
void RemoveCallCompletedCallback(CallCompletedCallback callback);
void FireCallCompletedCallback();
void AddBeforeCallEnteredCallback(BeforeCallEnteredCallback callback);
void RemoveBeforeCallEnteredCallback(BeforeCallEnteredCallback callback);
void FireBeforeCallEnteredCallback();
void SetPromiseRejectCallback(PromiseRejectCallback callback);
void ReportPromiseReject(Handle<JSObject> promise, Handle<Object> value,
v8::PromiseRejectEvent event);
......@@ -1318,6 +1322,9 @@ class Isolate {
int next_unique_sfi_id_;
#endif
// List of callbacks before a Call starts execution.
List<BeforeCallEnteredCallback> before_call_entered_callbacks_;
// List of callbacks when a Call completes.
List<CallCompletedCallback> call_completed_callbacks_;
......
......@@ -20790,20 +20790,34 @@ THREADED_TEST(ForeignFunctionReceiver) {
uint8_t callback_fired = 0;
uint8_t before_call_entered_callback_count1 = 0;
uint8_t before_call_entered_callback_count2 = 0;
void CallCompletedCallback1() {
void CallCompletedCallback1(v8::Isolate*) {
v8::base::OS::Print("Firing callback 1.\n");
callback_fired ^= 1; // Toggle first bit.
}
void CallCompletedCallback2() {
void CallCompletedCallback2(v8::Isolate*) {
v8::base::OS::Print("Firing callback 2.\n");
callback_fired ^= 2; // Toggle second bit.
}
void BeforeCallEnteredCallback1(v8::Isolate*) {
v8::base::OS::Print("Firing before call entered callback 1.\n");
before_call_entered_callback_count1++;
}
void BeforeCallEnteredCallback2(v8::Isolate*) {
v8::base::OS::Print("Firing before call entered callback 2.\n");
before_call_entered_callback_count2++;
}
void RecursiveCall(const v8::FunctionCallbackInfo<v8::Value>& args) {
int32_t level =
args[0]->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust();
......@@ -20836,36 +20850,54 @@ TEST(CallCompletedCallback) {
env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback1);
env->GetIsolate()->AddCallCompletedCallback(CallCompletedCallback2);
env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback1);
env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback2);
env->GetIsolate()->AddBeforeCallEnteredCallback(BeforeCallEnteredCallback1);
v8::base::OS::Print("--- Script (1) ---\n");
callback_fired = 0;
before_call_entered_callback_count1 = 0;
before_call_entered_callback_count2 = 0;
Local<Script> script =
v8::Script::Compile(env.local(), v8_str("recursion(0)")).ToLocalChecked();
script->Run(env.local()).ToLocalChecked();
CHECK_EQ(3, callback_fired);
CHECK_EQ(4, before_call_entered_callback_count1);
CHECK_EQ(4, before_call_entered_callback_count2);
v8::base::OS::Print("\n--- Script (2) ---\n");
callback_fired = 0;
before_call_entered_callback_count1 = 0;
before_call_entered_callback_count2 = 0;
env->GetIsolate()->RemoveCallCompletedCallback(CallCompletedCallback1);
env->GetIsolate()->RemoveBeforeCallEnteredCallback(
BeforeCallEnteredCallback1);
script->Run(env.local()).ToLocalChecked();
CHECK_EQ(2, callback_fired);
CHECK_EQ(0, before_call_entered_callback_count1);
CHECK_EQ(4, before_call_entered_callback_count2);
v8::base::OS::Print("\n--- Function ---\n");
callback_fired = 0;
before_call_entered_callback_count1 = 0;
before_call_entered_callback_count2 = 0;
Local<Function> recursive_function = Local<Function>::Cast(
env->Global()->Get(env.local(), v8_str("recursion")).ToLocalChecked());
v8::Local<Value> args[] = {v8_num(0)};
recursive_function->Call(env.local(), env->Global(), 1, args)
.ToLocalChecked();
CHECK_EQ(2, callback_fired);
CHECK_EQ(0, before_call_entered_callback_count1);
CHECK_EQ(4, before_call_entered_callback_count2);
}
void CallCompletedCallbackNoException() {
void CallCompletedCallbackNoException(v8::Isolate*) {
v8::HandleScope scope(CcTest::isolate());
CompileRun("1+1;");
}
void CallCompletedCallbackException() {
void CallCompletedCallbackException(v8::Isolate*) {
v8::HandleScope scope(CcTest::isolate());
CompileRun("throw 'second exception';");
}
......
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