d72b262963414e8924b998d03be69cfc0af6bf94
[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     {# imp #}
16     {# FIXME: use a local variable for holder more often and simplify below #}
17     {% if attribute.is_unforgeable or
18           interface_name == 'Window' and attribute.idl_type == 'EventHandler' %}
19     {% if interface_name == 'Window' %}
20     v8::Handle<v8::Object> holder = info.Holder();
21     {% else %}{# perform lookup first #}
22     {# FIXME: can we remove this lookup? #}
23     v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain({{v8_class}}::domTemplate(info.GetIsolate(), worldType(info.GetIsolate())));
24     if (holder.IsEmpty())
25         return;
26     {% endif %}{# Window #}
27     {{cpp_class}}* imp = {{v8_class}}::toNative(holder);
28     {% elif attribute.cached_attribute_validation_method %}
29     v8::Handle<v8::String> propertyName = v8AtomicString(info.GetIsolate(), "{{attribute.name}}");
30     {{cpp_class}}* imp = {{v8_class}}::toNative(info.Holder());
31     if (!imp->{{attribute.cached_attribute_validation_method}}()) {
32         v8::Handle<v8::Value> jsValue = getHiddenValue(info.GetIsolate(), info.Holder(), propertyName);
33         if (!jsValue.IsEmpty()) {
34             v8SetReturnValue(info, jsValue);
35             return;
36         }
37     }
38     {% elif not (attribute.is_static or attribute.is_unforgeable) %}
39     {{cpp_class}}* imp = {{v8_class}}::toNative(info.Holder());
40     {% endif %}
41     {% if interface_name == 'Window' and attribute.idl_type == 'EventHandler' %}
42     if (!imp->document())
43         return;
44     {% endif %}
45     {# Local variables #}
46     {% if attribute.is_call_with_execution_context %}
47     ExecutionContext* scriptContext = currentExecutionContext(info.GetIsolate());
48     {% endif %}
49     {% if attribute.is_check_security_for_node or
50           attribute.is_getter_raises_exception %}
51     ExceptionState exceptionState(ExceptionState::GetterContext, "{{attribute.name}}", "{{interface_name}}", info.Holder(), info.GetIsolate());
52     {% endif %}
53     {% if attribute.is_nullable %}
54     bool isNull = false;
55     {% endif %}
56     {# FIXME: consider always using a local variable for value #}
57     {% if attribute.cached_attribute_validation_method or
58           attribute.is_getter_raises_exception or
59           attribute.is_nullable or
60           attribute.reflect_only or
61           attribute.idl_type == 'EventHandler' %}
62     {{attribute.cpp_type}} {{attribute.cpp_value}} = {{attribute.cpp_value_original}};
63     {% endif %}
64     {# Checks #}
65     {% if attribute.is_getter_raises_exception %}
66     if (UNLIKELY(exceptionState.throwIfNeeded()))
67         return;
68     {% endif %}
69     {% if attribute.is_check_security_for_node %}
70     {# FIXME: use a local variable to not call getter twice #}
71     if (!BindingSecurity::shouldAllowAccessToNode(info.GetIsolate(), {{attribute.cpp_value}}, exceptionState)) {
72         v8SetReturnValueNull(info);
73         exceptionState.throwIfNeeded();
74         return;
75     }
76     {% endif %}
77     {% if attribute.reflect_only %}
78     {{release_only_check(attribute.reflect_only, attribute.reflect_missing,
79                          attribute.reflect_invalid, attribute.reflect_empty)
80       | indent}}
81     {% endif %}
82     {% if attribute.is_nullable %}
83     if (isNull) {
84         v8SetReturnValueNull(info);
85         return;
86     }
87     {% endif %}
88     {% if attribute.cached_attribute_validation_method %}
89     setHiddenValue(info.GetIsolate(), info.Holder(), propertyName, {{attribute.cpp_value}}.v8Value());
90     {% endif %}
91     {# v8SetReturnValue #}
92     {% if attribute.is_keep_alive_for_gc %}
93     {# FIXME: merge local variable assignment with above #}
94     {{attribute.cpp_type}} result = {{attribute.cpp_value}};
95     if (result && DOMDataStore::setReturnValueFromWrapper{{world_suffix}}<{{attribute.v8_type}}>(info.GetReturnValue(), result.get()))
96         return;
97     v8::Handle<v8::Value> wrapper = toV8(result.get(), info.Holder(), info.GetIsolate());
98     if (!wrapper.IsEmpty()) {
99         setHiddenValue(info.GetIsolate(), info.Holder(), "{{attribute.name}}", wrapper);
100         {{attribute.v8_set_return_value}};
101     }
102     {% elif world_suffix %}
103     {{attribute.v8_set_return_value_for_main_world}};
104     {% else %}
105     {{attribute.v8_set_return_value}};
106     {% endif %}
107 }
108 {% endfilter %}
109 {% endmacro %}
110
111 {######################################}
112 {% macro release_only_check(reflect_only_values, reflect_missing,
113                             reflect_invalid, reflect_empty) %}
114 {# Attribute is limited to only known values: check that the attribute value is
115    one of those. If not, set it to the empty string.
116    http://www.whatwg.org/specs/web-apps/current-work/#limited-to-only-known-values #}
117 {# FIXME: rename resultValue to jsValue #}
118 {% if reflect_empty %}
119 if (resultValue.isNull()) {
120 {% if reflect_missing %}
121     resultValue = "{{reflect_missing}}";
122 {% else %}
123     ;
124 {% endif %}
125 } else if (resultValue.isEmpty()) {
126     resultValue = "{{reflect_empty}}";
127 {% else %}
128 if (resultValue.isEmpty()) {
129 {# FIXME: should use [ReflectEmpty] instead; need to change IDL files #}
130 {% if reflect_missing %}
131     resultValue = "{{reflect_missing}}";
132 {% else %}
133     ;
134 {% endif %}
135 {% endif %}
136 {% for value in reflect_only_values %}
137 } else if (equalIgnoringCase(resultValue, "{{value}}")) {
138     resultValue = "{{value}}";
139 {% endfor %}
140 } else {
141     resultValue = "{{reflect_invalid}}";
142 }
143 {% endmacro %}
144
145
146 {##############################################################################}
147 {% macro attribute_getter_callback(attribute, world_suffix) %}
148 {% filter conditional(attribute.conditional_string) %}
149 static void {{attribute.name}}AttributeGetterCallback{{world_suffix}}(
150 {%- if attribute.is_expose_js_accessors %}
151 const v8::FunctionCallbackInfo<v8::Value>& info
152 {%- else %}
153 v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>& info
154 {%- endif %})
155 {
156     TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMGetter");
157     {% if attribute.deprecate_as %}
158     UseCounter::countDeprecation(activeExecutionContext(info.GetIsolate()), UseCounter::{{attribute.deprecate_as}});
159     {% endif %}
160     {% if attribute.measure_as %}
161     UseCounter::count(activeExecutionContext(info.GetIsolate()), UseCounter::{{attribute.measure_as}});
162     {% endif %}
163     {% if world_suffix in attribute.activity_logging_world_list_for_getter %}
164     V8PerContextData* contextData = V8PerContextData::from(info.GetIsolate()->GetCurrentContext());
165     if (contextData && contextData->activityLogger())
166         contextData->activityLogger()->log("{{interface_name}}.{{attribute.name}}", 0, 0, "Getter");
167     {% endif %}
168     {% if attribute.has_custom_getter %}
169     {{v8_class}}::{{attribute.name}}AttributeGetterCustom(info);
170     {% else %}
171     {{cpp_class}}V8Internal::{{attribute.name}}AttributeGetter{{world_suffix}}(info);
172     {% endif %}
173     TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution");
174 }
175 {% endfilter %}
176 {% endmacro %}
177
178
179 {##############################################################################}
180 {% macro attribute_setter(attribute, world_suffix) %}
181 {% filter conditional(attribute.conditional_string) %}
182 static void {{attribute.name}}AttributeSetter{{world_suffix}}(
183 {%- if attribute.is_expose_js_accessors %}
184 v8::Local<v8::Value> jsValue, const v8::FunctionCallbackInfo<v8::Value>& info
185 {%- else %}
186 v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info
187 {%- endif %})
188 {
189     {% if attribute.is_reflect and attribute.idl_type == 'DOMString' and
190           is_node %}
191     {% set cpp_class, v8_class = 'Element', 'V8Element' %}
192     {# FIXME: Perl skips most of function, but this seems unnecessary;
193        we only need to skip the CallbackDeliveryScope #}
194     {% endif %}
195     {% if attribute.has_setter_exception_state %}
196     ExceptionState exceptionState(ExceptionState::SetterContext, "{{attribute.name}}", "{{interface_name}}", info.Holder(), info.GetIsolate());
197     {% endif %}
198     {% if attribute.has_strict_type_checking %}
199     {# Type checking for interface types (if interface not implemented, throw
200        TypeError), per http://www.w3.org/TR/WebIDL/#es-interface #}
201     if (!isUndefinedOrNull(jsValue) && !V8{{attribute.idl_type}}::hasInstance(jsValue, info.GetIsolate())) {
202         exceptionState.throwTypeError("The provided value is not of type '{{attribute.idl_type}}'.");
203         exceptionState.throwIfNeeded();
204         return;
205     }
206     {% endif %}
207     {% if attribute.put_forwards %}
208     {{cpp_class}}* proxyImp = {{v8_class}}::toNative(info.Holder());
209     {{attribute.idl_type}}* imp = proxyImp->{{attribute.name}}();
210     if (!imp)
211         return;
212     {% elif not attribute.is_static %}
213     {{cpp_class}}* imp = {{v8_class}}::toNative(info.Holder());
214     {% endif %}{# imp #}
215     {% if attribute.idl_type == 'EventHandler' and interface_name == 'Window' %}
216     if (!imp->document())
217         return;
218     {% endif %}
219     {% if attribute.idl_type != 'EventHandler' %}
220     {{attribute.v8_value_to_local_cpp_value}};
221     {% elif not is_node %}{# EventHandler hack #}
222     moveEventListenerToNewWrapper(info.Holder(), {{attribute.event_handler_getter_expression}}, jsValue, {{v8_class}}::eventListenerCacheIndex, info.GetIsolate());
223     {% endif %}
224     {% if attribute.enum_validation_expression %}
225     {# Setter ignores invalid enum values: http://www.w3.org/TR/WebIDL/#idl-enums #}
226     String string = cppValue;
227     if (!({{attribute.enum_validation_expression}}))
228         return;
229     {% endif %}
230     {% if attribute.is_custom_element_callbacks or
231           (attribute.is_reflect and
232            not(attribute.idl_type == 'DOMString' and is_node)) %}
233     {# Skip on compact node DOMString getters #}
234     CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope;
235     {% endif %}
236     {% if attribute.is_call_with_execution_context or
237           attribute.is_setter_call_with_execution_context %}
238     ExecutionContext* scriptContext = currentExecutionContext(info.GetIsolate());
239     {% endif %}
240     {{attribute.cpp_setter}};
241     {% if attribute.is_setter_raises_exception %}
242     exceptionState.throwIfNeeded();
243     {% endif %}
244     {% if attribute.cached_attribute_validation_method %}
245     deleteHiddenValue(info.GetIsolate(), info.Holder(), "{{attribute.name}}"); // Invalidate the cached value.
246     {% endif %}
247 }
248 {% endfilter %}
249 {% endmacro %}
250
251
252 {##############################################################################}
253 {% macro attribute_setter_callback(attribute, world_suffix) %}
254 {% filter conditional(attribute.conditional_string) %}
255 static void {{attribute.name}}AttributeSetterCallback{{world_suffix}}(
256 {%- if attribute.is_expose_js_accessors %}
257 const v8::FunctionCallbackInfo<v8::Value>& info
258 {%- else %}
259 v8::Local<v8::String>, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info
260 {%- endif %})
261 {
262     {% if attribute.is_expose_js_accessors %}
263     v8::Local<v8::Value> jsValue = info[0];
264     {% endif %}
265     TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMSetter");
266     {% if attribute.deprecate_as %}
267     UseCounter::countDeprecation(activeExecutionContext(info.GetIsolate()), UseCounter::{{attribute.deprecate_as}});
268     {% endif %}
269     {% if attribute.measure_as %}
270     UseCounter::count(activeExecutionContext(info.GetIsolate()), UseCounter::{{attribute.measure_as}});
271     {% endif %}
272     {% if world_suffix in attribute.activity_logging_world_list_for_setter %}
273     V8PerContextData* contextData = V8PerContextData::from(info.GetIsolate()->GetCurrentContext());
274     if (contextData && contextData->activityLogger()) {
275         v8::Handle<v8::Value> loggerArg[] = { jsValue };
276         contextData->activityLogger()->log("{{interface_name}}.{{attribute.name}}", 1, &loggerArg[0], "Setter");
277     }
278     {% endif %}
279     {% if attribute.is_custom_element_callbacks or attribute.is_reflect %}
280     CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope;
281     {% endif %}
282     {% if attribute.has_custom_setter %}
283     {{v8_class}}::{{attribute.name}}AttributeSetterCustom(jsValue, info);
284     {% else %}
285     {{cpp_class}}V8Internal::{{attribute.name}}AttributeSetter{{world_suffix}}(jsValue, info);
286     {% endif %}
287     TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution");
288 }
289 {% endfilter %}
290 {% endmacro %}