Guard against callback being called twice
This commit is contained in:
parent
96d53d279e
commit
ee51e37db7
3 changed files with 26 additions and 19 deletions
|
@ -21,12 +21,19 @@ struct CallbackHolder {
|
||||||
// Cached JavaScript version of |HandlerCallback|.
|
// Cached JavaScript version of |HandlerCallback|.
|
||||||
v8::Persistent<v8::FunctionTemplate> g_handler_callback_;
|
v8::Persistent<v8::FunctionTemplate> g_handler_callback_;
|
||||||
|
|
||||||
// Cached C++ version of |Function.prototype.bind|.
|
|
||||||
base::Callback<v8::Local<v8::Value>(
|
|
||||||
v8::Local<v8::Value>, v8::Local<v8::Value>, v8::Local<v8::Value>)> g_bind;
|
|
||||||
|
|
||||||
// The callback which is passed to |handler|.
|
// The callback which is passed to |handler|.
|
||||||
void HandlerCallback(v8::Local<v8::External> external, mate::Arguments* args) {
|
void HandlerCallback(v8::Isolate* isolate,
|
||||||
|
v8::Local<v8::External> external,
|
||||||
|
v8::Local<v8::Object> state,
|
||||||
|
mate::Arguments* args) {
|
||||||
|
// Check if the callback has already been called.
|
||||||
|
v8::Local<v8::String> called_symbol = mate::StringToSymbol(isolate, "called");
|
||||||
|
if (state->Has(called_symbol))
|
||||||
|
return; // no nothing
|
||||||
|
else
|
||||||
|
state->Set(called_symbol, v8::Boolean::New(isolate, true));
|
||||||
|
|
||||||
|
// If there is no argument passed then we failed.
|
||||||
scoped_ptr<CallbackHolder> holder(
|
scoped_ptr<CallbackHolder> holder(
|
||||||
static_cast<CallbackHolder*>(external->Value()));
|
static_cast<CallbackHolder*>(external->Value()));
|
||||||
CHECK(holder);
|
CHECK(holder);
|
||||||
|
@ -36,13 +43,14 @@ void HandlerCallback(v8::Local<v8::External> external, mate::Arguments* args) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pass whatever user passed to the actaul request job.
|
||||||
V8ValueConverter converter;
|
V8ValueConverter converter;
|
||||||
v8::Local<v8::Context> context = args->isolate()->GetCurrentContext();
|
v8::Local<v8::Context> context = args->isolate()->GetCurrentContext();
|
||||||
scoped_ptr<base::Value> options(converter.FromV8Value(value, context));
|
scoped_ptr<base::Value> options(converter.FromV8Value(value, context));
|
||||||
holder->callback.Run(true, options.Pass());
|
holder->callback.Run(true, options.Pass());
|
||||||
}
|
}
|
||||||
|
|
||||||
// func.bind(...).
|
// func.bind(func, ...).
|
||||||
template<typename... ArgTypes>
|
template<typename... ArgTypes>
|
||||||
v8::Local<v8::Value> BindFunctionWith(v8::Isolate* isolate,
|
v8::Local<v8::Value> BindFunctionWith(v8::Isolate* isolate,
|
||||||
v8::Local<v8::Context> context,
|
v8::Local<v8::Context> context,
|
||||||
|
@ -75,7 +83,8 @@ v8::MaybeLocal<v8::Value> GenerateCallback(v8::Isolate* isolate,
|
||||||
holder->callback = callback;
|
holder->callback = callback;
|
||||||
return BindFunctionWith(isolate, context,
|
return BindFunctionWith(isolate, context,
|
||||||
handler_callback->GetFunction(),
|
handler_callback->GetFunction(),
|
||||||
v8::External::New(isolate, holder));
|
v8::External::New(isolate, holder),
|
||||||
|
v8::Object::New(isolate));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -64,7 +64,7 @@ class JsAsker : public RequestJob {
|
||||||
// Called when the JS handler has sent the response, we need to decide whether
|
// Called when the JS handler has sent the response, we need to decide whether
|
||||||
// to start, or fail the job.
|
// to start, or fail the job.
|
||||||
void OnResponse(bool success, scoped_ptr<base::Value> options) {
|
void OnResponse(bool success, scoped_ptr<base::Value> options) {
|
||||||
if (success) {
|
if (success && options) {
|
||||||
StartAsync(options.Pass());
|
StartAsync(options.Pass());
|
||||||
} else {
|
} else {
|
||||||
RequestJob::NotifyStartError(
|
RequestJob::NotifyStartError(
|
||||||
|
|
|
@ -19,7 +19,6 @@ URLRequestStringJob::URLRequestStringJob(net::URLRequest* request,
|
||||||
}
|
}
|
||||||
|
|
||||||
void URLRequestStringJob::StartAsync(scoped_ptr<base::Value> options) {
|
void URLRequestStringJob::StartAsync(scoped_ptr<base::Value> options) {
|
||||||
if (options) {
|
|
||||||
if (options->IsType(base::Value::TYPE_DICTIONARY)) {
|
if (options->IsType(base::Value::TYPE_DICTIONARY)) {
|
||||||
base::DictionaryValue* dict =
|
base::DictionaryValue* dict =
|
||||||
static_cast<base::DictionaryValue*>(options.get());
|
static_cast<base::DictionaryValue*>(options.get());
|
||||||
|
@ -29,7 +28,6 @@ void URLRequestStringJob::StartAsync(scoped_ptr<base::Value> options) {
|
||||||
} else if (options->IsType(base::Value::TYPE_STRING)) {
|
} else if (options->IsType(base::Value::TYPE_STRING)) {
|
||||||
options->GetAsString(&data_);
|
options->GetAsString(&data_);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
net::URLRequestSimpleJob::Start();
|
net::URLRequestSimpleJob::Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue