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

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

Issue 18167006: Implement Custom Elements' entered and left document callbacks. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Feedback Created 7 years, 5 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
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 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 24 matching lines...) Expand all
35 #include "bindings/v8/CustomElementHelpers.h" 35 #include "bindings/v8/CustomElementHelpers.h"
36 #include "bindings/v8/DOMDataStore.h" 36 #include "bindings/v8/DOMDataStore.h"
37 #include "bindings/v8/ScriptController.h" 37 #include "bindings/v8/ScriptController.h"
38 #include "bindings/v8/V8Binding.h" 38 #include "bindings/v8/V8Binding.h"
39 #include "bindings/v8/V8HiddenPropertyName.h" 39 #include "bindings/v8/V8HiddenPropertyName.h"
40 #include "core/dom/ScriptExecutionContext.h" 40 #include "core/dom/ScriptExecutionContext.h"
41 #include "wtf/PassRefPtr.h" 41 #include "wtf/PassRefPtr.h"
42 42
43 namespace WebCore { 43 namespace WebCore {
44 44
45 PassRefPtr<V8CustomElementLifecycleCallbacks> V8CustomElementLifecycleCallbacks: :create(ScriptExecutionContext* scriptExecutionContext, v8::Handle<v8::Object> p rototype, v8::Handle<v8::Function> created, v8::Handle<v8::Function> attributeCh anged) 45 #define CALLBACK_LIST(V) \
46 V(created, Created) \
47 V(enteredDocument, EnteredDocument) \
48 V(leftDocument, LeftDocument) \
49 V(attributeChanged, AttributeChanged)
50
51 PassRefPtr<V8CustomElementLifecycleCallbacks> V8CustomElementLifecycleCallbacks: :create(ScriptExecutionContext* scriptExecutionContext, v8::Handle<v8::Object> p rototype, v8::Handle<v8::Function> created, v8::Handle<v8::Function> enteredDocu ment, v8::Handle<v8::Function> leftDocument, v8::Handle<v8::Function> attributeC hanged)
46 { 52 {
47 // A given object can only be used as a Custom Element prototype once, see i sCustomElementInterfacePrototypeObject 53 // A given object can only be used as a Custom Element prototype
48 ASSERT(prototype->GetHiddenValue(V8HiddenPropertyName::customElementCreated( )).IsEmpty() && prototype->GetHiddenValue(V8HiddenPropertyName::customElementAtt ributeChanged()).IsEmpty()); 54 // once; see isCustomElementInterfacePrototypeObject
49 if (!created.IsEmpty()) 55 #define SET_HIDDEN_PROPERTY(Value, Name) \
50 prototype->SetHiddenValue(V8HiddenPropertyName::customElementCreated(), created); 56 ASSERT(prototype->GetHiddenValue(V8HiddenPropertyName::customElement##Name() ).IsEmpty()); \
57 if (!Value.IsEmpty()) \
58 prototype->SetHiddenValue(V8HiddenPropertyName::customElement##Name(), V alue);
59
60 CALLBACK_LIST(SET_HIDDEN_PROPERTY)
61 #undef SET_HIDDEN_PROPERTY
62
63 return adoptRef(new V8CustomElementLifecycleCallbacks(scriptExecutionContext , prototype, created, enteredDocument, leftDocument, attributeChanged));
64 }
65
66 static CustomElementLifecycleCallbacks::CallbackType flagSet(v8::Handle<v8::Func tion> enteredDocument, v8::Handle<v8::Function> leftDocument, v8::Handle<v8::Fun ction> attributeChanged)
67 {
68 // V8 Custom Elements always run created to swizzle prototypes.
69 int flags = CustomElementLifecycleCallbacks::Created;
70
71 if (!enteredDocument.IsEmpty())
72 flags |= CustomElementLifecycleCallbacks::EnteredDocument;
73
74 if (!leftDocument.IsEmpty())
75 flags |= CustomElementLifecycleCallbacks::LeftDocument;
76
51 if (!attributeChanged.IsEmpty()) 77 if (!attributeChanged.IsEmpty())
52 prototype->SetHiddenValue(V8HiddenPropertyName::customElementAttributeCh anged(), attributeChanged); 78 flags |= CustomElementLifecycleCallbacks::AttributeChanged;
53 return adoptRef(new V8CustomElementLifecycleCallbacks(scriptExecutionContext , prototype, created, attributeChanged)); 79
80 return CustomElementLifecycleCallbacks::CallbackType(flags);
54 } 81 }
55 82
56 template <typename T> 83 template <typename T>
57 static void weakCallback(v8::Isolate*, v8::Persistent<T>*, ScopedPersistent<T>* handle) 84 static void weakCallback(v8::Isolate*, v8::Persistent<T>*, ScopedPersistent<T>* handle)
58 { 85 {
59 handle->clear(); 86 handle->clear();
60 } 87 }
61 88
62 V8CustomElementLifecycleCallbacks::V8CustomElementLifecycleCallbacks(ScriptExecu tionContext* scriptExecutionContext, v8::Handle<v8::Object> prototype, v8::Handl e<v8::Function> created, v8::Handle<v8::Function> attributeChanged) 89 V8CustomElementLifecycleCallbacks::V8CustomElementLifecycleCallbacks(ScriptExecu tionContext* scriptExecutionContext, v8::Handle<v8::Object> prototype, v8::Handl e<v8::Function> created, v8::Handle<v8::Function> enteredDocument, v8::Handle<v8 ::Function> leftDocument, v8::Handle<v8::Function> attributeChanged)
63 : CustomElementLifecycleCallbacks(CallbackType(Created | (attributeChanged.I sEmpty() ? None : AttributeChanged))) 90 : CustomElementLifecycleCallbacks(flagSet(enteredDocument, leftDocument, att ributeChanged))
64 , ActiveDOMCallback(scriptExecutionContext) 91 , ActiveDOMCallback(scriptExecutionContext)
65 , m_world(DOMWrapperWorld::current()) 92 , m_world(DOMWrapperWorld::current())
66 , m_prototype(prototype) 93 , m_prototype(prototype)
67 , m_created(created) 94 , m_created(created)
95 , m_enteredDocument(enteredDocument)
96 , m_leftDocument(leftDocument)
68 , m_attributeChanged(attributeChanged) 97 , m_attributeChanged(attributeChanged)
69 { 98 {
70 m_prototype.makeWeak(&m_prototype, weakCallback<v8::Object>); 99 m_prototype.makeWeak(&m_prototype, weakCallback<v8::Object>);
71 if (!m_created.isEmpty()) 100
72 m_created.makeWeak(&m_created, weakCallback<v8::Function>); 101 #define MAKE_WEAK(Var, _) \
73 if (!m_attributeChanged.isEmpty()) 102 if (!m_##Var.isEmpty()) \
74 m_attributeChanged.makeWeak(&m_attributeChanged, weakCallback<v8::Functi on>); 103 m_##Var.makeWeak(&m_##Var, weakCallback<v8::Function>);
104
105 CALLBACK_LIST(MAKE_WEAK)
106 #undef MAKE_WEAK
75 } 107 }
76 108
77 void V8CustomElementLifecycleCallbacks::created(Element* element) 109 void V8CustomElementLifecycleCallbacks::created(Element* element)
78 { 110 {
79 if (!canInvokeCallback()) 111 if (!canInvokeCallback())
80 return; 112 return;
81 113
82 element->setIsUpgradedCustomElement(); 114 element->setIsUpgradedCustomElement();
83 115
84 v8::HandleScope handleScope; 116 v8::HandleScope handleScope;
(...skipping 22 matching lines...) Expand all
107 if (receiver.IsEmpty()) 139 if (receiver.IsEmpty())
108 receiver = toV8(element, context->Global(), isolate).As<v8::Object>(); 140 receiver = toV8(element, context->Global(), isolate).As<v8::Object>();
109 141
110 ASSERT(!receiver.IsEmpty()); 142 ASSERT(!receiver.IsEmpty());
111 143
112 v8::TryCatch exceptionCatcher; 144 v8::TryCatch exceptionCatcher;
113 exceptionCatcher.SetVerbose(true); 145 exceptionCatcher.SetVerbose(true);
114 ScriptController::callFunctionWithInstrumentation(scriptExecutionContext(), callback, receiver, 0, 0); 146 ScriptController::callFunctionWithInstrumentation(scriptExecutionContext(), callback, receiver, 0, 0);
115 } 147 }
116 148
149 void V8CustomElementLifecycleCallbacks::enteredDocument(Element* element)
150 {
151 call(m_enteredDocument, element);
152 }
153
154 void V8CustomElementLifecycleCallbacks::leftDocument(Element* element)
155 {
156 call(m_leftDocument, element);
157 }
158
117 void V8CustomElementLifecycleCallbacks::attributeChanged(Element* element, const AtomicString& name, const AtomicString& oldValue, const AtomicString& newValue) 159 void V8CustomElementLifecycleCallbacks::attributeChanged(Element* element, const AtomicString& name, const AtomicString& oldValue, const AtomicString& newValue)
118 { 160 {
119 if (!canInvokeCallback()) 161 if (!canInvokeCallback())
120 return; 162 return;
121 163
122 v8::HandleScope handleScope; 164 v8::HandleScope handleScope;
123 v8::Handle<v8::Context> context = toV8Context(scriptExecutionContext(), m_wo rld.get()); 165 v8::Handle<v8::Context> context = toV8Context(scriptExecutionContext(), m_wo rld.get());
124 if (context.IsEmpty()) 166 if (context.IsEmpty())
125 return; 167 return;
126 168
(...skipping 11 matching lines...) Expand all
138 v8String(name, isolate), 180 v8String(name, isolate),
139 oldValue.isNull() ? v8::Handle<v8::Value>(v8::Null()) : v8::Handle<v8::V alue>(v8String(oldValue, isolate)), 181 oldValue.isNull() ? v8::Handle<v8::Value>(v8::Null()) : v8::Handle<v8::V alue>(v8String(oldValue, isolate)),
140 newValue.isNull() ? v8::Handle<v8::Value>(v8::Null()) : v8::Handle<v8::V alue>(v8String(newValue, isolate)) 182 newValue.isNull() ? v8::Handle<v8::Value>(v8::Null()) : v8::Handle<v8::V alue>(v8String(newValue, isolate))
141 }; 183 };
142 184
143 v8::TryCatch exceptionCatcher; 185 v8::TryCatch exceptionCatcher;
144 exceptionCatcher.SetVerbose(true); 186 exceptionCatcher.SetVerbose(true);
145 ScriptController::callFunctionWithInstrumentation(scriptExecutionContext(), callback, receiver, sizeof(argv) / sizeof(v8::Handle<v8::Value>), argv); 187 ScriptController::callFunctionWithInstrumentation(scriptExecutionContext(), callback, receiver, sizeof(argv) / sizeof(v8::Handle<v8::Value>), argv);
146 } 188 }
147 189
190 void V8CustomElementLifecycleCallbacks::call(const ScopedPersistent<v8::Function >& weakCallback, Element* element)
191 {
192 if (!canInvokeCallback())
193 return;
194
195 v8::HandleScope handleScope;
196 v8::Handle<v8::Context> context = toV8Context(scriptExecutionContext(), m_wo rld.get());
197 if (context.IsEmpty())
198 return;
199
200 v8::Context::Scope scope(context);
201 v8::Isolate* isolate = context->GetIsolate();
202
203 v8::Handle<v8::Function> callback = weakCallback.newLocal(isolate);
204 if (callback.IsEmpty())
205 return;
206
207 v8::Handle<v8::Object> receiver = toV8(element, context->Global(), isolate). As<v8::Object>();
208 ASSERT(!receiver.IsEmpty());
209
210 v8::TryCatch exceptionCatcher;
211 exceptionCatcher.SetVerbose(true);
212 ScriptController::callFunctionWithInstrumentation(scriptExecutionContext(), callback, receiver, 0, 0);
213 }
214
148 } // namespace WebCore 215 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698