Upstream version 9.38.198.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
12           and attribute.idl_type == 'DOMString' and is_node
13           and not attribute.is_implemented_in_private_script %}
14     {% set cpp_class, v8_class = 'Element', 'V8Element' %}
15     {% endif %}
16     {# holder #}
17     {% if not attribute.is_static %}
18     v8::Handle<v8::Object> holder = info.Holder();
19     {% endif %}
20     {# impl #}
21     {% if attribute.cached_attribute_validation_method %}
22     v8::Handle<v8::String> propertyName = v8AtomicString(info.GetIsolate(), "{{attribute.name}}");
23     {{cpp_class}}* impl = {{v8_class}}::toNative(holder);
24     if (!impl->{{attribute.cached_attribute_validation_method}}()) {
25         v8::Handle<v8::Value> v8Value = V8HiddenValue::getHiddenValue(info.GetIsolate(), holder, propertyName);
26         if (!v8Value.IsEmpty()) {
27             v8SetReturnValue(info, v8Value);
28             return;
29         }
30     }
31     {% elif not attribute.is_static %}
32     {{cpp_class}}* impl = {{v8_class}}::toNative(holder);
33     {% endif %}
34     {% if interface_name == 'Window' and attribute.idl_type == 'EventHandler' %}
35     if (!impl->document())
36         return;
37     {% endif %}
38     {# Local variables #}
39     {% if attribute.is_call_with_execution_context %}
40     ExecutionContext* executionContext = currentExecutionContext(info.GetIsolate());
41     {% endif %}
42     {% if attribute.is_call_with_script_state %}
43     ScriptState* scriptState = ScriptState::current(info.GetIsolate());
44     {% endif %}
45     {% if attribute.is_check_security_for_node or
46           attribute.is_getter_raises_exception %}
47     ExceptionState exceptionState(ExceptionState::GetterContext, "{{attribute.name}}", "{{interface_name}}", holder, info.GetIsolate());
48     {% endif %}
49     {% if attribute.is_explicit_nullable %}
50     bool isNull = false;
51     {% endif %}
52     {% if attribute.is_implemented_in_private_script %}
53     {{attribute.cpp_type}} result{{attribute.cpp_type_initializer}};
54     if (!{{attribute.cpp_value_original}})
55         return;
56     {% elif attribute.cpp_value_original %}
57     {{attribute.cpp_type}} {{attribute.cpp_value}}({{attribute.cpp_value_original}});
58     {% endif %}
59     {# Checks #}
60     {% if attribute.is_getter_raises_exception %}
61     if (UNLIKELY(exceptionState.throwIfNeeded()))
62         return;
63     {% endif %}
64     {% if attribute.is_check_security_for_node %}
65     if (!BindingSecurity::shouldAllowAccessToNode(info.GetIsolate(), {{attribute.cpp_value}}, exceptionState)) {
66         v8SetReturnValueNull(info);
67         exceptionState.throwIfNeeded();
68         return;
69     }
70     {% endif %}
71     {% if attribute.reflect_only %}
72     {{release_only_check(attribute.reflect_only, attribute.reflect_missing,
73                          attribute.reflect_invalid, attribute.reflect_empty,
74                          attribute.cpp_value)
75       | indent}}
76     {% endif %}
77     {% if attribute.is_explicit_nullable %}
78     if (isNull) {
79         v8SetReturnValueNull(info);
80         return;
81     }
82     {% endif %}
83     {% if attribute.cached_attribute_validation_method %}
84     V8HiddenValue::setHiddenValue(info.GetIsolate(), holder, propertyName, {{attribute.cpp_value_to_v8_value}});
85     {% endif %}
86     {# v8SetReturnValue #}
87     {% if attribute.is_keep_alive_for_gc %}
88     if ({{attribute.cpp_value}} && DOMDataStore::setReturnValueFromWrapper{{world_suffix}}<V8{{attribute.idl_type}}>(info.GetReturnValue(), {{attribute.cpp_value}}.get()))
89         return;
90     v8::Handle<v8::Value> wrapper = toV8({{attribute.cpp_value}}.get(), holder, info.GetIsolate());
91     if (!wrapper.IsEmpty()) {
92         V8HiddenValue::setHiddenValue(info.GetIsolate(), holder, v8AtomicString(info.GetIsolate(), "{{attribute.name}}"), wrapper);
93         {{attribute.v8_set_return_value}};
94     }
95     {% elif world_suffix %}
96     {{attribute.v8_set_return_value_for_main_world}};
97     {% else %}
98     {{attribute.v8_set_return_value}};
99     {% endif %}
100 }
101 {% endfilter %}
102 {% endmacro %}
103
104 {######################################}
105 {% macro release_only_check(reflect_only_values, reflect_missing,
106                             reflect_invalid, reflect_empty, cpp_value) %}
107 {# Attribute is limited to only known values: check that the attribute value is
108    one of those. If not, set it to the empty string.
109    http://www.whatwg.org/specs/web-apps/current-work/#limited-to-only-known-values #}
110 {% if reflect_empty %}
111 if ({{cpp_value}}.isNull()) {
112 {% if reflect_missing %}
113     {{cpp_value}} = "{{reflect_missing}}";
114 {% else %}
115     ;
116 {% endif %}
117 } else if ({{cpp_value}}.isEmpty()) {
118     {{cpp_value}} = "{{reflect_empty}}";
119 {% else %}
120 if ({{cpp_value}}.isEmpty()) {
121 {# FIXME: should use [ReflectEmpty] instead; need to change IDL files #}
122 {% if reflect_missing %}
123     {{cpp_value}} = "{{reflect_missing}}";
124 {% else %}
125     ;
126 {% endif %}
127 {% endif %}
128 {% for value in reflect_only_values %}
129 } else if (equalIgnoringCase({{cpp_value}}, "{{value}}")) {
130     {{cpp_value}} = "{{value}}";
131 {% endfor %}
132 } else {
133     {{cpp_value}} = "{{reflect_invalid}}";
134 }
135 {% endmacro %}
136
137
138 {##############################################################################}
139 {% macro attribute_getter_callback(attribute, world_suffix) %}
140 {% filter conditional(attribute.conditional_string) %}
141 static void {{attribute.name}}AttributeGetterCallback{{world_suffix}}(
142 {%- if attribute.is_expose_js_accessors %}
143 const v8::FunctionCallbackInfo<v8::Value>& info
144 {%- else %}
145 v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>& info
146 {%- endif %})
147 {
148     TRACE_EVENT_SET_SAMPLING_STATE("blink", "DOMGetter");
149     {% if attribute.deprecate_as %}
150     UseCounter::countDeprecation(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.deprecate_as}});
151     {% endif %}
152     {% if attribute.measure_as %}
153     UseCounter::count(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.measure_as}});
154     {% endif %}
155     {% if world_suffix in attribute.activity_logging_world_list_for_getter %}
156     ScriptState* scriptState = ScriptState::from(info.GetIsolate()->GetCurrentContext());
157     V8PerContextData* contextData = scriptState->perContextData();
158     {% if attribute.activity_logging_world_check %}
159     if (scriptState->world().isIsolatedWorld() && contextData && contextData->activityLogger())
160     {% else %}
161     if (contextData && contextData->activityLogger())
162     {% endif %}
163         contextData->activityLogger()->logGetter("{{interface_name}}.{{attribute.name}}");
164     {% endif %}
165     {% if attribute.has_custom_getter %}
166     {{v8_class}}::{{attribute.name}}AttributeGetterCustom(info);
167     {% else %}
168     {{cpp_class}}V8Internal::{{attribute.name}}AttributeGetter{{world_suffix}}(info);
169     {% endif %}
170     TRACE_EVENT_SET_SAMPLING_STATE("v8", "V8Execution");
171 }
172 {% endfilter %}
173 {% endmacro %}
174
175
176 {##############################################################################}
177 {% macro constructor_getter_callback(attribute, world_suffix) %}
178 {% filter conditional(attribute.conditional_string) %}
179 static void {{attribute.name}}ConstructorGetterCallback{{world_suffix}}(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info)
180 {
181     TRACE_EVENT_SET_SAMPLING_STATE("blink", "DOMGetter");
182     {% if attribute.deprecate_as %}
183     UseCounter::countDeprecation(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.deprecate_as}});
184     {% endif %}
185     {% if attribute.measure_as %}
186     UseCounter::count(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.measure_as}});
187     {% endif %}
188     {{cpp_class}}V8Internal::{{cpp_class}}ConstructorGetter{{world_suffix}}(property, info);
189     TRACE_EVENT_SET_SAMPLING_STATE("v8", "V8Execution");
190 }
191 {% endfilter %}
192 {% endmacro %}
193
194
195 {##############################################################################}
196 {% macro attribute_setter(attribute, world_suffix) %}
197 {% filter conditional(attribute.conditional_string) %}
198 static void {{attribute.name}}AttributeSetter{{world_suffix}}(
199 {%- if attribute.is_expose_js_accessors %}
200 v8::Local<v8::Value> v8Value, const v8::FunctionCallbackInfo<v8::Value>& info
201 {%- else %}
202 v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<void>& info
203 {%- endif %})
204 {
205     {% if attribute.is_reflect and attribute.idl_type == 'DOMString'
206           and is_node and not attribute.is_implemented_in_private_script %}
207     {% set cpp_class, v8_class = 'Element', 'V8Element' %}
208     {% endif %}
209     {# Local variables #}
210     {% if not attribute.is_static %}
211     v8::Handle<v8::Object> holder = info.Holder();
212     {% endif %}
213     {% if attribute.has_setter_exception_state %}
214     ExceptionState exceptionState(ExceptionState::SetterContext, "{{attribute.name}}", "{{interface_name}}", holder, info.GetIsolate());
215     {% endif %}
216     {# Type checking #}
217     {% if attribute.has_type_checking_interface %}
218     {# Type checking for interface types (if interface not implemented, throw
219        TypeError), per http://www.w3.org/TR/WebIDL/#es-interface #}
220     if ({% if attribute.is_nullable %}!isUndefinedOrNull(v8Value) && {% endif %}!V8{{attribute.idl_type}}::hasInstance(v8Value, info.GetIsolate())) {
221         exceptionState.throwTypeError("The provided value is not of type '{{attribute.idl_type}}'.");
222         exceptionState.throwIfNeeded();
223         return;
224     }
225     {% endif %}
226     {# impl #}
227     {% if attribute.put_forwards %}
228     {{cpp_class}}* proxyImpl = {{v8_class}}::toNative(holder);
229     {{attribute.cpp_type}} impl = WTF::getPtr(proxyImpl->{{attribute.name}}());
230     if (!impl)
231         return;
232     {% elif not attribute.is_static %}
233     {{cpp_class}}* impl = {{v8_class}}::toNative(holder);
234     {% endif %}
235     {% if attribute.idl_type == 'EventHandler' and interface_name == 'Window' %}
236     if (!impl->document())
237         return;
238     {% endif %}
239     {# Convert JS value to C++ value #}
240     {% if attribute.idl_type != 'EventHandler' %}
241     {{attribute.v8_value_to_local_cpp_value}};
242     {% elif not is_node %}{# EventHandler hack #}
243     moveEventListenerToNewWrapper(holder, {{attribute.event_handler_getter_expression}}, v8Value, {{v8_class}}::eventListenerCacheIndex, info.GetIsolate());
244     {% endif %}
245     {# Type checking, possibly throw a TypeError, per:
246        http://www.w3.org/TR/WebIDL/#es-type-mapping #}
247     {% if attribute.has_type_checking_unrestricted %}
248     {# Non-finite floating point values (NaN, +Infinity or âˆ’Infinity), per:
249        http://heycam.github.io/webidl/#es-float
250        http://heycam.github.io/webidl/#es-double #}
251     if (!std::isfinite(cppValue)) {
252         exceptionState.throwTypeError("The provided {{attribute.idl_type}} value is non-finite.");
253         exceptionState.throwIfNeeded();
254         return;
255     }
256     {% elif attribute.enum_validation_expression %}
257     {# Setter ignores invalid enum values:
258        http://www.w3.org/TR/WebIDL/#idl-enums #}
259     String string = cppValue;
260     if (!({{attribute.enum_validation_expression}}))
261         return;
262     {% endif %}
263     {# Pre-set context #}
264     {% if attribute.is_custom_element_callbacks or
265           (attribute.is_reflect and
266            not(attribute.idl_type == 'DOMString' and is_node)) %}
267     {# Skip on compact node DOMString getters #}
268     CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope;
269     {% endif %}
270     {% if attribute.is_call_with_execution_context or
271           attribute.is_setter_call_with_execution_context %}
272     ExecutionContext* executionContext = currentExecutionContext(info.GetIsolate());
273     {% endif %}
274     {# Set #}
275     {{attribute.cpp_setter}};
276     {# Post-set #}
277     {% if attribute.is_setter_raises_exception %}
278     exceptionState.throwIfNeeded();
279     {% endif %}
280     {% if attribute.cached_attribute_validation_method %}
281     V8HiddenValue::deleteHiddenValue(info.GetIsolate(), holder, v8AtomicString(info.GetIsolate(), "{{attribute.name}}")); // Invalidate the cached value.
282     {% endif %}
283 }
284 {% endfilter %}
285 {% endmacro %}
286
287
288 {##############################################################################}
289 {% macro attribute_setter_callback(attribute, world_suffix) %}
290 {% filter conditional(attribute.conditional_string) %}
291 static void {{attribute.name}}AttributeSetterCallback{{world_suffix}}(
292 {%- if attribute.is_expose_js_accessors %}
293 const v8::FunctionCallbackInfo<v8::Value>& info
294 {%- else %}
295 v8::Local<v8::String>, v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<void>& info
296 {%- endif %})
297 {
298     {% if attribute.is_expose_js_accessors %}
299     v8::Local<v8::Value> v8Value = info[0];
300     {% endif %}
301     TRACE_EVENT_SET_SAMPLING_STATE("blink", "DOMSetter");
302     {% if attribute.deprecate_as %}
303     UseCounter::countDeprecation(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.deprecate_as}});
304     {% endif %}
305     {% if attribute.measure_as %}
306     UseCounter::count(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.measure_as}});
307     {% endif %}
308     {% if world_suffix in attribute.activity_logging_world_list_for_setter %}
309     ScriptState* scriptState = ScriptState::from(info.GetIsolate()->GetCurrentContext());
310     V8PerContextData* contextData = scriptState->perContextData();
311     {% if attribute.activity_logging_world_check %}
312     if (scriptState->world().isIsolatedWorld() && contextData && contextData->activityLogger()) {
313     {% else %}
314     if (contextData && contextData->activityLogger()) {
315     {% endif %}
316         {% if attribute.activity_logging_include_old_value_for_setter %}
317         {{cpp_class}}* impl = {{v8_class}}::toNative(info.Holder());
318         {% if attribute.cpp_value_original %}
319         {{attribute.cpp_type}} {{attribute.cpp_value}}({{attribute.cpp_value_original}});
320         {% endif %}
321         v8::Handle<v8::Value> originalValue = {{attribute.cpp_value_to_v8_value}};
322         contextData->activityLogger()->logSetter("{{interface_name}}.{{attribute.name}}", v8Value, originalValue);
323         {% else %}
324         contextData->activityLogger()->logSetter("{{interface_name}}.{{attribute.name}}", v8Value);
325         {% endif %}
326     }
327     {% endif %}
328     {% if attribute.is_custom_element_callbacks or attribute.is_reflect %}
329     CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope;
330     {% endif %}
331     {% if attribute.has_custom_setter %}
332     {{v8_class}}::{{attribute.name}}AttributeSetterCustom(v8Value, info);
333     {% else %}
334     {{cpp_class}}V8Internal::{{attribute.name}}AttributeSetter{{world_suffix}}(v8Value, info);
335     {% endif %}
336     TRACE_EVENT_SET_SAMPLING_STATE("v8", "V8Execution");
337 }
338 {% endfilter %}
339 {% endmacro %}
340
341
342 {##############################################################################}
343 {% macro attribute_getter_implemented_in_private_script(attribute) %}
344 bool {{v8_class}}::PrivateScript::{{attribute.name}}AttributeGetter(LocalFrame* frame, {{cpp_class}}* holderImpl, {{attribute.cpp_type}}* result)
345 {
346     if (!frame)
347         return false;
348     v8::HandleScope handleScope(toIsolate(frame));
349     ScriptForbiddenScope::AllowUserAgentScript script;
350     v8::Handle<v8::Context> context = toV8Context(frame, DOMWrapperWorld::privateScriptIsolatedWorld());
351     if (context.IsEmpty())
352         return false;
353     ScriptState* scriptState = ScriptState::from(context);
354     if (!scriptState->executionContext())
355         return false;
356
357     ScriptState::Scope scope(scriptState);
358     v8::Handle<v8::Value> holder = toV8(holderImpl, scriptState->context()->Global(), scriptState->isolate());
359
360     ExceptionState exceptionState(ExceptionState::GetterContext, "{{attribute.name}}", "{{cpp_class}}", scriptState->context()->Global(), scriptState->isolate());
361     v8::TryCatch block;
362     v8::Handle<v8::Value> v8Value = PrivateScriptRunner::runDOMAttributeGetter(scriptState, "{{cpp_class}}", "{{attribute.name}}", holder);
363     if (block.HasCaught()) {
364         if (!PrivateScriptRunner::rethrowExceptionInPrivateScript(scriptState->isolate(), exceptionState, block)) {
365             // FIXME: We should support more exceptions.
366             RELEASE_ASSERT_NOT_REACHED();
367         }
368         block.ReThrow();
369         return false;
370     }
371     {{attribute.private_script_v8_value_to_local_cpp_value}};
372     RELEASE_ASSERT(!exceptionState.hadException());
373     *result = cppValue;
374     return true;
375 }
376 {% endmacro %}
377
378
379 {% macro attribute_setter_implemented_in_private_script(attribute) %}
380 bool {{v8_class}}::PrivateScript::{{attribute.name}}AttributeSetter(LocalFrame* frame, {{cpp_class}}* holderImpl, {{attribute.argument_cpp_type}} cppValue)
381 {
382     if (!frame)
383         return false;
384     v8::HandleScope handleScope(toIsolate(frame));
385     ScriptForbiddenScope::AllowUserAgentScript script;
386     v8::Handle<v8::Context> context = toV8Context(frame, DOMWrapperWorld::privateScriptIsolatedWorld());
387     if (context.IsEmpty())
388         return false;
389     ScriptState* scriptState = ScriptState::from(context);
390     if (!scriptState->executionContext())
391         return false;
392
393     ScriptState::Scope scope(scriptState);
394     v8::Handle<v8::Value> holder = toV8(holderImpl, scriptState->context()->Global(), scriptState->isolate());
395
396     ExceptionState exceptionState(ExceptionState::SetterContext, "{{attribute.name}}", "{{cpp_class}}", scriptState->context()->Global(), scriptState->isolate());
397     v8::TryCatch block;
398     PrivateScriptRunner::runDOMAttributeSetter(scriptState, "{{cpp_class}}", "{{attribute.name}}", holder, {{attribute.private_script_cpp_value_to_v8_value}});
399     if (block.HasCaught()) {
400         if (!PrivateScriptRunner::rethrowExceptionInPrivateScript(scriptState->isolate(), exceptionState, block)) {
401             // FIXME: We should support more exceptions.
402             RELEASE_ASSERT_NOT_REACHED();
403         }
404         block.ReThrow();
405         return false;
406     }
407     return true;
408 }
409 {% endmacro %}