|
Lines 52-58
class JSEventListener : public EventListener {
a/Source/WebCore/bindings/js/JSEventListener.h_sec1
|
| 52 |
DOMWrapperWorld& isolatedWorld() const { return m_isolatedWorld; } |
52 |
DOMWrapperWorld& isolatedWorld() const { return m_isolatedWorld; } |
| 53 |
|
53 |
|
| 54 |
JSC::JSObject* wrapper() const { return m_wrapper.get(); } |
54 |
JSC::JSObject* wrapper() const { return m_wrapper.get(); } |
| 55 |
void setWrapper(JSC::VM&, JSC::JSObject* wrapper) const { m_wrapper = JSC::Weak<JSC::JSObject>(wrapper); } |
|
|
| 56 |
|
55 |
|
| 57 |
virtual String sourceURL() const { return String(); } |
56 |
virtual String sourceURL() const { return String(); } |
| 58 |
virtual TextPosition sourcePosition() const { return TextPosition(); } |
57 |
virtual TextPosition sourcePosition() const { return TextPosition(); } |
|
Lines 66-75
class JSEventListener : public EventListener {
a/Source/WebCore/bindings/js/JSEventListener.h_sec2
|
| 66 |
protected: |
65 |
protected: |
| 67 |
JSEventListener(JSC::JSObject* function, JSC::JSObject* wrapper, bool isAttribute, DOMWrapperWorld&); |
66 |
JSEventListener(JSC::JSObject* function, JSC::JSObject* wrapper, bool isAttribute, DOMWrapperWorld&); |
| 68 |
void handleEvent(ScriptExecutionContext&, Event&) override; |
67 |
void handleEvent(ScriptExecutionContext&, Event&) override; |
|
|
68 |
void setWrapperWhenInitializingJSFunction(JSC::VM&, JSC::JSObject* wrapper) const { m_wrapper = JSC::Weak<JSC::JSObject>(wrapper); } |
| 69 |
|
69 |
|
| 70 |
private: |
70 |
private: |
| 71 |
mutable JSC::Weak<JSC::JSObject> m_jsFunction; |
71 |
mutable JSC::Weak<JSC::JSObject> m_jsFunction; |
| 72 |
mutable JSC::Weak<JSC::JSObject> m_wrapper; |
72 |
mutable JSC::Weak<JSC::JSObject> m_wrapper; |
|
|
73 |
mutable bool m_isInitialized { false }; |
| 73 |
|
74 |
|
| 74 |
bool m_isAttribute; |
75 |
bool m_isAttribute; |
| 75 |
Ref<DOMWrapperWorld> m_isolatedWorld; |
76 |
Ref<DOMWrapperWorld> m_isolatedWorld; |
|
Lines 95-122
inline JSC::JSObject* JSEventListener::jsFunction(ScriptExecutionContext& script
a/Source/WebCore/bindings/js/JSEventListener.h_sec3
|
| 95 |
{ |
96 |
{ |
| 96 |
// initializeJSFunction can trigger code that deletes this event listener |
97 |
// initializeJSFunction can trigger code that deletes this event listener |
| 97 |
// before we're done. It should always return null in this case. |
98 |
// before we're done. It should always return null in this case. |
|
|
99 |
JSC::VM& vm = m_isolatedWorld->vm(); |
| 98 |
auto protect = makeRef(const_cast<JSEventListener&>(*this)); |
100 |
auto protect = makeRef(const_cast<JSEventListener&>(*this)); |
| 99 |
JSC::Strong<JSC::JSObject> wrapper(m_isolatedWorld->vm(), m_wrapper.get()); |
101 |
JSC::Strong<JSC::JSObject> wrapper(vm, m_wrapper.get()); |
| 100 |
|
102 |
|
| 101 |
if (!m_jsFunction) { |
103 |
if (!m_isInitialized) { |
|
|
104 |
ASSERT(!m_jsFunction); |
| 102 |
auto* function = initializeJSFunction(scriptExecutionContext); |
105 |
auto* function = initializeJSFunction(scriptExecutionContext); |
| 103 |
if (auto* wrapper = m_wrapper.get()) |
106 |
if (function) { |
| 104 |
JSC::Heap::heap(wrapper)->writeBarrier(wrapper, function); |
107 |
m_jsFunction = JSC::Weak<JSC::JSObject>(function); |
| 105 |
m_jsFunction = JSC::Weak<JSC::JSObject>(function); |
108 |
// When JSFunction is initialized, initializeJSFunction must ensure that m_wrapper should be initialized too. |
|
|
109 |
ASSERT(m_wrapper); |
| 110 |
vm.heap.writeBarrier(m_wrapper.get(), function); |
| 111 |
m_isInitialized = true; |
| 112 |
} |
| 106 |
} |
113 |
} |
| 107 |
|
114 |
|
| 108 |
// Verify that we have a valid wrapper protecting our function from |
115 |
// m_wrapper and m_jsFunction are Weak<>. nullptr of these fields do not mean that this event-listener is not initialized yet. |
| 109 |
// garbage collection. That is except for when we're not in the normal |
116 |
// If this is initialized once, m_isInitialized should be true, and then m_wrapper and m_jsFunction must be alive. m_wrapper's |
| 110 |
// world and can have zombie m_jsFunctions. |
117 |
// liveness should be kept correctly by using ActiveDOMObject, output-constraints, etc. And m_jsFunction must be alive if m_wrapper |
| 111 |
ASSERT(!m_isolatedWorld->isNormal() || m_wrapper || !m_jsFunction); |
118 |
// is alive since JSEventListener marks m_jsFunction in JSEventListener::visitJSFunction if m_wrapper is alive. |
| 112 |
|
119 |
// If the event-listener is not initialized yet, we should skip invoking this event-listener. |
| 113 |
// If m_wrapper is null, then m_jsFunction is zombied, and should never be accessed. |
120 |
if (!m_isInitialized) |
| 114 |
if (!m_wrapper) |
|
|
| 115 |
return nullptr; |
121 |
return nullptr; |
| 116 |
|
122 |
|
| 117 |
// Try to verify that m_jsFunction wasn't recycled. (Not exact, since an |
123 |
ASSERT(m_wrapper); |
| 118 |
// event listener can be almost anything, but this makes test-writing easier). |
124 |
ASSERT(m_jsFunction); |
| 119 |
ASSERT(!m_jsFunction || static_cast<JSC::JSCell*>(m_jsFunction.get())->isObject()); |
125 |
// Ensure m_jsFunction is live JSObject as a quick sanity check (while it is already ensured by Weak<>). If this fails, this is possibly JSC GC side's bug. |
|
|
126 |
ASSERT(static_cast<JSC::JSCell*>(m_jsFunction.get())->isObject()); |
| 120 |
|
127 |
|
| 121 |
return m_jsFunction.get(); |
128 |
return m_jsFunction.get(); |
| 122 |
} |
129 |
} |