Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / bindings / scripts / v8_methods.py
1 # Copyright (C) 2013 Google Inc. All rights reserved.
2 #
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions are
5 # met:
6 #
7 #     * Redistributions of source code must retain the above copyright
8 # notice, this list of conditions and the following disclaimer.
9 #     * Redistributions in binary form must reproduce the above
10 # copyright notice, this list of conditions and the following disclaimer
11 # in the documentation and/or other materials provided with the
12 # distribution.
13 #     * Neither the name of Google Inc. nor the names of its
14 # contributors may be used to endorse or promote products derived from
15 # this software without specific prior written permission.
16 #
17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29 """Generate template values for methods.
30
31 Extends IdlArgument with property |default_cpp_value|.
32 Extends IdlTypeBase and IdlUnionType with property |union_arguments|.
33
34 Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
35 """
36
37 from idl_definitions import IdlArgument
38 from idl_types import IdlTypeBase, IdlUnionType, inherits_interface
39 from v8_globals import includes
40 import v8_types
41 import v8_utilities
42 from v8_utilities import has_extended_attribute_value
43
44
45 # Methods with any of these require custom method registration code in the
46 # interface's configure*Template() function.
47 CUSTOM_REGISTRATION_EXTENDED_ATTRIBUTES = frozenset([
48     'DoNotCheckSecurity',
49     'DoNotCheckSignature',
50     'NotEnumerable',
51     'Unforgeable',
52 ])
53
54
55 def argument_needs_try_catch(argument, return_promise):
56     idl_type = argument.idl_type
57     base_type = idl_type.base_type
58
59     return not (
60         # These cases are handled by separate code paths in the
61         # generate_argument() macro in Source/bindings/templates/methods.cpp.
62         idl_type.is_callback_interface or
63         base_type == 'SerializedScriptValue' or
64         (argument.is_variadic and idl_type.is_wrapper_type) or
65         # String and enumeration arguments converted using one of the
66         # TOSTRING_* macros except for _PROMISE variants in
67         # Source/bindings/core/v8/V8BindingMacros.h don't use a v8::TryCatch.
68         (base_type == 'DOMString' and not argument.is_variadic and
69          not return_promise))
70
71
72 def use_local_result(method):
73     extended_attributes = method.extended_attributes
74     idl_type = method.idl_type
75     return (has_extended_attribute_value(method, 'CallWith', 'ScriptState') or
76             'ImplementedInPrivateScript' in extended_attributes or
77             'RaisesException' in extended_attributes or
78             idl_type.is_union_type or
79             idl_type.is_explicit_nullable)
80
81
82 def method_context(interface, method):
83     arguments = method.arguments
84     extended_attributes = method.extended_attributes
85     idl_type = method.idl_type
86     is_static = method.is_static
87     name = method.name
88     return_promise = idl_type.name == 'Promise'
89
90     idl_type.add_includes_for_type()
91     this_cpp_value = cpp_value(interface, method, len(arguments))
92
93     def function_template():
94         if is_static:
95             return 'functionTemplate'
96         if 'Unforgeable' in extended_attributes:
97             return 'instanceTemplate'
98         return 'prototypeTemplate'
99
100     is_implemented_in_private_script = 'ImplementedInPrivateScript' in extended_attributes
101     if is_implemented_in_private_script:
102         includes.add('bindings/core/v8/PrivateScriptRunner.h')
103         includes.add('core/frame/LocalFrame.h')
104         includes.add('platform/ScriptForbiddenScope.h')
105
106     # [OnlyExposedToPrivateScript]
107     is_only_exposed_to_private_script = 'OnlyExposedToPrivateScript' in extended_attributes
108
109     is_call_with_script_arguments = has_extended_attribute_value(method, 'CallWith', 'ScriptArguments')
110     if is_call_with_script_arguments:
111         includes.update(['bindings/core/v8/ScriptCallStackFactory.h',
112                          'core/inspector/ScriptArguments.h'])
113     is_call_with_script_state = has_extended_attribute_value(method, 'CallWith', 'ScriptState')
114     if is_call_with_script_state:
115         includes.add('bindings/core/v8/ScriptState.h')
116     is_check_security_for_node = 'CheckSecurity' in extended_attributes
117     if is_check_security_for_node:
118         includes.add('bindings/core/v8/BindingSecurity.h')
119     is_custom_element_callbacks = 'CustomElementCallbacks' in extended_attributes
120     if is_custom_element_callbacks:
121         includes.add('core/dom/custom/CustomElementCallbackDispatcher.h')
122
123     is_check_security_for_frame = (
124         'CheckSecurity' in interface.extended_attributes and
125         'DoNotCheckSecurity' not in extended_attributes)
126     is_raises_exception = 'RaisesException' in extended_attributes
127
128     arguments_need_try_catch = (
129         any(argument_needs_try_catch(argument, return_promise)
130             for argument in arguments))
131
132     return {
133         'activity_logging_world_list': v8_utilities.activity_logging_world_list(method),  # [ActivityLogging]
134         'arguments': [argument_context(interface, method, argument, index)
135                       for index, argument in enumerate(arguments)],
136         'argument_declarations_for_private_script':
137             argument_declarations_for_private_script(interface, method),
138         'arguments_need_try_catch': arguments_need_try_catch,
139         'conditional_string': v8_utilities.conditional_string(method),
140         'cpp_type': (v8_types.cpp_template_type('Nullable', idl_type.cpp_type)
141                      if idl_type.is_explicit_nullable else idl_type.cpp_type),
142         'cpp_value': this_cpp_value,
143         'cpp_type_initializer': idl_type.cpp_type_initializer,
144         'custom_registration_extended_attributes':
145             CUSTOM_REGISTRATION_EXTENDED_ATTRIBUTES.intersection(
146                 extended_attributes.iterkeys()),
147         'deprecate_as': v8_utilities.deprecate_as(method),  # [DeprecateAs]
148         'exposed_test': v8_utilities.exposed(method, interface),  # [Exposed]
149         'function_template': function_template(),
150         'has_custom_registration': is_static or
151             v8_utilities.has_extended_attribute(
152                 method, CUSTOM_REGISTRATION_EXTENDED_ATTRIBUTES),
153         'has_exception_state':
154             is_raises_exception or
155             is_check_security_for_frame or
156             interface.name == 'EventTarget' or  # FIXME: merge with is_check_security_for_frame http://crbug.com/383699
157             any(argument for argument in arguments
158                 if argument.idl_type.name == 'SerializedScriptValue' or
159                    argument.idl_type.may_raise_exception_on_conversion),
160         'idl_type': idl_type.base_type,
161         'is_call_with_execution_context': has_extended_attribute_value(method, 'CallWith', 'ExecutionContext'),
162         'is_call_with_script_arguments': is_call_with_script_arguments,
163         'is_call_with_script_state': is_call_with_script_state,
164         'is_check_security_for_frame': is_check_security_for_frame,
165         'is_check_security_for_node': is_check_security_for_node,
166         'is_custom': 'Custom' in extended_attributes,
167         'is_custom_element_callbacks': is_custom_element_callbacks,
168         'is_do_not_check_security': 'DoNotCheckSecurity' in extended_attributes,
169         'is_do_not_check_signature': 'DoNotCheckSignature' in extended_attributes,
170         'is_explicit_nullable': idl_type.is_explicit_nullable,
171         'is_implemented_in_private_script': is_implemented_in_private_script,
172         'is_partial_interface_member':
173             'PartialInterfaceImplementedAs' in extended_attributes,
174         'is_per_world_bindings': 'PerWorldBindings' in extended_attributes,
175         'is_raises_exception': is_raises_exception,
176         'is_read_only': 'Unforgeable' in extended_attributes,
177         'is_static': is_static,
178         'is_variadic': arguments and arguments[-1].is_variadic,
179         'measure_as': v8_utilities.measure_as(method),  # [MeasureAs]
180         'name': name,
181         'number_of_arguments': len(arguments),
182         'number_of_required_arguments': len([
183             argument for argument in arguments
184             if not (argument.is_optional or argument.is_variadic)]),
185         'number_of_required_or_variadic_arguments': len([
186             argument for argument in arguments
187             if not argument.is_optional]),
188         'only_exposed_to_private_script': is_only_exposed_to_private_script,
189         'per_context_enabled_function': v8_utilities.per_context_enabled_function_name(method),  # [PerContextEnabled]
190         'private_script_v8_value_to_local_cpp_value': idl_type.v8_value_to_local_cpp_value(
191             extended_attributes, 'v8Value', 'cppValue', isolate='scriptState->isolate()', used_in_private_script=True),
192         'property_attributes': property_attributes(method),
193         'runtime_enabled_function': v8_utilities.runtime_enabled_function_name(method),  # [RuntimeEnabled]
194         'should_be_exposed_to_script': not (is_implemented_in_private_script and is_only_exposed_to_private_script),
195         'signature': 'v8::Local<v8::Signature>()' if is_static or 'DoNotCheckSignature' in extended_attributes else 'defaultSignature',
196         'union_arguments': idl_type.union_arguments,
197         'use_local_result': use_local_result(method),
198         'v8_set_return_value': v8_set_return_value(interface.name, method, this_cpp_value),
199         'v8_set_return_value_for_main_world': v8_set_return_value(interface.name, method, this_cpp_value, for_main_world=True),
200         'world_suffixes': ['', 'ForMainWorld'] if 'PerWorldBindings' in extended_attributes else [''],  # [PerWorldBindings],
201     }
202
203
204 def argument_context(interface, method, argument, index):
205     extended_attributes = argument.extended_attributes
206     idl_type = argument.idl_type
207     this_cpp_value = cpp_value(interface, method, index)
208     is_variadic_wrapper_type = argument.is_variadic and idl_type.is_wrapper_type
209     return_promise = (method.idl_type.name == 'Promise' if method.idl_type
210                                                         else False)
211
212     if ('ImplementedInPrivateScript' in extended_attributes and
213         not idl_type.is_wrapper_type and
214         not idl_type.is_basic_type):
215         raise Exception('Private scripts supports only primitive types and DOM wrappers.')
216
217     return {
218         'cpp_type': idl_type.cpp_type_args(extended_attributes=extended_attributes,
219                                            raw_type=True,
220                                            used_as_variadic_argument=argument.is_variadic),
221         'cpp_value': this_cpp_value,
222         # FIXME: check that the default value's type is compatible with the argument's
223         'default_value': argument.default_cpp_value,
224         'enum_validation_expression': idl_type.enum_validation_expression,
225         'handle': '%sHandle' % argument.name,
226         # FIXME: remove once [Default] removed and just use argument.default_value
227         'has_default': 'Default' in extended_attributes or argument.default_value,
228         'has_type_checking_interface':
229             (has_extended_attribute_value(interface, 'TypeChecking', 'Interface') or
230              has_extended_attribute_value(method, 'TypeChecking', 'Interface')) and
231             idl_type.is_wrapper_type,
232         'has_type_checking_unrestricted':
233             (has_extended_attribute_value(interface, 'TypeChecking', 'Unrestricted') or
234              has_extended_attribute_value(method, 'TypeChecking', 'Unrestricted')) and
235             idl_type.name in ('Float', 'Double'),
236         # Dictionary is special-cased, but arrays and sequences shouldn't be
237         'idl_type': idl_type.base_type,
238         'idl_type_object': idl_type,
239         'index': index,
240         'is_clamp': 'Clamp' in extended_attributes,
241         'is_callback_interface': idl_type.is_callback_interface,
242         'is_nullable': idl_type.is_nullable,
243         'is_optional': argument.is_optional,
244         'is_variadic_wrapper_type': is_variadic_wrapper_type,
245         'is_wrapper_type': idl_type.is_wrapper_type,
246         'name': argument.name,
247         'private_script_cpp_value_to_v8_value': idl_type.cpp_value_to_v8_value(
248             argument.name, isolate='scriptState->isolate()',
249             creation_context='scriptState->context()->Global()'),
250         'v8_set_return_value': v8_set_return_value(interface.name, method, this_cpp_value),
251         'v8_set_return_value_for_main_world': v8_set_return_value(interface.name, method, this_cpp_value, for_main_world=True),
252         'v8_value_to_local_cpp_value': v8_value_to_local_cpp_value(argument, index, return_promise=return_promise),
253         'vector_type': v8_types.cpp_ptr_type('Vector', 'HeapVector', idl_type.gc_type),
254     }
255
256
257 def argument_declarations_for_private_script(interface, method):
258     argument_declarations = ['LocalFrame* frame']
259     argument_declarations.append('%s* holderImpl' % interface.name)
260     argument_declarations.extend(['%s %s' % (argument.idl_type.cpp_type_args(
261         used_as_rvalue_type=True), argument.name) for argument in method.arguments])
262     if method.idl_type.name != 'void':
263         argument_declarations.append('%s* %s' % (method.idl_type.cpp_type, 'result'))
264     return argument_declarations
265
266
267 ################################################################################
268 # Value handling
269 ################################################################################
270
271 def cpp_value(interface, method, number_of_arguments):
272     def cpp_argument(argument):
273         idl_type = argument.idl_type
274         if idl_type.name == 'EventListener':
275             return argument.name
276         if (idl_type.is_callback_interface or
277             idl_type.name in ['NodeFilter', 'NodeFilterOrNull',
278                               'XPathNSResolver', 'XPathNSResolverOrNull']):
279             # FIXME: remove this special case
280             return '%s.release()' % argument.name
281         return argument.name
282
283     # Truncate omitted optional arguments
284     arguments = method.arguments[:number_of_arguments]
285     cpp_arguments = []
286     if 'ImplementedInPrivateScript' in method.extended_attributes:
287         cpp_arguments.append('toFrameIfNotDetached(info.GetIsolate()->GetCurrentContext())')
288         cpp_arguments.append('impl')
289
290     if method.is_constructor:
291         call_with_values = interface.extended_attributes.get('ConstructorCallWith')
292     else:
293         call_with_values = method.extended_attributes.get('CallWith')
294     cpp_arguments.extend(v8_utilities.call_with_arguments(call_with_values))
295
296     # Members of IDL partial interface definitions are implemented in C++ as
297     # static member functions, which for instance members (non-static members)
298     # take *impl as their first argument
299     if ('PartialInterfaceImplementedAs' in method.extended_attributes and
300         not 'ImplementedInPrivateScript' in method.extended_attributes and
301         not method.is_static):
302         cpp_arguments.append('*impl')
303     cpp_arguments.extend(cpp_argument(argument) for argument in arguments)
304
305     this_union_arguments = method.idl_type and method.idl_type.union_arguments
306     if this_union_arguments:
307         cpp_arguments.extend([member_argument['cpp_value']
308                               for member_argument in this_union_arguments])
309
310     if 'ImplementedInPrivateScript' in method.extended_attributes:
311         if method.idl_type.name != 'void':
312             cpp_arguments.append('&result')
313     elif ('RaisesException' in method.extended_attributes or
314         (method.is_constructor and
315          has_extended_attribute_value(interface, 'RaisesException', 'Constructor'))):
316         cpp_arguments.append('exceptionState')
317
318     if method.name == 'Constructor':
319         base_name = 'create'
320     elif method.name == 'NamedConstructor':
321         base_name = 'createForJSConstructor'
322     elif 'ImplementedInPrivateScript' in method.extended_attributes:
323         base_name = '%sMethod' % method.name
324     else:
325         base_name = v8_utilities.cpp_name(method)
326
327     cpp_method_name = v8_utilities.scoped_name(interface, method, base_name)
328     return '%s(%s)' % (cpp_method_name, ', '.join(cpp_arguments))
329
330
331 def v8_set_return_value(interface_name, method, cpp_value, for_main_world=False):
332     idl_type = method.idl_type
333     extended_attributes = method.extended_attributes
334     if not idl_type or idl_type.name == 'void':
335         # Constructors and void methods don't have a return type
336         return None
337
338     if ('ImplementedInPrivateScript' in extended_attributes and
339         not idl_type.is_wrapper_type and
340         not idl_type.is_basic_type):
341         raise Exception('Private scripts supports only primitive types and DOM wrappers.')
342
343     release = False
344     # [CallWith=ScriptState], [RaisesException]
345     if use_local_result(method):
346         if idl_type.is_explicit_nullable:
347             # result is of type Nullable<T>
348             cpp_value = 'result.get()'
349         else:
350             cpp_value = 'result'
351         release = idl_type.release
352
353     script_wrappable = 'impl' if inherits_interface(interface_name, 'Node') else ''
354     return idl_type.v8_set_return_value(cpp_value, extended_attributes, script_wrappable=script_wrappable, release=release, for_main_world=for_main_world)
355
356
357 def v8_value_to_local_cpp_variadic_value(argument, index, return_promise):
358     assert argument.is_variadic
359     idl_type = argument.idl_type
360
361     suffix = ''
362
363     macro = 'TONATIVE_VOID'
364     macro_args = [
365       argument.name,
366       'toNativeArguments<%s>(info, %s)' % (idl_type.cpp_type, index),
367     ]
368
369     if return_promise:
370         suffix += '_PROMISE'
371         macro_args.append('info')
372
373     suffix += '_INTERNAL'
374
375     return '%s%s(%s)' % (macro, suffix, ', '.join(macro_args))
376
377
378 def v8_value_to_local_cpp_value(argument, index, return_promise=False):
379     extended_attributes = argument.extended_attributes
380     idl_type = argument.idl_type
381     name = argument.name
382     if argument.is_variadic:
383         return v8_value_to_local_cpp_variadic_value(argument, index, return_promise)
384     return idl_type.v8_value_to_local_cpp_value(extended_attributes, 'info[%s]' % index,
385                                                 name, index=index, declare_variable=False, return_promise=return_promise)
386
387
388 ################################################################################
389 # Auxiliary functions
390 ################################################################################
391
392 # [NotEnumerable]
393 def property_attributes(method):
394     extended_attributes = method.extended_attributes
395     property_attributes_list = []
396     if 'NotEnumerable' in extended_attributes:
397         property_attributes_list.append('v8::DontEnum')
398     if 'Unforgeable' in extended_attributes:
399         property_attributes_list.append('v8::ReadOnly')
400     if property_attributes_list:
401         property_attributes_list.insert(0, 'v8::DontDelete')
402     return property_attributes_list
403
404
405 def union_member_argument_context(idl_type, index):
406     """Returns a context of union member for argument."""
407     this_cpp_value = 'result%d' % index
408     this_cpp_type = idl_type.cpp_type
409     cpp_return_value = this_cpp_value
410
411     if not idl_type.cpp_type_has_null_value:
412         this_cpp_type = v8_types.cpp_template_type('Nullable', this_cpp_type)
413         cpp_return_value = '%s.get()' % this_cpp_value
414
415     if idl_type.is_string_type:
416         null_check_value = '!%s.isNull()' % this_cpp_value
417     else:
418         null_check_value = this_cpp_value
419
420     return {
421         'cpp_type': this_cpp_type,
422         'cpp_value': this_cpp_value,
423         'null_check_value': null_check_value,
424         'v8_set_return_value': idl_type.v8_set_return_value(
425             cpp_value=cpp_return_value,
426             release=idl_type.release),
427     }
428
429
430 def union_arguments(idl_type):
431     return [union_member_argument_context(member_idl_type, index)
432             for index, member_idl_type
433             in enumerate(idl_type.member_types)]
434
435
436 def argument_default_cpp_value(argument):
437     if not argument.default_value:
438         return None
439     return argument.idl_type.literal_cpp_value(argument.default_value)
440
441 IdlTypeBase.union_arguments = None
442 IdlUnionType.union_arguments = property(union_arguments)
443 IdlArgument.default_cpp_value = property(argument_default_cpp_value)