Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / bindings / templates / attributes.cpp
1 {##############################################################################}
2 {% macro attribute_getter(attribute, world_suffix) %}
3 {% filter conditional(attribute.conditional_string) %}
4 static void {{attribute.name}}AttributeGetter{{world_suffix}}(
5 {%- if attribute.is_expose_js_accessors %}
6 const v8::FunctionCallbackInfo<v8::Value>& info
7 {%- else %}
8 const v8::PropertyCallbackInfo<v8::Value>& info
9 {%- endif %})
10 {
11     {% if attribute.is_reflect and not attribute.is_url and
12           attribute.idl_type == 'DOMString' and is_node %}
13     {% set cpp_class, v8_class = 'Element', 'V8Element' %}
14     {% endif %}
15     {# holder #}
16     {% if attribute.is_unforgeable and interface_name != 'Window' %}
17     {# perform lookup first #}
18     {# FIXME: can we remove this lookup? #}
19     v8::Handle<v8::Object> holder = {{v8_class}}::findInstanceInPrototypeChain(info.This(), info.GetIsolate());
20     if (holder.IsEmpty())
21         return;
22     {% elif not attribute.is_static %}
23     v8::Handle<v8::Object> holder = info.Holder();
24     {% endif %}
25     {# impl #}
26     {% if attribute.cached_attribute_validation_method %}
27     v8::Handle<v8::String> propertyName = v8AtomicString(info.GetIsolate(), "{{attribute.name}}");
28     {{cpp_class}}* impl = {{v8_class}}::toNative(holder);
29     if (!impl->{{attribute.cached_attribute_validation_method}}()) {
30         v8::Handle<v8::Value> v8Value = V8HiddenValue::getHiddenValue(info.GetIsolate(), holder, propertyName);
31         if (!v8Value.IsEmpty()) {
32             v8SetReturnValue(info, v8Value);
33             return;
34         }
35     }
36     {% elif not attribute.is_static %}
37     {{cpp_class}}* impl = {{v8_class}}::toNative(holder);
38     {% endif %}
39     {% if attribute.is_partial_interface_member and not attribute.is_static %}
40     {# instance members (non-static members) in partial interface take |impl| #}
41     ASSERT(impl);
42     {% endif %}
43     {% if interface_name == 'Window' and attribute.idl_type == 'EventHandler' %}
44     if (!impl->document())
45         return;
46     {% endif %}
47     {# Local variables #}
48     {% if attribute.is_call_with_execution_context %}
49     ExecutionContext* scriptContext = currentExecutionContext(info.GetIsolate());
50     {% endif %}
51     {% if attribute.is_call_with_script_state %}
52     ScriptState* state = ScriptState::current(info.GetIsolate());
53     {% endif %}
54     {% if attribute.is_check_security_for_node or
55           attribute.is_getter_raises_exception %}
56     ExceptionState exceptionState(ExceptionState::GetterContext, "{{attribute.name}}", "{{interface_name}}", holder, info.GetIsolate());
57     {% endif %}
58     {% if attribute.is_nullable and not attribute.has_type_checking_nullable %}
59     bool isNull = false;
60     {% endif %}
61     {# FIXME: consider always using a local variable for value #}
62     {% if attribute.cached_attribute_validation_method or
63           attribute.is_getter_raises_exception or
64           attribute.is_nullable or
65           attribute.reflect_only or
66           attribute.idl_type == 'EventHandler' %}
67     {{attribute.cpp_type}} {{attribute.cpp_value}} = {{attribute.cpp_value_original}};
68     {% endif %}
69     {# Checks #}
70     {% if attribute.is_getter_raises_exception %}
71     if (UNLIKELY(exceptionState.throwIfNeeded()))
72         return;
73     {% endif %}
74     {% if attribute.is_check_security_for_node %}
75     {# FIXME: use a local variable to not call getter twice #}
76     if (!BindingSecurity::shouldAllowAccessToNode(info.GetIsolate(), {{attribute.cpp_value}}, exceptionState)) {
77         v8SetReturnValueNull(info);
78         exceptionState.throwIfNeeded();
79         return;
80     }
81     {% endif %}
82     {% if attribute.reflect_only %}
83     {{release_only_check(attribute.reflect_only, attribute.reflect_missing,
84                          attribute.reflect_invalid, attribute.reflect_empty)
85       | indent}}
86     {% endif %}
87     {% if attribute.is_nullable %}
88     {% if attribute.has_type_checking_nullable %}
89     if (!{{attribute.cpp_value}}) {
90     {% else %}
91     if (isNull) {
92     {% endif %}
93         v8SetReturnValueNull(info);
94         return;
95     }
96     {% endif %}
97     {% if attribute.cached_attribute_validation_method %}
98     V8HiddenValue::setHiddenValue(info.GetIsolate(), holder, propertyName, {{attribute.cpp_value}}.v8Value());
99     {% endif %}
100     {# v8SetReturnValue #}
101     {% if attribute.is_keep_alive_for_gc %}
102     {# FIXME: merge local variable assignment with above #}
103     {{attribute.cpp_type}} result({{attribute.cpp_value}});
104     if (result && DOMDataStore::setReturnValueFromWrapper{{world_suffix}}<{{attribute.v8_type}}>(info.GetReturnValue(), result.get()))
105         return;
106     v8::Handle<v8::Value> wrapper = toV8(result.get(), holder, info.GetIsolate());
107     if (!wrapper.IsEmpty()) {
108         V8HiddenValue::setHiddenValue(info.GetIsolate(), holder, v8AtomicString(info.GetIsolate(), "{{attribute.name}}"), wrapper);
109         {{attribute.v8_set_return_value}};
110     }
111     {% elif world_suffix %}
112     {{attribute.v8_set_return_value_for_main_world}};
113     {% else %}
114     {{attribute.v8_set_return_value}};
115     {% endif %}
116 }
117 {% endfilter %}
118 {% endmacro %}
119
120 {######################################}
121 {% macro release_only_check(reflect_only_values, reflect_missing,
122                             reflect_invalid, reflect_empty) %}
123 {# Attribute is limited to only known values: check that the attribute value is
124    one of those. If not, set it to the empty string.
125    http://www.whatwg.org/specs/web-apps/current-work/#limited-to-only-known-values #}
126 {% if reflect_empty %}
127 if (v8Value.isNull()) {
128 {% if reflect_missing %}
129     v8Value = "{{reflect_missing}}";
130 {% else %}
131     ;
132 {% endif %}
133 } else if (v8Value.isEmpty()) {
134     v8Value = "{{reflect_empty}}";
135 {% else %}
136 if (v8Value.isEmpty()) {
137 {# FIXME: should use [ReflectEmpty] instead; need to change IDL files #}
138 {% if reflect_missing %}
139     v8Value = "{{reflect_missing}}";
140 {% else %}
141     ;
142 {% endif %}
143 {% endif %}
144 {% for value in reflect_only_values %}
145 } else if (equalIgnoringCase(v8Value, "{{value}}")) {
146     v8Value = "{{value}}";
147 {% endfor %}
148 } else {
149     v8Value = "{{reflect_invalid}}";
150 }
151 {% endmacro %}
152
153
154 {##############################################################################}
155 {% macro attribute_getter_callback(attribute, world_suffix) %}
156 {% filter conditional(attribute.conditional_string) %}
157 static void {{attribute.name}}AttributeGetterCallback{{world_suffix}}(
158 {%- if attribute.is_expose_js_accessors %}
159 const v8::FunctionCallbackInfo<v8::Value>& info
160 {%- else %}
161 v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>& info
162 {%- endif %})
163 {
164     TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMGetter");
165     {% if attribute.deprecate_as %}
166     UseCounter::countDeprecation(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.deprecate_as}});
167     {% endif %}
168     {% if attribute.measure_as %}
169     UseCounter::count(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.measure_as}});
170     {% endif %}
171     {% if world_suffix in attribute.activity_logging_world_list_for_getter %}
172     DOMWrapperWorld& world = DOMWrapperWorld::current(info.GetIsolate());
173     if (world.activityLogger())
174         world.activityLogger()->logGetter("{{interface_name}}.{{attribute.name}}");
175     {% endif %}
176     {% if attribute.has_custom_getter %}
177     {{v8_class}}::{{attribute.name}}AttributeGetterCustom(info);
178     {% else %}
179     {{cpp_class}}V8Internal::{{attribute.name}}AttributeGetter{{world_suffix}}(info);
180     {% endif %}
181     TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution");
182 }
183 {% endfilter %}
184 {% endmacro %}
185
186
187 {##############################################################################}
188 {% macro constructor_getter_callback(attribute, world_suffix) %}
189 {% filter conditional(attribute.conditional_string) %}
190 static void {{attribute.name}}ConstructorGetterCallback{{world_suffix}}(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info)
191 {
192     TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMGetter");
193     {% if attribute.deprecate_as %}
194     UseCounter::countDeprecation(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.deprecate_as}});
195     {% endif %}
196     {% if attribute.measure_as %}
197     UseCounter::count(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.measure_as}});
198     {% endif %}
199     {{cpp_class}}V8Internal::{{cpp_class}}ConstructorGetter{{world_suffix}}(property, info);
200     TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution");
201 }
202 {% endfilter %}
203 {% endmacro %}
204
205
206 {##############################################################################}
207 {% macro attribute_setter(attribute, world_suffix) %}
208 {% filter conditional(attribute.conditional_string) %}
209 static void {{attribute.name}}AttributeSetter{{world_suffix}}(
210 {%- if attribute.is_expose_js_accessors %}
211 v8::Local<v8::Value> v8Value, const v8::FunctionCallbackInfo<v8::Value>& info
212 {%- else %}
213 v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<void>& info
214 {%- endif %})
215 {
216     {% if attribute.is_reflect and attribute.idl_type == 'DOMString' and
217           is_node %}
218     {% set cpp_class, v8_class = 'Element', 'V8Element' %}
219     {% endif %}
220     {# Local variables #}
221     {% if not attribute.is_static %}
222     v8::Handle<v8::Object> holder = info.Holder();
223     {% endif %}
224     {% if attribute.has_setter_exception_state %}
225     ExceptionState exceptionState(ExceptionState::SetterContext, "{{attribute.name}}", "{{interface_name}}", holder, info.GetIsolate());
226     {% endif %}
227     {# Type checking #}
228     {% if attribute.has_type_checking_interface %}
229     {# Type checking for interface types (if interface not implemented, throw
230        TypeError), per http://www.w3.org/TR/WebIDL/#es-interface #}
231     if ({% if attribute.is_nullable %}!isUndefinedOrNull(v8Value) && {% endif %}!V8{{attribute.idl_type}}::hasInstance(v8Value, info.GetIsolate())) {
232         exceptionState.throwTypeError("The provided value is not of type '{{attribute.idl_type}}'.");
233         exceptionState.throwIfNeeded();
234         return;
235     }
236     {% endif %}
237     {# impl #}
238     {% if attribute.put_forwards %}
239     {{cpp_class}}* proxyImpl = {{v8_class}}::toNative(holder);
240     {{attribute.cpp_type}} impl = WTF::getPtr(proxyImpl->{{attribute.name}}());
241     if (!impl)
242         return;
243     {% elif not attribute.is_static %}
244     {{cpp_class}}* impl = {{v8_class}}::toNative(holder);
245     {% endif %}
246     {% if attribute.is_partial_interface_member and not attribute.is_static %}
247     {# instance members (non-static members) in partial interface take |impl| #}
248     ASSERT(impl);
249     {% endif %}
250     {% if attribute.idl_type == 'EventHandler' and interface_name == 'Window' %}
251     if (!impl->document())
252         return;
253     {% endif %}
254     {# Convert JS value to C++ value #}
255     {% if attribute.idl_type != 'EventHandler' %}
256     {{attribute.v8_value_to_local_cpp_value}};
257     {% elif not is_node %}{# EventHandler hack #}
258     moveEventListenerToNewWrapper(holder, {{attribute.event_handler_getter_expression}}, v8Value, {{v8_class}}::eventListenerCacheIndex, info.GetIsolate());
259     {% endif %}
260     {# Type checking, possibly throw a TypeError, per:
261        http://www.w3.org/TR/WebIDL/#es-type-mapping #}
262     {% if attribute.has_type_checking_unrestricted %}
263     {# Non-finite floating point values (NaN, +Infinity or âˆ’Infinity), per:
264        http://heycam.github.io/webidl/#es-float
265        http://heycam.github.io/webidl/#es-double #}
266     if (!std::isfinite(cppValue)) {
267         exceptionState.throwTypeError("The provided {{attribute.idl_type}} value is non-finite.");
268         exceptionState.throwIfNeeded();
269         return;
270     }
271     {% elif attribute.enum_validation_expression %}
272     {# Setter ignores invalid enum values:
273        http://www.w3.org/TR/WebIDL/#idl-enums #}
274     String string = cppValue;
275     if (!({{attribute.enum_validation_expression}}))
276         return;
277     {% endif %}
278     {# Pre-set context #}
279     {% if attribute.is_custom_element_callbacks or
280           (attribute.is_reflect and
281            not(attribute.idl_type == 'DOMString' and is_node)) %}
282     {# Skip on compact node DOMString getters #}
283     CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope;
284     {% endif %}
285     {% if attribute.is_call_with_execution_context or
286           attribute.is_setter_call_with_execution_context %}
287     ExecutionContext* scriptContext = currentExecutionContext(info.GetIsolate());
288     {% endif %}
289     {# Set #}
290     {{attribute.cpp_setter}};
291     {# Post-set #}
292     {% if attribute.is_setter_raises_exception %}
293     exceptionState.throwIfNeeded();
294     {% endif %}
295     {% if attribute.cached_attribute_validation_method %}
296     V8HiddenValue::deleteHiddenValue(info.GetIsolate(), holder, v8AtomicString(info.GetIsolate(), "{{attribute.name}}")); // Invalidate the cached value.
297     {% endif %}
298 }
299 {% endfilter %}
300 {% endmacro %}
301
302
303 {##############################################################################}
304 {% macro attribute_setter_callback(attribute, world_suffix) %}
305 {% filter conditional(attribute.conditional_string) %}
306 static void {{attribute.name}}AttributeSetterCallback{{world_suffix}}(
307 {%- if attribute.is_expose_js_accessors %}
308 const v8::FunctionCallbackInfo<v8::Value>& info
309 {%- else %}
310 v8::Local<v8::String>, v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<void>& info
311 {%- endif %})
312 {
313     {% if attribute.is_expose_js_accessors %}
314     v8::Local<v8::Value> v8Value = info[0];
315     {% endif %}
316     TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMSetter");
317     {% if attribute.deprecate_as %}
318     UseCounter::countDeprecation(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.deprecate_as}});
319     {% endif %}
320     {% if attribute.measure_as %}
321     UseCounter::count(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.measure_as}});
322     {% endif %}
323     {% if world_suffix in attribute.activity_logging_world_list_for_setter %}
324     DOMWrapperWorld& world = DOMWrapperWorld::current(info.GetIsolate());
325     if (world.activityLogger()) {
326         {% if attribute.activity_logging_include_old_value_for_setter %}
327         {{cpp_class}}* impl = {{v8_class}}::toNative(info.Holder());
328         {% if attribute.cpp_value_original %}
329         {{attribute.cpp_type}} original = {{attribute.cpp_value_original}};
330         {% else %}
331         {{attribute.cpp_type}} original = {{attribute.cpp_value}};
332         {% endif %}
333         v8::Handle<v8::Value> originalValue = {{attribute.cpp_value_to_v8_value}};
334         world.activityLogger()->logSetter("{{interface_name}}.{{attribute.name}}", v8Value, originalValue);
335         {% else %}
336         world.activityLogger()->logSetter("{{interface_name}}.{{attribute.name}}", v8Value);
337         {% endif %}
338     }
339     {% endif %}
340     {% if attribute.is_custom_element_callbacks or attribute.is_reflect %}
341     CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope;
342     {% endif %}
343     {% if attribute.has_custom_setter %}
344     {{v8_class}}::{{attribute.name}}AttributeSetterCustom(v8Value, info);
345     {% else %}
346     {{cpp_class}}V8Internal::{{attribute.name}}AttributeSetter{{world_suffix}}(v8Value, info);
347     {% endif %}
348     TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution");
349 }
350 {% endfilter %}
351 {% endmacro %}