#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;
}
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
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;
if (!m_owner)
return;
- v8::HandleScope handleScope(toIsolate(executionContext()));
+ v8::HandleScope handleScope(m_scriptState->isolate());
if (V8PerContextData* perContextData = creationContextData())
perContextData->clearCustomElementBinding(m_owner);
}
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
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());
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);
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;
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);