Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(447)

Side by Side Diff: Source/bindings/v8/V8AbstractEventListener.cpp

Issue 293053007: V8AbstractEventListener should hold a ScriptState (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/bindings/v8/V8AbstractEventListener.h ('k') | Source/bindings/v8/V8ErrorHandler.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2006, 2007, 2008, 2009 Google Inc. All rights reserved. 2 * Copyright (C) 2006, 2007, 2008, 2009 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 25 matching lines...) Expand all
36 #include "bindings/v8/V8Binding.h" 36 #include "bindings/v8/V8Binding.h"
37 #include "bindings/v8/V8EventListenerList.h" 37 #include "bindings/v8/V8EventListenerList.h"
38 #include "bindings/v8/V8HiddenValue.h" 38 #include "bindings/v8/V8HiddenValue.h"
39 #include "core/events/BeforeUnloadEvent.h" 39 #include "core/events/BeforeUnloadEvent.h"
40 #include "core/events/Event.h" 40 #include "core/events/Event.h"
41 #include "core/inspector/InspectorCounters.h" 41 #include "core/inspector/InspectorCounters.h"
42 #include "core/workers/WorkerGlobalScope.h" 42 #include "core/workers/WorkerGlobalScope.h"
43 43
44 namespace WebCore { 44 namespace WebCore {
45 45
46 V8AbstractEventListener::V8AbstractEventListener(bool isAttribute, DOMWrapperWor ld& world, v8::Isolate* isolate) 46 V8AbstractEventListener::V8AbstractEventListener(bool isAttribute, ScriptState* scriptState)
47 : EventListener(JSEventListenerType) 47 : EventListener(JSEventListenerType)
48 , m_isAttribute(isAttribute) 48 , m_isAttribute(isAttribute)
49 , m_world(world) 49 , m_scriptState(scriptState)
50 , m_isolate(scriptState->isolate())
51 {
52 if (isMainThread())
53 InspectorCounters::incrementCounter(InspectorCounters::JSEventListenerCo unter);
54 }
55
56 V8AbstractEventListener::V8AbstractEventListener(bool isAttribute, v8::Isolate* isolate)
57 : EventListener(JSEventListenerType)
58 , m_isAttribute(isAttribute)
59 , m_scriptState(nullptr)
50 , m_isolate(isolate) 60 , m_isolate(isolate)
51 { 61 {
52 if (isMainThread()) 62 if (isMainThread())
53 InspectorCounters::incrementCounter(InspectorCounters::JSEventListenerCo unter); 63 InspectorCounters::incrementCounter(InspectorCounters::JSEventListenerCo unter);
54 } 64 }
55 65
56 V8AbstractEventListener::~V8AbstractEventListener() 66 V8AbstractEventListener::~V8AbstractEventListener()
57 { 67 {
58 if (!m_listener.isEmpty()) { 68 if (!m_listener.isEmpty()) {
59 v8::HandleScope scope(m_isolate); 69 v8::HandleScope scope(m_isolate);
60 V8EventListenerList::clearWrapper(m_listener.newLocal(m_isolate), m_isAt tribute, m_isolate); 70 V8EventListenerList::clearWrapper(m_listener.newLocal(isolate()), m_isAt tribute, isolate());
61 } 71 }
62 if (isMainThread()) 72 if (isMainThread())
63 InspectorCounters::decrementCounter(InspectorCounters::JSEventListenerCo unter); 73 InspectorCounters::decrementCounter(InspectorCounters::JSEventListenerCo unter);
64 } 74 }
65 75
66 void V8AbstractEventListener::handleEvent(ExecutionContext* context, Event* even t) 76 void V8AbstractEventListener::handleEvent(ExecutionContext* context, Event* even t)
67 { 77 {
68 // Don't reenter V8 if execution was terminated in this instance of V8. 78 // Don't reenter V8 if execution was terminated in this instance of V8.
69 if (context->isJSExecutionForbidden()) 79 if (context->isJSExecutionForbidden())
70 return; 80 return;
71 81
72 ASSERT(event); 82 ASSERT(event);
73 83
74 // The callback function on XMLHttpRequest can clear the event listener and destroys 'this' object. Keep a local reference to it. 84 // The callback function on XMLHttpRequest can clear the event listener and destroys 'this' object. Keep a local reference to it.
75 // See issue 889829. 85 // See issue 889829.
76 RefPtr<V8AbstractEventListener> protect(this); 86 RefPtr<V8AbstractEventListener> protect(this);
77 87
78 v8::HandleScope handleScope(m_isolate); 88 if (scriptState()->contextIsEmpty())
79
80 v8::Local<v8::Context> v8Context = toV8Context(context, world());
81 if (v8Context.IsEmpty())
82 return; 89 return;
83 90 ScriptState::Scope scope(scriptState());
84 // Enter the V8 context in which to perform the event handling.
85 v8::Context::Scope scope(v8Context);
86 91
87 // Get the V8 wrapper for the event object. 92 // Get the V8 wrapper for the event object.
88 v8::Isolate* isolate = v8Context->GetIsolate(); 93 v8::Handle<v8::Value> jsEvent = toV8(event, scriptState()->context()->Global (), isolate());
89 v8::Handle<v8::Value> jsEvent = toV8(event, v8::Handle<v8::Object>(), isolat e);
90 if (jsEvent.IsEmpty()) 94 if (jsEvent.IsEmpty())
91 return; 95 return;
92 invokeEventHandler(context, event, v8::Local<v8::Value>::New(isolate, jsEven t)); 96 invokeEventHandler(event, v8::Local<v8::Value>::New(isolate(), jsEvent));
93 } 97 }
94 98
95 void V8AbstractEventListener::setListenerObject(v8::Handle<v8::Object> listener) 99 void V8AbstractEventListener::setListenerObject(v8::Handle<v8::Object> listener)
96 { 100 {
97 m_listener.set(m_isolate, listener); 101 m_listener.set(isolate(), listener);
98 m_listener.setWeak(this, &setWeakCallback); 102 m_listener.setWeak(this, &setWeakCallback);
99 } 103 }
100 104
101 void V8AbstractEventListener::invokeEventHandler(ExecutionContext* context, Even t* event, v8::Local<v8::Value> jsEvent) 105 void V8AbstractEventListener::invokeEventHandler(Event* event, v8::Local<v8::Val ue> jsEvent)
102 { 106 {
103 // If jsEvent is empty, attempt to set it as a hidden value would crash v8. 107 // If jsEvent is empty, attempt to set it as a hidden value would crash v8.
104 if (jsEvent.IsEmpty()) 108 if (jsEvent.IsEmpty())
105 return; 109 return;
106 110
107 v8::Local<v8::Context> v8Context = toV8Context(context, world());
108 if (v8Context.IsEmpty())
adamk 2014/05/21 10:51:06 I take it you removed this check because you've up
haraken 2014/05/21 11:15:31 Yes. Added the ASSERT.
109 return;
110 v8::Isolate* isolate = v8Context->GetIsolate();
111
112 v8::Local<v8::Value> returnValue; 111 v8::Local<v8::Value> returnValue;
113 { 112 {
114 // Catch exceptions thrown in the event handler so they do not propagate to javascript code that caused the event to fire. 113 // Catch exceptions thrown in the event handler so they do not propagate to javascript code that caused the event to fire.
115 v8::TryCatch tryCatch; 114 v8::TryCatch tryCatch;
116 tryCatch.SetVerbose(true); 115 tryCatch.SetVerbose(true);
117 116
118 // Save the old 'event' property so we can restore it later. 117 // Save the old 'event' property so we can restore it later.
119 v8::Local<v8::Value> savedEvent = V8HiddenValue::getHiddenValue(v8Contex t->GetIsolate(), v8Context->Global(), V8HiddenValue::event(isolate)); 118 v8::Local<v8::Value> savedEvent = V8HiddenValue::getHiddenValue(isolate( ), scriptState()->context()->Global(), V8HiddenValue::event(isolate()));
120 tryCatch.Reset(); 119 tryCatch.Reset();
121 120
122 // Make the event available in the global object, so DOMWindow can expos e it. 121 // Make the event available in the global object, so DOMWindow can expos e it.
123 V8HiddenValue::setHiddenValue(v8Context->GetIsolate(), v8Context->Global (), V8HiddenValue::event(isolate), jsEvent); 122 V8HiddenValue::setHiddenValue(isolate(), scriptState()->context()->Globa l(), V8HiddenValue::event(isolate()), jsEvent);
124 tryCatch.Reset(); 123 tryCatch.Reset();
125 124
126 returnValue = callListenerFunction(context, jsEvent, event); 125 returnValue = callListenerFunction(scriptState()->executionContext(), js Event, event);
127 if (tryCatch.HasCaught()) 126 if (tryCatch.HasCaught())
128 event->target()->uncaughtExceptionInEventHandler(); 127 event->target()->uncaughtExceptionInEventHandler();
129 128
130 if (!tryCatch.CanContinue()) { // Result of TerminateExecution(). 129 if (!tryCatch.CanContinue()) { // Result of TerminateExecution().
131 if (context->isWorkerGlobalScope()) 130 if (scriptState()->executionContext()->isWorkerGlobalScope())
132 toWorkerGlobalScope(context)->script()->forbidExecution(); 131 toWorkerGlobalScope(scriptState()->executionContext())->script() ->forbidExecution();
133 return; 132 return;
134 } 133 }
135 tryCatch.Reset(); 134 tryCatch.Reset();
136 135
137 // Restore the old event. This must be done for all exit paths through t his method. 136 // Restore the old event. This must be done for all exit paths through t his method.
138 if (savedEvent.IsEmpty()) 137 if (savedEvent.IsEmpty())
139 V8HiddenValue::setHiddenValue(v8Context->GetIsolate(), v8Context->Gl obal(), V8HiddenValue::event(isolate), v8::Undefined(v8Context->GetIsolate())); 138 V8HiddenValue::setHiddenValue(isolate(), scriptState()->context()->G lobal(), V8HiddenValue::event(isolate()), v8::Undefined(isolate()));
140 else 139 else
141 V8HiddenValue::setHiddenValue(v8Context->GetIsolate(), v8Context->Gl obal(), V8HiddenValue::event(isolate), savedEvent); 140 V8HiddenValue::setHiddenValue(isolate(), scriptState()->context()->G lobal(), V8HiddenValue::event(isolate()), savedEvent);
142 tryCatch.Reset(); 141 tryCatch.Reset();
143 } 142 }
144 143
145 if (returnValue.IsEmpty()) 144 if (returnValue.IsEmpty())
146 return; 145 return;
147 146
148 if (m_isAttribute && !returnValue->IsNull() && !returnValue->IsUndefined() & & event->isBeforeUnloadEvent()) { 147 if (m_isAttribute && !returnValue->IsNull() && !returnValue->IsUndefined() & & event->isBeforeUnloadEvent()) {
149 TOSTRING_VOID(V8StringResource<>, stringReturnValue, returnValue); 148 TOSTRING_VOID(V8StringResource<>, stringReturnValue, returnValue);
150 toBeforeUnloadEvent(event)->setReturnValue(stringReturnValue); 149 toBeforeUnloadEvent(event)->setReturnValue(stringReturnValue);
151 } 150 }
152 151
153 if (m_isAttribute && shouldPreventDefault(returnValue)) 152 if (m_isAttribute && shouldPreventDefault(returnValue))
154 event->preventDefault(); 153 event->preventDefault();
155 } 154 }
156 155
157 bool V8AbstractEventListener::shouldPreventDefault(v8::Local<v8::Value> returnVa lue) 156 bool V8AbstractEventListener::shouldPreventDefault(v8::Local<v8::Value> returnVa lue)
158 { 157 {
159 // Prevent default action if the return value is false in accord with the sp ec 158 // Prevent default action if the return value is false in accord with the sp ec
160 // http://www.w3.org/TR/html5/webappapis.html#event-handler-attributes 159 // http://www.w3.org/TR/html5/webappapis.html#event-handler-attributes
161 return returnValue->IsBoolean() && !returnValue->BooleanValue(); 160 return returnValue->IsBoolean() && !returnValue->BooleanValue();
162 } 161 }
163 162
164 v8::Local<v8::Object> V8AbstractEventListener::getReceiverObject(ExecutionContex t* context, Event* event) 163 v8::Local<v8::Object> V8AbstractEventListener::getReceiverObject(Event* event)
165 { 164 {
166 v8::Isolate* isolate = toV8Context(context, world())->GetIsolate(); 165 v8::Local<v8::Object> listener = m_listener.newLocal(isolate());
167 v8::Local<v8::Object> listener = m_listener.newLocal(isolate);
168 if (!m_listener.isEmpty() && !listener->IsFunction()) 166 if (!m_listener.isEmpty() && !listener->IsFunction())
169 return listener; 167 return listener;
170 168
171 EventTarget* target = event->currentTarget(); 169 EventTarget* target = event->currentTarget();
172 v8::Handle<v8::Value> value = toV8(target, v8::Handle<v8::Object>(), isolate ); 170 v8::Handle<v8::Value> value = toV8(target, scriptState()->context()->Global( ), isolate());
173 if (value.IsEmpty()) 171 if (value.IsEmpty())
174 return v8::Local<v8::Object>(); 172 return v8::Local<v8::Object>();
175 return v8::Local<v8::Object>::New(isolate, v8::Handle<v8::Object>::Cast(valu e)); 173 return v8::Local<v8::Object>::New(isolate(), v8::Handle<v8::Object>::Cast(va lue));
176 } 174 }
177 175
178 bool V8AbstractEventListener::belongsToTheCurrentWorld() const 176 bool V8AbstractEventListener::belongsToTheCurrentWorld() const
179 { 177 {
180 return m_isolate->InContext() && m_world == &DOMWrapperWorld::current(m_isol ate); 178 return isolate()->InContext() && &world() == &DOMWrapperWorld::current(isola te());
181 } 179 }
182 180
183 void V8AbstractEventListener::setWeakCallback(const v8::WeakCallbackData<v8::Obj ect, V8AbstractEventListener> &data) 181 void V8AbstractEventListener::setWeakCallback(const v8::WeakCallbackData<v8::Obj ect, V8AbstractEventListener> &data)
184 { 182 {
185 data.GetParameter()->m_listener.clear(); 183 data.GetParameter()->m_listener.clear();
186 } 184 }
187 185
188 } // namespace WebCore 186 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/bindings/v8/V8AbstractEventListener.h ('k') | Source/bindings/v8/V8ErrorHandler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698