Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / bindings / templates / methods.cpp
1 {##############################################################################}
2 {% macro generate_method(method, world_suffix) %}
3 {% filter conditional(method.conditional_string) %}
4 static void {{method.name}}{{method.overload_index}}Method{{world_suffix}}(const v8::FunctionCallbackInfo<v8::Value>& info)
5 {
6     {% if method.has_exception_state %}
7     ExceptionState exceptionState(ExceptionState::ExecutionContext, "{{method.name}}", "{{interface_name}}", info.Holder(), info.GetIsolate());
8     {% endif %}
9     {% if method.name in ['addEventListener', 'removeEventListener',
10                           'dispatchEvent'] %}
11     {{add_event_listener_remove_event_listener_dispatch_event() | indent}}
12     {% endif %}
13     {% if method.name in ['addEventListener', 'removeEventListener'] %}
14     {{add_event_listener_remove_event_listener_method(method.name) | indent}}
15     {% else %}
16     {% if method.number_of_required_arguments %}
17     if (UNLIKELY(info.Length() < {{method.number_of_required_arguments}})) {
18         {{throw_type_error(method,
19               'ExceptionMessages::notEnoughArguments(%s, info.Length())' %
20                   method.number_of_required_arguments) | indent(8)}}
21         return;
22     }
23     {% endif %}
24     {% if not method.is_static %}
25     {{cpp_class}}* imp = {{v8_class}}::toNative(info.Holder());
26     {% endif %}
27     {% if method.is_custom_element_callbacks %}
28     CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope;
29     {% endif %}
30     {% if method.is_check_security_for_frame %}
31     if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), imp->frame(), exceptionState)) {
32         exceptionState.throwIfNeeded();
33         return;
34     }
35     {% endif %}
36     {% if method.is_check_security_for_node %}
37     if (!BindingSecurity::shouldAllowAccessToNode(info.GetIsolate(), imp->{{method.name}}(exceptionState), exceptionState)) {
38         v8SetReturnValueNull(info);
39         exceptionState.throwIfNeeded();
40         return;
41     }
42     {% endif %}
43     {% for argument in method.arguments %}
44     {{generate_argument(method, argument, world_suffix) | indent}}
45     {% endfor %}
46     {% if world_suffix %}
47     {{cpp_method_call(method, method.v8_set_return_value_for_main_world, method.cpp_value) | indent}}
48     {% else %}
49     {{cpp_method_call(method, method.v8_set_return_value, method.cpp_value) | indent}}
50     {% endif %}
51     {% endif %}{# addEventListener, removeEventListener #}
52 }
53 {% endfilter %}
54 {% endmacro %}
55
56
57 {######################################}
58 {% macro add_event_listener_remove_event_listener_dispatch_event() %}
59 {# FIXME: Clean up: use the normal |imp| above,
60           use the existing shouldAllowAccessToFrame check if possible. #}
61 EventTarget* impl = {{v8_class}}::toNative(info.Holder());
62 if (DOMWindow* window = impl->toDOMWindow()) {
63     if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), window->frame(), exceptionState)) {
64         exceptionState.throwIfNeeded();
65         return;
66     }
67     if (!window->document())
68         return;
69 }
70 {% endmacro %}
71
72
73 {######################################}
74 {% macro add_event_listener_remove_event_listener_method(method_name) %}
75 {# Set template values for addEventListener vs. removeEventListener #}
76 {% set listener_lookup_type, listener, hidden_dependency_action =
77     ('ListenerFindOrCreate', 'listener', 'addHiddenValueToArray')
78     if method_name == 'addEventListener' else
79     ('ListenerFindOnly', 'listener.get()', 'removeHiddenValueFromArray')
80 %}
81 RefPtr<EventListener> listener = V8EventListenerList::getEventListener(info[1], false, {{listener_lookup_type}});
82 if (listener) {
83     V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithNullCheck>, eventName, info[0]);
84     impl->{{method_name}}(eventName, {{listener}}, info[2]->BooleanValue());
85     if (!impl->toNode())
86         {{hidden_dependency_action}}(info.Holder(), info[1], {{v8_class}}::eventListenerCacheIndex, info.GetIsolate());
87 }
88 {% endmacro %}
89
90
91 {######################################}
92 {% macro generate_argument(method, argument, world_suffix) %}
93 {% if argument.is_optional and not argument.has_default and
94       argument.idl_type != 'Dictionary' and
95       not argument.is_callback_interface %}
96 {# Optional arguments without a default value generate an early call with
97    fewer arguments if they are omitted.
98    Optional Dictionary arguments default to empty dictionary. #}
99 if (UNLIKELY(info.Length() <= {{argument.index}})) {
100     {% if world_suffix %}
101     {{cpp_method_call(method, argument.v8_set_return_value_for_main_world, argument.cpp_value) | indent}}
102     {% else %}
103     {{cpp_method_call(method, argument.v8_set_return_value, argument.cpp_value) | indent}}
104     {% endif %}
105     return;
106 }
107 {% endif %}
108 {% if method.is_strict_type_checking and argument.is_wrapper_type %}
109 {# Type checking for wrapper interface types (if interface not implemented,
110    throw TypeError), per http://www.w3.org/TR/WebIDL/#es-interface #}
111 if (info.Length() > {{argument.index}} && {% if argument.is_nullable %}!isUndefinedOrNull(info[{{argument.index}}]) && {% endif %}!V8{{argument.idl_type}}::hasInstance(info[{{argument.index}}], info.GetIsolate())) {
112     {{throw_type_error(method, '"parameter %s is not of type \'%s\'."' %
113                                (argument.index + 1, argument.idl_type)) | indent}}
114     return;
115 }
116 {% endif %}
117 {% if argument.is_callback_interface %}
118 {% if argument.is_optional %}
119 OwnPtr<{{argument.idl_type}}> {{argument.name}};
120 if (info.Length() > {{argument.index}} && !isUndefinedOrNull(info[{{argument.index}}])) {
121     if (!info[{{argument.index}}]->IsFunction()) {
122         {{throw_type_error(method,
123               '"The callback provided as parameter %s is not a function."' %
124                   (argument.index + 1)) | indent(8)}}
125         return;
126     }
127     {{argument.name}} = V8{{argument.idl_type}}::create(v8::Handle<v8::Function>::Cast(info[{{argument.index}}]), currentExecutionContext(info.GetIsolate()));
128 }
129 {% else %}
130 if (info.Length() <= {{argument.index}} || !{% if argument.is_nullable %}(info[{{argument.index}}]->IsFunction() || info[{{argument.index}}]->IsNull()){% else %}info[{{argument.index}}]->IsFunction(){% endif %}) {
131     {{throw_type_error(method,
132           '"The callback provided as parameter %s is not a function."' %
133               (argument.index + 1)) | indent }}
134     return;
135 }
136 OwnPtr<{{argument.idl_type}}> {{argument.name}} = {% if argument.is_nullable %}info[{{argument.index}}]->IsNull() ? nullptr : {% endif %}V8{{argument.idl_type}}::create(v8::Handle<v8::Function>::Cast(info[{{argument.index}}]), currentExecutionContext(info.GetIsolate()));
137 {% endif %}{# argument.is_optional #}
138 {% elif argument.is_clamp %}{# argument.is_callback_interface #}
139 {# NaN is treated as 0: http://www.w3.org/TR/WebIDL/#es-type-mapping #}
140 {{argument.cpp_type}} {{argument.name}} = 0;
141 V8TRYCATCH_VOID(double, {{argument.name}}NativeValue, info[{{argument.index}}]->NumberValue());
142 if (!std::isnan({{argument.name}}NativeValue))
143     {# IDL type is used for clamping, for the right bounds, since different
144        IDL integer types have same internal C++ type (int or unsigned) #}
145     {{argument.name}} = clampTo<{{argument.idl_type}}>({{argument.name}}NativeValue);
146 {% elif argument.idl_type == 'SerializedScriptValue' %}
147 {{argument.cpp_type}} {{argument.name}} = SerializedScriptValue::create(info[{{argument.index}}], 0, 0, exceptionState, info.GetIsolate());
148 if (exceptionState.throwIfNeeded())
149     return;
150 {% elif argument.is_variadic_wrapper_type %}
151 Vector<{{argument.cpp_type}} > {{argument.name}};
152 for (int i = {{argument.index}}; i < info.Length(); ++i) {
153     if (!V8{{argument.idl_type}}::hasInstance(info[i], info.GetIsolate())) {
154         {{throw_type_error(method, '"parameter %s is not of type \'%s\'."' %
155                                    (argument.index + 1, argument.idl_type)) | indent(8)}}
156         return;
157     }
158     {{argument.name}}.append(V8{{argument.idl_type}}::toNative(v8::Handle<v8::Object>::Cast(info[i])));
159 }
160 {% else %}
161 {{argument.v8_value_to_local_cpp_value}};
162 {% endif %}
163 {% if argument.enum_validation_expression %}
164 {# Methods throw on invalid enum values: http://www.w3.org/TR/WebIDL/#idl-enums #}
165 String string = {{argument.name}};
166 if (!({{argument.enum_validation_expression}})) {
167     {{throw_type_error(method,
168           '"parameter %s (\'" + string + "\') is not a valid enum value."' %
169               (argument.index + 1)) | indent}}
170     return;
171 }
172 {% endif %}
173 {% if argument.idl_type in ['Dictionary', 'Promise'] %}
174 if (!{{argument.name}}.isUndefinedOrNull() && !{{argument.name}}.isObject()) {
175     {{throw_type_error(method, '"parameter %s (\'%s\') is not an object."' %
176                                (argument.index + 1, argument.name)) | indent}}
177     return;
178 }
179 {% endif %}
180 {% endmacro %}
181
182
183 {######################################}
184 {% macro cpp_method_call(method, v8_set_return_value, cpp_value) %}
185 {% if method.is_call_with_script_state %}
186 ScriptState* currentState = ScriptState::current();
187 if (!currentState)
188     return;
189 ScriptState& state = *currentState;
190 {% endif %}
191 {% if method.is_call_with_execution_context %}
192 ExecutionContext* scriptContext = currentExecutionContext(info.GetIsolate());
193 {% endif %}
194 {% if method.is_call_with_script_arguments %}
195 RefPtr<ScriptArguments> scriptArguments(createScriptArguments(info, {{method.number_of_arguments}}));
196 {% endif %}
197 {% if method.idl_type == 'void' %}
198 {{cpp_value}};
199 {% elif method.is_call_with_script_state or method.is_raises_exception %}
200 {# FIXME: consider always using a local variable #}
201 {{method.cpp_type}} result = {{cpp_value}};
202 {% endif %}
203 {% if method.is_raises_exception %}
204 if (exceptionState.throwIfNeeded())
205     return;
206 {% endif %}
207 {% if method.is_call_with_script_state %}
208 if (state.hadException()) {
209     v8::Local<v8::Value> exception = state.exception();
210     state.clearException();
211     throwError(exception, info.GetIsolate());
212     return;
213 }
214 {% endif %}
215 {% if method.union_arguments %}
216 {{union_type_method_call(method)}}
217 {% elif v8_set_return_value %}{{v8_set_return_value}};{% endif %}{# None for void #}
218 {% endmacro %}
219
220 {######################################}
221 {% macro union_type_method_call(method) %}
222 {% for cpp_type in method.cpp_type %}
223 bool result{{loop.index0}}Enabled = false;
224 {{cpp_type}} result{{loop.index0}};
225 {% endfor %}
226 {{method.cpp_value}};
227 {% if method.is_null_expression %}{# used by getters #}
228 if ({{method.is_null_expression}})
229     return;
230 {% endif %}
231 {% for v8_set_return_value in method.v8_set_return_value %}
232 if (result{{loop.index0}}Enabled) {
233     {{v8_set_return_value}};
234     return;
235 }
236 {% endfor %}
237 {# Fall back to null if none of the union members results are returned #}
238 v8SetReturnValueNull(info);
239 {%- endmacro %}
240
241
242 {######################################}
243 {% macro throw_type_error(method, error_message) %}
244 {% if method.has_exception_state %}
245 exceptionState.throwTypeError({{error_message}});
246 exceptionState.throwIfNeeded();
247 {%- elif method.is_constructor %}
248 throwTypeError(ExceptionMessages::failedToConstruct("{{interface_name}}", {{error_message}}), info.GetIsolate());
249 {%- else %}
250 throwTypeError(ExceptionMessages::failedToExecute("{{method.name}}", "{{interface_name}}", {{error_message}}), info.GetIsolate());
251 {%- endif %}
252 {% endmacro %}
253
254
255 {##############################################################################}
256 {% macro overload_resolution_method(overloads, world_suffix) %}
257 static void {{overloads.name}}Method{{world_suffix}}(const v8::FunctionCallbackInfo<v8::Value>& info)
258 {
259     {% for method in overloads.methods %}
260     if ({{method.overload_resolution_expression}}) {
261         {{method.name}}{{method.overload_index}}Method{{world_suffix}}(info);
262         return;
263     }
264     {% endfor %}
265     {% if overloads.minimum_number_of_required_arguments %}
266     ExceptionState exceptionState(ExceptionState::ExecutionContext, "{{overloads.name}}", "{{interface_name}}", info.Holder(), info.GetIsolate());
267     if (UNLIKELY(info.Length() < {{overloads.minimum_number_of_required_arguments}})) {
268         {{throw_type_error(overloads,
269               'ExceptionMessages::notEnoughArguments(%s, info.Length())' %
270               overloads.minimum_number_of_required_arguments) | indent(8)}}
271         return;
272     }
273     {% endif %}
274     {{throw_type_error(overloads, '"No function was found that matched the signature provided."') | indent}}
275 }
276 {% endmacro %}
277
278
279 {##############################################################################}
280 {% macro method_callback(method, world_suffix) %}
281 {% filter conditional(method.conditional_string) %}
282 static void {{method.name}}MethodCallback{{world_suffix}}(const v8::FunctionCallbackInfo<v8::Value>& info)
283 {
284     TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMMethod");
285     {% if method.measure_as %}
286     UseCounter::count(activeExecutionContext(info.GetIsolate()), UseCounter::{{method.measure_as}});
287     {% endif %}
288     {% if method.deprecate_as %}
289     UseCounter::countDeprecation(activeExecutionContext(info.GetIsolate()), UseCounter::{{method.deprecate_as}});
290     {% endif %}
291     {% if world_suffix in method.activity_logging_world_list %}
292     V8PerContextData* contextData = V8PerContextData::from(info.GetIsolate()->GetCurrentContext());
293     if (contextData && contextData->activityLogger()) {
294         {# FIXME: replace toVectorOfArguments with toNativeArguments(info, 0)
295            and delete toVectorOfArguments #}
296         Vector<v8::Handle<v8::Value> > loggerArgs = toNativeArguments<v8::Handle<v8::Value> >(info, 0);
297         contextData->activityLogger()->log("{{interface_name}}.{{method.name}}", info.Length(), loggerArgs.data(), "Method");
298     }
299     {% endif %}
300     {% if method.is_custom %}
301     {{v8_class}}::{{method.name}}MethodCustom(info);
302     {% else %}
303     {{cpp_class}}V8Internal::{{method.name}}Method{{world_suffix}}(info);
304     {% endif %}
305     TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution");
306 }
307 {% endfilter %}
308 {% endmacro %}
309
310
311 {##############################################################################}
312 {% macro origin_safe_method_getter(method, world_suffix) %}
313 static void {{method.name}}OriginSafeMethodGetter{{world_suffix}}(const v8::PropertyCallbackInfo<v8::Value>& info)
314 {
315     {% set signature = 'v8::Local<v8::Signature>()'
316                        if method.is_do_not_check_signature else
317                        'v8::Signature::New(info.GetIsolate(), %s::domTemplate(info.GetIsolate(), currentWorldType))' % v8_class %}
318     {# FIXME: don't call GetIsolate() so often #}
319     // This is only for getting a unique pointer which we can pass to privateTemplate.
320     static int privateTemplateUniqueKey;
321     WrapperWorldType currentWorldType = worldType(info.GetIsolate());
322     V8PerIsolateData* data = V8PerIsolateData::from(info.GetIsolate());
323     {# FIXME: 1 case of [DoNotCheckSignature] in Window.idl may differ #}
324     v8::Handle<v8::FunctionTemplate> privateTemplate = data->privateTemplate(currentWorldType, &privateTemplateUniqueKey, {{cpp_class}}V8Internal::{{method.name}}MethodCallback{{world_suffix}}, v8Undefined(), {{signature}}, {{method.number_of_required_or_variadic_arguments}});
325
326     v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain({{v8_class}}::domTemplate(info.GetIsolate(), currentWorldType));
327     if (holder.IsEmpty()) {
328         // This is only reachable via |object.__proto__.func|, in which case it
329         // has already passed the same origin security check
330         v8SetReturnValue(info, privateTemplate->GetFunction());
331         return;
332     }
333     {{cpp_class}}* imp = {{v8_class}}::toNative(holder);
334     if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), imp->frame(), DoNotReportSecurityError)) {
335         static int sharedTemplateUniqueKey;
336         v8::Handle<v8::FunctionTemplate> sharedTemplate = data->privateTemplate(currentWorldType, &sharedTemplateUniqueKey, {{cpp_class}}V8Internal::{{method.name}}MethodCallback{{world_suffix}}, v8Undefined(), {{signature}}, {{method.number_of_required_or_variadic_arguments}});
337         v8SetReturnValue(info, sharedTemplate->GetFunction());
338         return;
339     }
340
341     v8::Local<v8::Value> hiddenValue = getHiddenValue(info.GetIsolate(), info.This(), "{{method.name}}");
342     if (!hiddenValue.IsEmpty()) {
343         v8SetReturnValue(info, hiddenValue);
344         return;
345     }
346
347     v8SetReturnValue(info, privateTemplate->GetFunction());
348 }
349
350 static void {{method.name}}OriginSafeMethodGetterCallback{{world_suffix}}(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>& info)
351 {
352     TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMGetter");
353     {{cpp_class}}V8Internal::{{method.name}}OriginSafeMethodGetter{{world_suffix}}(info);
354     TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution");
355 }
356 {% endmacro %}
357
358
359 {##############################################################################}
360 {% macro generate_constructor(constructor) %}
361 static void constructor{{constructor.overload_index}}(const v8::FunctionCallbackInfo<v8::Value>& info)
362 {
363     {% if constructor.has_exception_state %}
364     ExceptionState exceptionState(ExceptionState::ConstructionContext, "{{interface_name}}", info.Holder(), info.GetIsolate());
365     {% endif %}
366     {% if interface_length and not constructor.overload_index %}
367     {# FIXME: remove this UNLIKELY: constructors are heavy, so no difference. #}
368     if (UNLIKELY(info.Length() < {{interface_length}})) {
369         {{throw_type_error(constructor,
370             'ExceptionMessages::notEnoughArguments(%s, info.Length())' %
371                 interface_length) | indent(8)}}
372         return;
373     }
374     {% endif %}
375     {% for argument in constructor.arguments %}
376     {{generate_argument(constructor, argument) | indent}}
377     {% endfor %}
378     {% if is_constructor_call_with_execution_context %}
379     ExecutionContext* context = currentExecutionContext(info.GetIsolate());
380     {% endif %}
381     {% if is_constructor_call_with_document %}
382     Document& document = *toDocument(currentExecutionContext(info.GetIsolate()));
383     {% endif %}
384     {{ref_ptr}}<{{cpp_class}}> impl = {{cpp_class}}::create({{constructor.argument_list | join(', ')}});
385     v8::Handle<v8::Object> wrapper = info.Holder();
386     {% if is_constructor_raises_exception %}
387     if (exceptionState.throwIfNeeded())
388         return;
389     {% endif %}
390
391     {# FIXME: Should probably be Independent unless [ActiveDOMObject]
392               or [DependentLifetime]. #}
393     V8DOMWrapper::associateObjectWithWrapper<{{v8_class}}>(impl.release(), &{{v8_class}}::wrapperTypeInfo, wrapper, info.GetIsolate(), WrapperConfiguration::Dependent);
394     v8SetReturnValue(info, wrapper);
395 }
396 {% endmacro %}
397
398
399 {##############################################################################}
400 {% macro named_constructor_callback(constructor) %}
401 static void {{v8_class}}ConstructorCallback(const v8::FunctionCallbackInfo<v8::Value>& info)
402 {
403     if (!info.IsConstructCall()) {
404         throwTypeError(ExceptionMessages::failedToConstruct("{{constructor.name}}", "Please use the 'new' operator, this DOM object constructor cannot be called as a function."), info.GetIsolate());
405         return;
406     }
407
408     if (ConstructorMode::current() == ConstructorMode::WrapExistingObject) {
409         v8SetReturnValue(info, info.Holder());
410         return;
411     }
412
413     Document* document = currentDocument(info.GetIsolate());
414     ASSERT(document);
415
416     // Make sure the document is added to the DOM Node map. Otherwise, the {{cpp_class}} instance
417     // may end up being the only node in the map and get garbage-collected prematurely.
418     toV8(document, info.Holder(), info.GetIsolate());
419
420     {% if constructor.has_exception_state %}
421     ExceptionState exceptionState(ExceptionState::ConstructionContext, "{{interface_name}}", info.Holder(), info.GetIsolate());
422     {% endif %}
423     {% if constructor.number_of_required_arguments %}
424     if (UNLIKELY(info.Length() < {{constructor.number_of_required_arguments}})) {
425         {{throw_type_error(constructor,
426               'ExceptionMessages::notEnoughArguments(%s, info.Length())' %
427                   constructor.number_of_required_arguments) | indent(8)}}
428         return;
429     }
430     {% endif %}
431     {% for argument in constructor.arguments %}
432     {{generate_argument(constructor, argument) | indent}}
433     {% endfor %}
434     RefPtr<{{cpp_class}}> impl = {{cpp_class}}::createForJSConstructor({{constructor.argument_list | join(', ')}});
435     v8::Handle<v8::Object> wrapper = info.Holder();
436     {% if is_constructor_raises_exception %}
437     if (exceptionState.throwIfNeeded())
438         return;
439     {% endif %}
440
441     V8DOMWrapper::associateObjectWithWrapper<{{v8_class}}>(impl.release(), &{{v8_class}}Constructor::wrapperTypeInfo, wrapper, info.GetIsolate(), WrapperConfiguration::Dependent);
442     v8SetReturnValue(info, wrapper);
443 }
444 {% endmacro %}