Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / bindings / v8 / V8CustomElementLifecycleCallbacks.cpp
index da0a0a8..2585458 100644 (file)
 #include "bindings/v8/DOMDataStore.h"
 #include "bindings/v8/ScriptController.h"
 #include "bindings/v8/V8Binding.h"
-#include "bindings/v8/V8HiddenPropertyName.h"
+#include "bindings/v8/V8HiddenValue.h"
 #include "bindings/v8/V8PerContextData.h"
 #include "core/dom/ExecutionContext.h"
+#include "core/inspector/InspectorInstrumentation.h"
 #include "wtf/PassOwnPtr.h"
 
 namespace WebCore {
 
 #define CALLBACK_LIST(V)                  \
     V(created, Created)                   \
-    V(enteredView, EnteredView)           \
-    V(leftView, LeftView)                 \
+    V(attached, Attached)           \
+    V(detached, Detached)                 \
     V(attributeChanged, AttributeChanged)
 
-PassRefPtr<V8CustomElementLifecycleCallbacks> V8CustomElementLifecycleCallbacks::create(ExecutionContext* executionContext, v8::Handle<v8::Object> prototype, v8::Handle<v8::Function> created, v8::Handle<v8::Function> enteredView, v8::Handle<v8::Function> leftView, v8::Handle<v8::Function> attributeChanged)
+PassRefPtr<V8CustomElementLifecycleCallbacks> V8CustomElementLifecycleCallbacks::create(ExecutionContext* executionContext, v8::Handle<v8::Object> prototype, v8::Handle<v8::Function> created, v8::Handle<v8::Function> attached, v8::Handle<v8::Function> detached, v8::Handle<v8::Function> attributeChanged)
 {
     v8::Isolate* isolate = toIsolate(executionContext);
     // A given object can only be used as a Custom Element prototype
     // once; see customElementIsInterfacePrototypeObject
-#define SET_HIDDEN_PROPERTY(Value, Name) \
-    ASSERT(prototype->GetHiddenValue(V8HiddenPropertyName::customElement##Name(isolate)).IsEmpty()); \
+#define SET_HIDDEN_VALUE(Value, Name) \
+    ASSERT(V8HiddenValue::getHiddenValue(isolate, prototype, V8HiddenValue::customElement##Name(isolate)).IsEmpty()); \
     if (!Value.IsEmpty()) \
-        prototype->SetHiddenValue(V8HiddenPropertyName::customElement##Name(isolate), Value);
+        V8HiddenValue::setHiddenValue(isolate, prototype, V8HiddenValue::customElement##Name(isolate), Value);
 
-    CALLBACK_LIST(SET_HIDDEN_PROPERTY)
-#undef SET_HIDDEN_PROPERTY
+    CALLBACK_LIST(SET_HIDDEN_VALUE)
+#undef SET_HIDDEN_VALUE
 
-    return adoptRef(new V8CustomElementLifecycleCallbacks(executionContext, prototype, created, enteredView, leftView, attributeChanged));
+    return adoptRef(new V8CustomElementLifecycleCallbacks(executionContext, prototype, created, attached, detached, attributeChanged));
 }
 
-static CustomElementLifecycleCallbacks::CallbackType flagSet(v8::Handle<v8::Function> enteredView, v8::Handle<v8::Function> leftView, v8::Handle<v8::Function> attributeChanged)
+static CustomElementLifecycleCallbacks::CallbackType flagSet(v8::Handle<v8::Function> attached, v8::Handle<v8::Function> detached, v8::Handle<v8::Function> attributeChanged)
 {
     // V8 Custom Elements always run created to swizzle prototypes.
     int flags = CustomElementLifecycleCallbacks::Created;
 
-    if (!enteredView.IsEmpty())
-        flags |= CustomElementLifecycleCallbacks::EnteredView;
+    if (!attached.IsEmpty())
+        flags |= CustomElementLifecycleCallbacks::Attached;
 
-    if (!leftView.IsEmpty())
-        flags |= CustomElementLifecycleCallbacks::LeftView;
+    if (!detached.IsEmpty())
+        flags |= CustomElementLifecycleCallbacks::Detached;
 
     if (!attributeChanged.IsEmpty())
         flags |= CustomElementLifecycleCallbacks::AttributeChanged;
@@ -83,27 +84,27 @@ static CustomElementLifecycleCallbacks::CallbackType flagSet(v8::Handle<v8::Func
 }
 
 template <typename T>
-static void weakCallback(v8::Isolate*, v8::Persistent<T>*, ScopedPersistent<T>* handle)
+static void weakCallback(const v8::WeakCallbackData<T, ScopedPersistent<T> >& data)
 {
-    handle->clear();
+    data.GetParameter()->clear();
 }
 
-V8CustomElementLifecycleCallbacks::V8CustomElementLifecycleCallbacks(ExecutionContext* executionContext, v8::Handle<v8::Object> prototype, v8::Handle<v8::Function> created, v8::Handle<v8::Function> enteredView, v8::Handle<v8::Function> leftView, v8::Handle<v8::Function> attributeChanged)
-    : CustomElementLifecycleCallbacks(flagSet(enteredView, leftView, attributeChanged))
-    , ActiveDOMCallback(executionContext)
+V8CustomElementLifecycleCallbacks::V8CustomElementLifecycleCallbacks(ExecutionContext* executionContext, v8::Handle<v8::Object> prototype, v8::Handle<v8::Function> created, v8::Handle<v8::Function> attached, v8::Handle<v8::Function> detached, v8::Handle<v8::Function> attributeChanged)
+    : CustomElementLifecycleCallbacks(flagSet(attached, detached, attributeChanged))
+    , ContextLifecycleObserver(executionContext)
     , m_owner(0)
-    , m_world(DOMWrapperWorld::current())
-    , m_prototype(toIsolate(executionContext), prototype)
-    , m_created(toIsolate(executionContext), created)
-    , m_enteredView(toIsolate(executionContext), enteredView)
-    , m_leftView(toIsolate(executionContext), leftView)
-    , m_attributeChanged(toIsolate(executionContext), attributeChanged)
+    , m_scriptState(ScriptState::current(toIsolate(executionContext)))
+    , m_prototype(m_scriptState->isolate(), prototype)
+    , m_created(m_scriptState->isolate(), created)
+    , m_attached(m_scriptState->isolate(), attached)
+    , m_detached(m_scriptState->isolate(), detached)
+    , m_attributeChanged(m_scriptState->isolate(), attributeChanged)
 {
-    m_prototype.makeWeak(&m_prototype, weakCallback<v8::Object>);
+    m_prototype.setWeak(&m_prototype, weakCallback<v8::Object>);
 
 #define MAKE_WEAK(Var, _) \
     if (!m_##Var.isEmpty()) \
-        m_##Var.makeWeak(&m_##Var, weakCallback<v8::Function>);
+        m_##Var.setWeak(&m_##Var, weakCallback<v8::Function>);
 
     CALLBACK_LIST(MAKE_WEAK)
 #undef MAKE_WEAK
@@ -114,7 +115,7 @@ V8PerContextData* V8CustomElementLifecycleCallbacks::creationContextData()
     if (!executionContext())
         return 0;
 
-    v8::Handle<v8::Context> context = toV8Context(executionContext(), m_world.get());
+    v8::Handle<v8::Context> context = m_scriptState->context();
     if (context.IsEmpty())
         return 0;
 
@@ -126,7 +127,7 @@ V8CustomElementLifecycleCallbacks::~V8CustomElementLifecycleCallbacks()
     if (!m_owner)
         return;
 
-    v8::HandleScope handleScope(toIsolate(executionContext()));
+    v8::HandleScope handleScope(m_scriptState->isolate());
     if (V8PerContextData* perContextData = creationContextData())
         perContextData->clearCustomElementBinding(m_owner);
 }
@@ -149,20 +150,20 @@ bool V8CustomElementLifecycleCallbacks::setBinding(CustomElementDefinition* owne
 
 void V8CustomElementLifecycleCallbacks::created(Element* element)
 {
-    if (!canInvokeCallback())
+    // FIXME: callbacks while paused should be queued up for execution to
+    // continue then be delivered in order rather than delivered immediately.
+    // Bug 329665 tracks similar behavior for other synchronous events.
+    if (!executionContext() || executionContext()->activeDOMObjectsAreStopped())
         return;
 
     element->setCustomElementState(Element::Upgraded);
 
-    v8::Isolate* isolate = toIsolate(executionContext());
-    v8::HandleScope handleScope(isolate);
-    v8::Handle<v8::Context> context = toV8Context(executionContext(), m_world.get());
-    if (context.IsEmpty())
+    if (m_scriptState->contextIsEmpty())
         return;
-
-    v8::Context::Scope scope(context);
-
-    v8::Handle<v8::Object> receiver = DOMDataStore::current(isolate)->get<V8Element>(element, isolate);
+    ScriptState::Scope scope(m_scriptState.get());
+    v8::Isolate* isolate = m_scriptState->isolate();
+    v8::Handle<v8::Context> context = m_scriptState->context();
+    v8::Handle<v8::Object> receiver = DOMDataStore::current(isolate).get<V8Element>(element, isolate);
     if (!receiver.IsEmpty()) {
         // Swizzle the prototype of the existing wrapper. We don't need to
         // worry about non-existent wrappers; they will get the right
@@ -182,34 +183,36 @@ void V8CustomElementLifecycleCallbacks::created(Element* element)
 
     ASSERT(!receiver.IsEmpty());
 
+    InspectorInstrumentation::willExecuteCustomElementCallback(element);
+
     v8::TryCatch exceptionCatcher;
     exceptionCatcher.SetVerbose(true);
     ScriptController::callFunction(executionContext(), callback, receiver, 0, 0, isolate);
 }
 
-void V8CustomElementLifecycleCallbacks::enteredView(Element* element)
+void V8CustomElementLifecycleCallbacks::attached(Element* element)
 {
-    call(m_enteredView, element);
+    call(m_attached, element);
 }
 
-void V8CustomElementLifecycleCallbacks::leftView(Element* element)
+void V8CustomElementLifecycleCallbacks::detached(Element* element)
 {
-    call(m_leftView, element);
+    call(m_detached, element);
 }
 
 void V8CustomElementLifecycleCallbacks::attributeChanged(Element* element, const AtomicString& name, const AtomicString& oldValue, const AtomicString& newValue)
 {
-    if (!canInvokeCallback())
+    // FIXME: callbacks while paused should be queued up for execution to
+    // continue then be delivered in order rather than delivered immediately.
+    // Bug 329665 tracks similar behavior for other synchronous events.
+    if (!executionContext() || executionContext()->activeDOMObjectsAreStopped())
         return;
 
-    v8::Isolate* isolate = toIsolate(executionContext());
-    v8::HandleScope handleScope(isolate);
-    v8::Handle<v8::Context> context = toV8Context(executionContext(), m_world.get());
-    if (context.IsEmpty())
+    if (m_scriptState->contextIsEmpty())
         return;
-
-    v8::Context::Scope scope(context);
-
+    ScriptState::Scope scope(m_scriptState.get());
+    v8::Isolate* isolate = m_scriptState->isolate();
+    v8::Handle<v8::Context> context = m_scriptState->context();
     v8::Handle<v8::Object> receiver = toV8(element, context->Global(), isolate).As<v8::Object>();
     ASSERT(!receiver.IsEmpty());
 
@@ -218,11 +221,13 @@ void V8CustomElementLifecycleCallbacks::attributeChanged(Element* element, const
         return;
 
     v8::Handle<v8::Value> argv[] = {
-        v8String(name, isolate),
-        oldValue.isNull() ? v8::Handle<v8::Value>(v8::Null(isolate)) : v8::Handle<v8::Value>(v8String(oldValue, isolate)),
-        newValue.isNull() ? v8::Handle<v8::Value>(v8::Null(isolate)) : v8::Handle<v8::Value>(v8String(newValue, isolate))
+        v8String(isolate, name),
+        oldValue.isNull() ? v8::Handle<v8::Value>(v8::Null(isolate)) : v8::Handle<v8::Value>(v8String(isolate, oldValue)),
+        newValue.isNull() ? v8::Handle<v8::Value>(v8::Null(isolate)) : v8::Handle<v8::Value>(v8String(isolate, newValue))
     };
 
+    InspectorInstrumentation::willExecuteCustomElementCallback(element);
+
     v8::TryCatch exceptionCatcher;
     exceptionCatcher.SetVerbose(true);
     ScriptController::callFunction(executionContext(), callback, receiver, WTF_ARRAY_LENGTH(argv), argv, isolate);
@@ -230,17 +235,17 @@ void V8CustomElementLifecycleCallbacks::attributeChanged(Element* element, const
 
 void V8CustomElementLifecycleCallbacks::call(const ScopedPersistent<v8::Function>& weakCallback, Element* element)
 {
-    if (!canInvokeCallback())
+    // FIXME: callbacks while paused should be queued up for execution to
+    // continue then be delivered in order rather than delivered immediately.
+    // Bug 329665 tracks similar behavior for other synchronous events.
+    if (!executionContext() || executionContext()->activeDOMObjectsAreStopped())
         return;
 
-    v8::HandleScope handleScope(toIsolate(executionContext()));
-    v8::Handle<v8::Context> context = toV8Context(executionContext(), m_world.get());
-    if (context.IsEmpty())
+    if (m_scriptState->contextIsEmpty())
         return;
-
-    v8::Context::Scope scope(context);
-    v8::Isolate* isolate = context->GetIsolate();
-
+    ScriptState::Scope scope(m_scriptState.get());
+    v8::Isolate* isolate = m_scriptState->isolate();
+    v8::Handle<v8::Context> context = m_scriptState->context();
     v8::Handle<v8::Function> callback = weakCallback.newLocal(isolate);
     if (callback.IsEmpty())
         return;
@@ -248,6 +253,8 @@ void V8CustomElementLifecycleCallbacks::call(const ScopedPersistent<v8::Function
     v8::Handle<v8::Object> receiver = toV8(element, context->Global(), isolate).As<v8::Object>();
     ASSERT(!receiver.IsEmpty());
 
+    InspectorInstrumentation::willExecuteCustomElementCallback(element);
+
     v8::TryCatch exceptionCatcher;
     exceptionCatcher.SetVerbose(true);
     ScriptController::callFunction(executionContext(), callback, receiver, 0, 0, isolate);