Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / bindings / scripts / unstable / v8_attributes.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 attributes.
30
31 FIXME: Not currently used in build.
32 This is a rewrite of the Perl IDL compiler in Python, but is not complete.
33 Once it is complete, we will switch all IDL files over to Python at once.
34 Until then, please work on the Perl IDL compiler.
35 For details, see bug http://crbug.com/239771
36 """
37
38 from v8_globals import includes, interfaces
39 import v8_types
40 import v8_utilities
41 from v8_utilities import capitalize, cpp_name, has_extended_attribute, uncapitalize
42
43
44 def generate_attribute(interface, attribute):
45     idl_type = attribute.idl_type
46     extended_attributes = attribute.extended_attributes
47
48     v8_types.add_includes_for_type(idl_type)
49
50     # [CheckSecurity]
51     is_check_security_for_node = 'CheckSecurity' in extended_attributes
52     if is_check_security_for_node:
53         includes.add('bindings/v8/BindingSecurity.h')
54     # [Custom]
55     has_custom_getter = ('Custom' in extended_attributes and
56                          extended_attributes['Custom'] in [None, 'Getter'])
57     has_custom_setter = (not attribute.is_read_only and
58                          'Custom' in extended_attributes and
59                          extended_attributes['Custom'] in [None, 'Setter'])
60     # [CustomElementCallbacks], [Reflect]
61     is_custom_element_callbacks = 'CustomElementCallbacks' in extended_attributes
62     is_reflect = 'Reflect' in extended_attributes
63     if is_custom_element_callbacks or is_reflect:
64         includes.add('core/dom/custom/CustomElementCallbackDispatcher.h')
65     # [RaisesException], [RaisesException=Setter]
66     is_setter_raises_exception = (
67         'RaisesException' in extended_attributes and
68         extended_attributes['RaisesException'] in [None, 'Setter'])
69     # [StrictTypeChecking]
70     has_strict_type_checking = (
71         ('StrictTypeChecking' in extended_attributes or
72          'StrictTypeChecking' in interface.extended_attributes) and
73         v8_types.is_wrapper_type(idl_type))
74
75     if (idl_type == 'EventHandler' and
76         interface.name in ['Window', 'WorkerGlobalScope'] and
77         attribute.name == 'onerror'):
78         includes.add('bindings/v8/V8ErrorHandler.h')
79
80     contents = {
81         'access_control_list': access_control_list(attribute),
82         'activity_logging_world_list_for_getter': v8_utilities.activity_logging_world_list(attribute, 'Getter'),  # [ActivityLogging]
83         'activity_logging_world_list_for_setter': v8_utilities.activity_logging_world_list(attribute, 'Setter'),  # [ActivityLogging]
84         'cached_attribute_validation_method': extended_attributes.get('CachedAttribute'),
85         'conditional_string': v8_utilities.conditional_string(attribute),
86         'constructor_type': v8_types.constructor_type(idl_type)
87                             if is_constructor_attribute(attribute) else None,
88         'cpp_name': cpp_name(attribute),
89         'cpp_type': v8_types.cpp_type(idl_type),
90         'deprecate_as': v8_utilities.deprecate_as(attribute),  # [DeprecateAs]
91         'enum_validation_expression':
92             v8_utilities.enum_validation_expression(idl_type),
93         'has_custom_getter': has_custom_getter,
94         'has_custom_setter': has_custom_setter,
95         'has_strict_type_checking': has_strict_type_checking,
96         'idl_type': idl_type,
97         'is_call_with_execution_context': v8_utilities.has_extended_attribute_value(attribute, 'CallWith', 'ExecutionContext'),
98         'is_check_security_for_node': is_check_security_for_node,
99         'is_custom_element_callbacks': is_custom_element_callbacks,
100         'is_expose_js_accessors': 'ExposeJSAccessors' in extended_attributes,
101         'is_getter_raises_exception': (  # [RaisesException]
102             'RaisesException' in extended_attributes and
103             extended_attributes['RaisesException'] in [None, 'Getter']),
104         'is_initialized_by_event_constructor':
105             'InitializedByEventConstructor' in extended_attributes,
106         'is_keep_alive_for_gc': is_keep_alive_for_gc(interface, attribute),
107         'is_nullable': attribute.is_nullable,
108         'is_per_world_bindings': 'PerWorldBindings' in extended_attributes,
109         'is_read_only': attribute.is_read_only,
110         'is_reflect': is_reflect,
111         'is_replaceable': 'Replaceable' in attribute.extended_attributes,
112         'is_setter_call_with_execution_context': v8_utilities.has_extended_attribute_value(attribute, 'SetterCallWith', 'ExecutionContext'),
113         'is_setter_raises_exception': is_setter_raises_exception,
114         'has_setter_exception_state': (
115             is_setter_raises_exception or has_strict_type_checking or
116             v8_types.is_integer_type(idl_type)),
117         'is_static': attribute.is_static,
118         'is_url': 'URL' in extended_attributes,
119         'is_unforgeable': 'Unforgeable' in extended_attributes,
120         'measure_as': v8_utilities.measure_as(attribute),  # [MeasureAs]
121         'name': attribute.name,
122         'per_context_enabled_function': v8_utilities.per_context_enabled_function_name(attribute),  # [PerContextEnabled]
123         'property_attributes': property_attributes(attribute),
124         'put_forwards': 'PutForwards' in extended_attributes,
125         'reflect_empty': extended_attributes.get('ReflectEmpty'),
126         'reflect_invalid': extended_attributes.get('ReflectInvalid', ''),
127         'reflect_missing': extended_attributes.get('ReflectMissing'),
128         'reflect_only': extended_attributes['ReflectOnly'].split('|')
129             if 'ReflectOnly' in extended_attributes else None,
130         'setter_callback': setter_callback_name(interface, attribute),
131         'v8_type': v8_types.v8_type(idl_type),
132         'runtime_enabled_function': v8_utilities.runtime_enabled_function_name(attribute),  # [RuntimeEnabled]
133         'world_suffixes': ['', 'ForMainWorld']
134                           if 'PerWorldBindings' in extended_attributes
135                           else [''],  # [PerWorldBindings]
136     }
137
138     if is_constructor_attribute(attribute):
139         return contents
140     if not has_custom_getter:
141         generate_getter(interface, attribute, contents)
142     if (not has_custom_setter and
143         (not attribute.is_read_only or 'PutForwards' in extended_attributes)):
144         generate_setter(interface, attribute, contents)
145
146     return contents
147
148
149 ################################################################################
150 # Getter
151 ################################################################################
152
153 def generate_getter(interface, attribute, contents):
154     idl_type = attribute.idl_type
155     extended_attributes = attribute.extended_attributes
156
157     cpp_value = getter_expression(interface, attribute, contents)
158     # Normally we can inline the function call into the return statement to
159     # avoid the overhead of using a Ref<> temporary, but for some cases
160     # (nullable types, EventHandler, [CachedAttribute], or if there are
161     # exceptions), we need to use a local variable.
162     # FIXME: check if compilers are smart enough to inline this, and if so,
163     # always use a local variable (for readability and CG simplicity).
164     release = False
165     if (attribute.is_nullable or
166         idl_type == 'EventHandler' or
167         'CachedAttribute' in extended_attributes or
168         contents['is_getter_raises_exception']):
169         contents['cpp_value_original'] = cpp_value
170         cpp_value = 'jsValue'
171         # EventHandler has special handling
172         if idl_type != 'EventHandler' and v8_types.is_interface_type(idl_type):
173             release = True
174
175     if 'ReflectOnly' in extended_attributes:
176         contents['cpp_value_original'] = cpp_value
177         # FIXME: rename to jsValue
178         cpp_value = 'resultValue'
179
180     def v8_set_return_value_statement(for_main_world=False):
181         if contents['is_keep_alive_for_gc']:
182             return 'v8SetReturnValue(info, wrapper)'
183         return v8_types.v8_set_return_value(idl_type, cpp_value, extended_attributes=extended_attributes, script_wrappable='imp', release=release, for_main_world=for_main_world)
184
185     contents.update({
186         'cpp_value': cpp_value,
187         'v8_set_return_value_for_main_world': v8_set_return_value_statement(for_main_world=True),
188         'v8_set_return_value': v8_set_return_value_statement(),
189     })
190
191
192 def getter_expression(interface, attribute, contents):
193     arguments = []
194     this_getter_base_name = getter_base_name(attribute, arguments)
195     getter_name = v8_utilities.scoped_name(interface, attribute, this_getter_base_name)
196
197     arguments.extend(v8_utilities.call_with_arguments(attribute))
198     if ('ImplementedBy' in attribute.extended_attributes and
199         not attribute.is_static):
200         arguments.append('imp')
201     if attribute.is_nullable:
202         arguments.append('isNull')
203     if contents['is_getter_raises_exception']:
204         arguments.append('exceptionState')
205     return '%s(%s)' % (getter_name, ', '.join(arguments))
206
207
208 CONTENT_ATTRIBUTE_GETTER_NAMES = {
209     'boolean': 'fastHasAttribute',
210     'long': 'getIntegralAttribute',
211     'unsigned long': 'getUnsignedIntegralAttribute',
212 }
213
214
215 def getter_base_name(attribute, arguments):
216     extended_attributes = attribute.extended_attributes
217     if 'Reflect' not in extended_attributes:
218         return uncapitalize(cpp_name(attribute))
219
220     content_attribute_name = extended_attributes['Reflect'] or attribute.name.lower()
221     if content_attribute_name in ['class', 'id', 'name']:
222         # Special-case for performance optimization.
223         return 'get%sAttribute' % content_attribute_name.capitalize()
224
225     arguments.append(scoped_content_attribute_name(attribute))
226
227     idl_type = attribute.idl_type
228     if idl_type in CONTENT_ATTRIBUTE_GETTER_NAMES:
229         return CONTENT_ATTRIBUTE_GETTER_NAMES[idl_type]
230     if 'URL' in attribute.extended_attributes:
231         return 'getURLAttribute'
232     return 'fastGetAttribute'
233
234
235 def is_keep_alive_for_gc(interface, attribute):
236     idl_type = attribute.idl_type
237     extended_attributes = attribute.extended_attributes
238     return (
239         # For readonly attributes, for performance reasons we keep the attribute
240         # wrapper alive while the owner wrapper is alive, because the attribute
241         # never changes.
242         (attribute.is_read_only and
243          v8_types.is_wrapper_type(idl_type) and
244          # There are some exceptions, however:
245          not(
246              # Node lifetime is managed by object grouping.
247              v8_types.inherits_interface(interface.name, 'Node') or
248              v8_types.inherits_interface(idl_type, 'Node') or
249              # A self-reference is unnecessary.
250              attribute.name == 'self' or
251              # FIXME: Remove these hard-coded hacks.
252              idl_type in ['EventTarget', 'Window'] or
253              idl_type.startswith('HTML'))))
254
255
256 ################################################################################
257 # Setter
258 ################################################################################
259
260 def generate_setter(interface, attribute, contents):
261     def target_attribute():
262         target_interface_name = attribute.idl_type
263         target_attribute_name = extended_attributes['PutForwards']
264         target_interface = interfaces[target_interface_name]
265         try:
266             return next(attribute
267                         for attribute in target_interface.attributes
268                         if attribute.name == target_attribute_name)
269         except StopIteration:
270             raise Exception('[PutForward] target not found:\n'
271                             'Attribute "%s" is not present in interface "%s"' %
272                             (target_attribute_name, target_interface_name))
273
274     extended_attributes = attribute.extended_attributes
275
276     if 'PutForwards' in extended_attributes:
277         # Use target attribute in place of original attribute
278         attribute = target_attribute()
279
280     contents.update({
281         'cpp_setter': setter_expression(interface, attribute, contents),
282         'v8_value_to_local_cpp_value': v8_types.v8_value_to_local_cpp_value(
283             attribute.idl_type, extended_attributes, 'jsValue', 'cppValue'),
284     })
285
286
287 def setter_expression(interface, attribute, contents):
288     extended_attributes = attribute.extended_attributes
289     arguments = v8_utilities.call_with_arguments(attribute, extended_attributes.get('SetterCallWith'))
290
291     this_setter_base_name = setter_base_name(attribute, arguments)
292     setter_name = v8_utilities.scoped_name(interface, attribute, this_setter_base_name)
293
294     if ('ImplementedBy' in extended_attributes and
295         not attribute.is_static):
296         arguments.append('imp')
297     idl_type = attribute.idl_type
298     if idl_type == 'EventHandler':
299         getter_name = v8_utilities.scoped_name(interface, attribute, cpp_name(attribute))
300         contents['event_handler_getter_expression'] = '%s(%s)' % (
301             getter_name, ', '.join(arguments))
302         if (interface.name in ['Window', 'WorkerGlobalScope'] and
303             attribute.name == 'onerror'):
304             includes.add('bindings/v8/V8ErrorHandler.h')
305             arguments.append('V8EventListenerList::findOrCreateWrapper<V8ErrorHandler>(jsValue, true, info.GetIsolate())')
306         else:
307             arguments.append('V8EventListenerList::getEventListener(jsValue, true, ListenerFindOrCreate)')
308     elif v8_types.is_interface_type(idl_type) and not v8_types.array_type(idl_type):
309         # FIXME: should be able to eliminate WTF::getPtr in most or all cases
310         arguments.append('WTF::getPtr(cppValue)')
311     else:
312         arguments.append('cppValue')
313     if contents['is_setter_raises_exception']:
314         arguments.append('exceptionState')
315
316     return '%s(%s)' % (setter_name, ', '.join(arguments))
317
318
319 CONTENT_ATTRIBUTE_SETTER_NAMES = {
320     'boolean': 'setBooleanAttribute',
321     'long': 'setIntegralAttribute',
322     'unsigned long': 'setUnsignedIntegralAttribute',
323 }
324
325
326 def setter_base_name(attribute, arguments):
327     if 'Reflect' not in attribute.extended_attributes:
328         return 'set%s' % capitalize(cpp_name(attribute))
329     arguments.append(scoped_content_attribute_name(attribute))
330
331     idl_type = attribute.idl_type
332     if idl_type in CONTENT_ATTRIBUTE_SETTER_NAMES:
333         return CONTENT_ATTRIBUTE_SETTER_NAMES[idl_type]
334     return 'setAttribute'
335
336
337 def scoped_content_attribute_name(attribute):
338     content_attribute_name = attribute.extended_attributes['Reflect'] or attribute.name.lower()
339     namespace = 'HTMLNames'  # FIXME: can be SVG too
340     includes.add('%s.h' % namespace)
341     return '%s::%sAttr' % (namespace, content_attribute_name)
342
343
344 ################################################################################
345 # Attribute configuration
346 ################################################################################
347
348 # [Replaceable]
349 def setter_callback_name(interface, attribute):
350     cpp_class_name = cpp_name(interface)
351     extended_attributes = attribute.extended_attributes
352     if (('Replaceable' in extended_attributes and
353          'PutForwards' not in extended_attributes) or
354         is_constructor_attribute(attribute)):
355         # FIXME: rename to ForceSetAttributeOnThisCallback, since also used for Constructors
356         return '{0}V8Internal::{0}ReplaceableAttributeSetterCallback'.format(cpp_class_name)
357     if attribute.is_read_only and 'PutForwards' not in extended_attributes:
358         return '0'
359     return '%sV8Internal::%sAttributeSetterCallback' % (cpp_class_name, attribute.name)
360
361
362 # [DoNotCheckSecurity], [Unforgeable]
363 def access_control_list(attribute):
364     extended_attributes = attribute.extended_attributes
365     access_control = []
366     if 'DoNotCheckSecurity' in extended_attributes:
367         do_not_check_security = extended_attributes['DoNotCheckSecurity']
368         if do_not_check_security == 'Setter':
369             access_control.append('v8::ALL_CAN_WRITE')
370         else:
371             access_control.append('v8::ALL_CAN_READ')
372             if (not attribute.is_read_only or
373                 'Replaceable' in extended_attributes):
374                 access_control.append('v8::ALL_CAN_WRITE')
375     if 'Unforgeable' in extended_attributes:
376         access_control.append('v8::PROHIBITS_OVERWRITING')
377     return access_control or ['v8::DEFAULT']
378
379
380 # [NotEnumerable], [Unforgeable]
381 def property_attributes(attribute):
382     extended_attributes = attribute.extended_attributes
383     property_attributes_list = []
384     if ('NotEnumerable' in extended_attributes or
385         is_constructor_attribute(attribute)):
386         property_attributes_list.append('v8::DontEnum')
387     if 'Unforgeable' in extended_attributes:
388         property_attributes_list.append('v8::DontDelete')
389     return property_attributes_list or ['v8::None']
390
391
392 ################################################################################
393 # Constructors
394 ################################################################################
395
396 def is_constructor_attribute(attribute):
397     return attribute.idl_type.endswith('Constructor')