Browse Source

Wrap callbacks with v8::Locker.

In browser process, because of the use of v8::Locker in ProxyResolverV8,
creating HandleScope requires entering locker first, so in browser
process we should just use v8::Locker whenever we need to use V8 in a
callback called from non-V8 places (like dialog's callback, work pushed
to MessageLoop).

But also notice that the renderer process doesn't use v8::Locker, so we
have to be careful not to use it, otherwise blink would crash when
creating HandleScope.
Cheng Zhao 11 years ago
parent
commit
d63de1ae15

+ 2 - 0
browser/api/atom_api_dialog.cc

@@ -19,7 +19,9 @@ namespace {
 
 template<typename T>
 void CallV8Function(const RefCountedV8Function& callback, T arg) {
+  v8::Locker locker(node_isolate);
   v8::HandleScope handle_scope(node_isolate);
+
   v8::Handle<v8::Value> value = ToV8Value(arg);
   callback->NewHandle(node_isolate)->Call(
       v8::Context::GetCurrent()->Global(), 1, &value);

+ 9 - 0
browser/api/atom_api_menu.cc

@@ -24,6 +24,7 @@ v8::Handle<v8::Value> CallDelegate(v8::Handle<v8::Value> default_value,
                                    v8::Handle<v8::Object> menu,
                                    const char* method,
                                    int command_id) {
+  v8::Locker locker(node_isolate);
   v8::HandleScope handle_scope(node_isolate);
 
   v8::Handle<v8::Value> delegate = menu->Get(v8::String::New("delegate"));
@@ -52,6 +53,7 @@ Menu::~Menu() {
 }
 
 bool Menu::IsCommandIdChecked(int command_id) const {
+  v8::Locker locker(node_isolate);
   v8::HandleScope handle_scope(node_isolate);
   return CallDelegate(v8::False(),
                       const_cast<Menu*>(this)->handle(),
@@ -60,6 +62,7 @@ bool Menu::IsCommandIdChecked(int command_id) const {
 }
 
 bool Menu::IsCommandIdEnabled(int command_id) const {
+  v8::Locker locker(node_isolate);
   v8::HandleScope handle_scope(node_isolate);
   return CallDelegate(v8::True(),
                       const_cast<Menu*>(this)->handle(),
@@ -68,6 +71,7 @@ bool Menu::IsCommandIdEnabled(int command_id) const {
 }
 
 bool Menu::IsCommandIdVisible(int command_id) const {
+  v8::Locker locker(node_isolate);
   v8::HandleScope handle_scope(node_isolate);
   return CallDelegate(v8::True(),
                       const_cast<Menu*>(this)->handle(),
@@ -77,6 +81,7 @@ bool Menu::IsCommandIdVisible(int command_id) const {
 
 bool Menu::GetAcceleratorForCommandId(int command_id,
                                       ui::Accelerator* accelerator) {
+  v8::Locker locker(node_isolate);
   v8::HandleScope handle_scope(node_isolate);
   v8::Handle<v8::Value> shortcut = CallDelegate(v8::Undefined(),
                                                 handle(),
@@ -91,6 +96,7 @@ bool Menu::GetAcceleratorForCommandId(int command_id,
 }
 
 bool Menu::IsItemForCommandIdDynamic(int command_id) const {
+  v8::Locker locker(node_isolate);
   v8::HandleScope handle_scope(node_isolate);
   return CallDelegate(v8::False(),
                       const_cast<Menu*>(this)->handle(),
@@ -99,6 +105,7 @@ bool Menu::IsItemForCommandIdDynamic(int command_id) const {
 }
 
 string16 Menu::GetLabelForCommandId(int command_id) const {
+  v8::Locker locker(node_isolate);
   v8::HandleScope handle_scope(node_isolate);
   return FromV8Value(CallDelegate(v8::False(),
                                   const_cast<Menu*>(this)->handle(),
@@ -107,6 +114,7 @@ string16 Menu::GetLabelForCommandId(int command_id) const {
 }
 
 string16 Menu::GetSublabelForCommandId(int command_id) const {
+  v8::Locker locker(node_isolate);
   v8::HandleScope handle_scope(node_isolate);
   return FromV8Value(CallDelegate(v8::False(),
                                   const_cast<Menu*>(this)->handle(),
@@ -115,6 +123,7 @@ string16 Menu::GetSublabelForCommandId(int command_id) const {
 }
 
 void Menu::ExecuteCommand(int command_id, int event_flags) {
+  v8::Locker locker(node_isolate);
   v8::HandleScope handle_scope(node_isolate);
   CallDelegate(v8::False(), handle(), "executeCommand", command_id);
 }

+ 2 - 0
browser/api/atom_api_protocol.cc

@@ -35,6 +35,7 @@ static const char* kEarlyUseProtocolError = "This method can only be used"
 
 // Emit an event for the protocol module.
 void EmitEventInUI(const std::string& event, const std::string& parameter) {
+  v8::Locker locker(node_isolate);
   v8::HandleScope handle_scope(node_isolate);
 
   v8::Handle<v8::Value> argv[] = {
@@ -72,6 +73,7 @@ class CustomProtocolRequestJob : public AdapterRequestJob {
   virtual void GetJobTypeInUI() OVERRIDE {
     DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
 
+    v8::Locker locker(node_isolate);
     v8::HandleScope handle_scope(node_isolate);
 
     // Call the JS handler.

+ 1 - 0
browser/api/atom_api_window.cc

@@ -92,6 +92,7 @@ void Window::OnRendererCrashed() {
 
 void Window::OnCapturePageDone(const RefCountedV8Function& callback,
                                const std::vector<unsigned char>& data) {
+  v8::Locker locker(node_isolate);
   v8::HandleScope handle_scope(node_isolate);
 
   v8::Local<v8::Value> buffer = node::Buffer::New(

+ 2 - 0
browser/api/atom_browser_bindings.cc

@@ -25,6 +25,7 @@ void AtomBrowserBindings::OnRendererMessage(int process_id,
                                             int routing_id,
                                             const string16& channel,
                                             const base::ListValue& args) {
+  v8::Locker locker(node_isolate);
   v8::HandleScope handle_scope(node_isolate);
 
   scoped_ptr<V8ValueConverter> converter(new V8ValueConverter);
@@ -58,6 +59,7 @@ void AtomBrowserBindings::OnRendererMessageSync(
     const base::ListValue& args,
     NativeWindow* sender,
     IPC::Message* message) {
+  v8::Locker locker(node_isolate);
   v8::HandleScope handle_scope(node_isolate);
 
   scoped_ptr<V8ValueConverter> converter(new V8ValueConverter);

+ 1 - 0
browser/atom_browser_main_parts.cc

@@ -51,6 +51,7 @@ void AtomBrowserMainParts::PostEarlyInitialization() {
   v8::V8::Initialize();
 
   // Create context.
+  v8::Locker locker(node_isolate);
   v8::HandleScope handle_scope(node_isolate);
   v8::Local<v8::Context> context = v8::Context::New(node_isolate);
 

+ 10 - 0
common/api/atom_api_event_emitter.cc

@@ -21,6 +21,11 @@ EventEmitter::EventEmitter(v8::Handle<v8::Object> wrapper) {
 }
 
 EventEmitter::~EventEmitter() {
+  // Use Locker in browser process.
+  scoped_ptr<v8::Locker> locker;
+  if (node::g_standalone_mode)
+    locker.reset(new v8::Locker(node_isolate));
+
   // Clear the aligned pointer, it should have been done by ObjectWrap but
   // somehow node v0.11.x changed this behaviour.
   v8::HandleScope handle_scope(node_isolate);
@@ -33,6 +38,11 @@ bool EventEmitter::Emit(const std::string& name) {
 }
 
 bool EventEmitter::Emit(const std::string& name, base::ListValue* args) {
+  // Use Locker in browser process.
+  scoped_ptr<v8::Locker> locker;
+  if (node::g_standalone_mode)
+    locker.reset(new v8::Locker(node_isolate));
+
   v8::HandleScope handle_scope(node_isolate);
 
   v8::Handle<v8::Context> context = v8::Context::GetCurrent();

+ 5 - 0
common/node_bindings.cc

@@ -194,6 +194,11 @@ void NodeBindings::RunMessageLoop() {
 void NodeBindings::UvRunOnce() {
   DCHECK(!is_browser_ || BrowserThread::CurrentlyOn(BrowserThread::UI));
 
+  // Use Locker in browser process.
+  scoped_ptr<v8::Locker> locker;
+  if (is_browser_)
+    locker.reset(new v8::Locker(node_isolate));
+
   v8::HandleScope handle_scope(node_isolate);
 
   // Enter node context while dealing with uv events, by default the global