Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / bindings / scripts / unstable / v8_types.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 """Functions for type handling and type conversion (Blink/C++ <-> V8/JS).
30
31 Spec:
32 http://www.w3.org/TR/WebIDL/#es-type-mapping
33
34 FIXME: Not currently used in build.
35 This is a rewrite of the Perl IDL compiler in Python, but is not complete.
36 Once it is complete, we will switch all IDL files over to Python at once.
37 Until then, please work on the Perl IDL compiler.
38 For details, see bug http://crbug.com/239771
39 """
40
41 import posixpath
42 import re
43
44 from v8_globals import includes
45 import idl_definitions  # for UnionType
46 from v8_utilities import strip_suffix
47
48 ################################################################################
49 # IDL types
50 ################################################################################
51
52 BASIC_TYPES = set([
53     # Built-in, non-composite, non-object data types
54     # http://www.w3.org/TR/WebIDL/#dfn-primitive-type
55     'boolean',
56     'float',
57     # unrestricted float is not supported
58     'double',
59     # unrestricted double is not supported
60     # http://www.w3.org/TR/WebIDL/#idl-types
61     'DOMString',
62     'Date',
63     # http://www.w3.org/TR/WebIDL/#es-type-mapping
64     'void',
65 ])
66 INTEGER_TYPES = set([
67     # http://www.w3.org/TR/WebIDL/#dfn-integer-type
68     'byte',
69     'octet',
70     'short',
71     'unsigned short',
72     # int and unsigned are not IDL types
73     'long',
74     'unsigned long',
75     'long long',
76     'unsigned long long',
77 ])
78 BASIC_TYPES.update(INTEGER_TYPES)
79
80 ancestors = {}  # interface_name -> ancestors
81 callback_functions = set()
82 callback_interfaces = set()
83 enums = {}  # name -> values
84
85
86 def array_or_sequence_type(idl_type):
87     return array_type(idl_type) or sequence_type(idl_type)
88
89
90 def array_type(idl_type):
91     if is_union_type(idl_type):
92         # We do not support arrays of union types
93         return False
94     matched = re.match(r'([\w\s]+)\[\]', idl_type)
95     return matched and matched.group(1)
96
97
98 def is_basic_type(idl_type):
99     return idl_type in BASIC_TYPES
100
101
102 def is_integer_type(idl_type):
103     return idl_type in INTEGER_TYPES
104
105
106 def is_callback_function(idl_type):
107     return idl_type in callback_functions
108
109
110 def set_callback_functions(new_callback_functions):
111     callback_functions.update(new_callback_functions)
112
113
114 def is_callback_interface(idl_type):
115     return idl_type in callback_interfaces
116
117
118 def set_callback_interfaces(new_callback_interfaces):
119     callback_interfaces.update(new_callback_interfaces)
120
121
122 def is_composite_type(idl_type):
123     return (idl_type == 'any' or
124             array_type(idl_type) or
125             sequence_type(idl_type) or
126             is_union_type(idl_type))
127
128
129 def is_enum(idl_type):
130     return idl_type in enums
131
132
133 def enum_values(idl_type):
134     return enums.get(idl_type)
135
136
137 def set_enums(new_enums):
138     enums.update(new_enums)
139
140
141 def inherits_interface(interface_name, ancestor_name):
142     return (interface_name == ancestor_name or
143             ancestor_name in ancestors.get(interface_name, []))
144
145
146 def set_ancestors(new_ancestors):
147     ancestors.update(new_ancestors)
148
149
150 def is_interface_type(idl_type):
151     # Anything that is not another type is an interface type.
152     # http://www.w3.org/TR/WebIDL/#idl-types
153     # http://www.w3.org/TR/WebIDL/#idl-interface
154     # In C++ these are RefPtr or PassRefPtr types.
155     return not(is_basic_type(idl_type) or
156                is_composite_type(idl_type) or
157                is_callback_function(idl_type) or
158                is_enum(idl_type) or
159                idl_type == 'object' or
160                idl_type == 'Promise')  # Promise will be basic in future
161
162
163 def sequence_type(idl_type):
164     if is_union_type(idl_type):
165         # We do not support sequences of union types
166         return False
167     matched = re.match(r'sequence<([\w\s]+)>', idl_type)
168     return matched and matched.group(1)
169
170
171 def is_union_type(idl_type):
172     return isinstance(idl_type, idl_definitions.IdlUnionType)
173
174
175 ################################################################################
176 # V8-specific type handling
177 ################################################################################
178
179 NON_WRAPPER_TYPES = set([
180     'CompareHow',
181     'Dictionary',
182     'EventHandler',
183     'EventListener',
184     'MediaQueryListListener',
185     'NodeFilter',
186     'SerializedScriptValue',
187 ])
188 TYPED_ARRAYS = {
189     # (cpp_type, v8_type), used by constructor templates
190     'ArrayBuffer': None,
191     'ArrayBufferView': None,
192     'Float32Array': ('float', 'v8::kExternalFloatArray'),
193     'Float64Array': ('double', 'v8::kExternalDoubleArray'),
194     'Int8Array': ('signed char', 'v8::kExternalByteArray'),
195     'Int16Array': ('short', 'v8::kExternalShortArray'),
196     'Int32Array': ('int', 'v8::kExternalIntArray'),
197     'Uint8Array': ('unsigned char', 'v8::kExternalUnsignedByteArray'),
198     'Uint8ClampedArray': ('unsigned char', 'v8::kExternalPixelArray'),
199     'Uint16Array': ('unsigned short', 'v8::kExternalUnsignedShortArray'),
200     'Uint32Array': ('unsigned int', 'v8::kExternalUnsignedIntArray'),
201 }
202
203
204 def constructor_type(idl_type):
205     return strip_suffix(idl_type, 'Constructor')
206
207
208 def is_typed_array_type(idl_type):
209     return idl_type in TYPED_ARRAYS
210
211
212 def is_wrapper_type(idl_type):
213     return (is_interface_type(idl_type) and
214             idl_type not in NON_WRAPPER_TYPES)
215
216
217 ################################################################################
218 # C++ types
219 ################################################################################
220
221 CPP_TYPE_SAME_AS_IDL_TYPE = set([
222     'double',
223     'float',
224     'long long',
225     'unsigned long long',
226 ])
227 CPP_INT_TYPES = set([
228     'byte',
229     'long',
230     'short',
231 ])
232 CPP_UNSIGNED_TYPES = set([
233     'octet',
234     'unsigned int',
235     'unsigned long',
236     'unsigned short',
237 ])
238 CPP_SPECIAL_CONVERSION_RULES = {
239     'CompareHow': 'Range::CompareHow',
240     'Date': 'double',
241     'Dictionary': 'Dictionary',
242     'EventHandler': 'EventListener*',
243     'Promise': 'ScriptPromise',
244     'ScriptValue': 'ScriptValue',
245     'boolean': 'bool',
246 }
247
248 def cpp_type(idl_type, extended_attributes=None, used_as_argument=False):
249     """Returns C++ type corresponding to IDL type."""
250     def string_mode():
251         # FIXME: the Web IDL spec requires 'EmptyString', not 'NullString',
252         # but we use NullString for performance.
253         if extended_attributes.get('TreatNullAs') != 'NullString':
254             return ''
255         if extended_attributes.get('TreatUndefinedAs') != 'NullString':
256             return 'WithNullCheck'
257         return 'WithUndefinedOrNullCheck'
258
259     extended_attributes = extended_attributes or {}
260     idl_type = preprocess_idl_type(idl_type)
261
262     if idl_type in CPP_TYPE_SAME_AS_IDL_TYPE:
263         return idl_type
264     if idl_type in CPP_INT_TYPES:
265         return 'int'
266     if idl_type in CPP_UNSIGNED_TYPES:
267         return 'unsigned'
268     if idl_type in CPP_SPECIAL_CONVERSION_RULES:
269         return CPP_SPECIAL_CONVERSION_RULES[idl_type]
270     if (idl_type in NON_WRAPPER_TYPES or
271         idl_type == 'XPathNSResolver'):  # FIXME: eliminate this special case
272         return 'RefPtr<%s>' % idl_type
273     if idl_type == 'DOMString':
274         if not used_as_argument:
275             return 'String'
276         return 'V8StringResource<%s>' % string_mode()
277     if is_union_type(idl_type):
278         # Attribute 'union_member_types' use is ok, but pylint can't infer this
279         # pylint: disable=E1103
280         return (cpp_type(union_member_type)
281                 for union_member_type in idl_type.union_member_types)
282     this_array_or_sequence_type = array_or_sequence_type(idl_type)
283     if this_array_or_sequence_type:
284         return cpp_template_type('Vector', cpp_type(this_array_or_sequence_type))
285
286     if is_typed_array_type(idl_type) and used_as_argument:
287         return idl_type + '*'
288     if is_interface_type(idl_type):
289         implemented_as_class = implemented_as(idl_type)
290         if used_as_argument:
291             return implemented_as_class + '*'
292         if is_will_be_garbage_collected(idl_type):
293             return cpp_template_type('RefPtrWillBeRawPtr', implemented_as_class)
294         return cpp_template_type('RefPtr', implemented_as_class)
295     # Default, assume native type is a pointer with same type name as idl type
296     return idl_type + '*'
297
298
299 def cpp_template_type(template, inner_type):
300     """Returns C++ template specialized to type, with space added if needed."""
301     if inner_type.endswith('>'):
302         format_string = '{template}<{inner_type} >'
303     else:
304         format_string = '{template}<{inner_type}>'
305     return format_string.format(template=template, inner_type=inner_type)
306
307
308 def v8_type(interface_type):
309     return 'V8' + interface_type
310
311
312 # [ImplementedAs]
313 # This handles [ImplementedAs] on interface types, not [ImplementedAs] in the
314 # interface being generated. e.g., given:
315 #   Foo.idl: interface Foo {attribute Bar bar};
316 #   Bar.idl: [ImplementedAs=Zork] interface Bar {};
317 # when generating bindings for Foo, the [ImplementedAs] on Bar is needed.
318 # This data is external to Foo.idl, and hence computed as global information in
319 # compute_dependencies.py to avoid having to parse IDLs of all used interfaces.
320 implemented_as_interfaces = {}
321
322
323 def implemented_as(idl_type):
324     if idl_type in implemented_as_interfaces:
325         return implemented_as_interfaces[idl_type]
326     return idl_type
327
328
329 def set_implemented_as_interfaces(new_implemented_as_interfaces):
330     implemented_as_interfaces.update(new_implemented_as_interfaces)
331
332
333 # [WillBeGarbageCollected]
334 will_be_garbage_collected_types = set()
335
336
337 def is_will_be_garbage_collected(idl_type):
338     return idl_type in will_be_garbage_collected_types
339
340
341 def set_will_be_garbage_collected_types(new_will_be_garbage_collected_types):
342     will_be_garbage_collected_types.update(new_will_be_garbage_collected_types)
343
344
345 ################################################################################
346 # Includes
347 ################################################################################
348
349 def includes_for_cpp_class(class_name, relative_dir_posix):
350     return set([posixpath.join('bindings', relative_dir_posix, class_name + '.h')])
351
352
353 INCLUDES_FOR_TYPE = {
354     'object': set(),
355     'CompareHow': set(),
356     'Dictionary': set(['bindings/v8/Dictionary.h']),
357     'EventHandler': set(['bindings/v8/V8AbstractEventListener.h',
358                          'bindings/v8/V8EventListenerList.h']),
359     'EventListener': set(['bindings/v8/BindingSecurity.h',
360                           'bindings/v8/V8EventListenerList.h',
361                           'core/frame/DOMWindow.h']),
362     'MediaQueryListListener': set(['core/css/MediaQueryListListener.h']),
363     'Promise': set(['bindings/v8/ScriptPromise.h']),
364     'SerializedScriptValue': set(['bindings/v8/SerializedScriptValue.h']),
365     'ScriptValue': set(['bindings/v8/ScriptValue.h']),
366 }
367
368 def includes_for_type(idl_type):
369     idl_type = preprocess_idl_type(idl_type)
370     if idl_type in INCLUDES_FOR_TYPE:
371         return INCLUDES_FOR_TYPE[idl_type]
372     if is_basic_type(idl_type):
373         return set()
374     if is_typed_array_type(idl_type):
375         return set(['bindings/v8/custom/V8%sCustom.h' % idl_type])
376     this_array_or_sequence_type = array_or_sequence_type(idl_type)
377     if this_array_or_sequence_type:
378         return includes_for_type(this_array_or_sequence_type)
379     if is_union_type(idl_type):
380         # Attribute 'union_member_types' use is ok, but pylint can't infer this
381         # pylint: disable=E1103
382         return set.union(*[
383             includes_for_type(union_member_type)
384             for union_member_type in idl_type.union_member_types])
385     if idl_type.endswith('ConstructorConstructor'):
386         # FIXME: rename to NamedConstructor
387         # Ending with 'ConstructorConstructor' indicates a named constructor,
388         # and these do not have header files, as they are part of the generated
389         # bindings for the interface
390         return set()
391     if idl_type.endswith('Constructor'):
392         idl_type = constructor_type(idl_type)
393     return set(['V8%s.h' % idl_type])
394
395
396 def add_includes_for_type(idl_type):
397     includes.update(includes_for_type(idl_type))
398
399
400 ################################################################################
401 # V8 -> C++
402 ################################################################################
403
404 V8_VALUE_TO_CPP_VALUE = {
405     # Basic
406     'Date': 'toCoreDate({v8_value})',
407     'DOMString': '{v8_value}',
408     'boolean': '{v8_value}->BooleanValue()',
409     'float': 'static_cast<float>({v8_value}->NumberValue())',
410     'double': 'static_cast<double>({v8_value}->NumberValue())',
411     'byte': 'toInt8({arguments})',
412     'octet': 'toUInt8({arguments})',
413     'short': 'toInt16({arguments})',
414     'unsigned short': 'toUInt16({arguments})',
415     'long': 'toInt32({arguments})',
416     'unsigned long': 'toUInt32({arguments})',
417     'long long': 'toInt64({arguments})',
418     'unsigned long long': 'toUInt64({arguments})',
419     # Interface types
420     'CompareHow': 'static_cast<Range::CompareHow>({v8_value}->Int32Value())',
421     'Dictionary': 'Dictionary({v8_value}, info.GetIsolate())',
422     'EventTarget': 'V8DOMWrapper::isDOMWrapper({v8_value}) ? toWrapperTypeInfo(v8::Handle<v8::Object>::Cast({v8_value}))->toEventTarget(v8::Handle<v8::Object>::Cast({v8_value})) : 0',
423     'MediaQueryListListener': 'MediaQueryListListener::create(ScriptValue({v8_value}, info.GetIsolate()))',
424     'NodeFilter': 'toNodeFilter({v8_value}, info.GetIsolate())',
425     'Promise': 'ScriptPromise({v8_value}, info.GetIsolate())',
426     'SerializedScriptValue': 'SerializedScriptValue::create({v8_value}, info.GetIsolate())',
427     'ScriptValue': 'ScriptValue({v8_value}, info.GetIsolate())',
428     'Window': 'toDOMWindow({v8_value}, info.GetIsolate())',
429     'XPathNSResolver': 'toXPathNSResolver({v8_value}, info.GetIsolate())',
430 }
431
432
433 def v8_value_to_cpp_value(idl_type, extended_attributes, v8_value, index):
434     this_array_or_sequence_type = array_or_sequence_type(idl_type)
435     if this_array_or_sequence_type:
436         return v8_value_to_cpp_value_array_or_sequence(this_array_or_sequence_type, v8_value, index)
437
438     idl_type = preprocess_idl_type(idl_type)
439     add_includes_for_type(idl_type)
440
441     if 'EnforceRange' in extended_attributes:
442         arguments = ', '.join([v8_value, 'EnforceRange', 'exceptionState'])
443     elif is_integer_type(idl_type):  # NormalConversion
444         arguments = ', '.join([v8_value, 'exceptionState'])
445     else:
446         arguments = v8_value
447
448     if idl_type in V8_VALUE_TO_CPP_VALUE:
449         cpp_expression_format = V8_VALUE_TO_CPP_VALUE[idl_type]
450     elif is_typed_array_type(idl_type):
451         cpp_expression_format = (
452             '{v8_value}->Is{idl_type}() ? '
453             'V8{idl_type}::toNative(v8::Handle<v8::{idl_type}>::Cast({v8_value})) : 0')
454     else:
455         cpp_expression_format = (
456             'V8{idl_type}::hasInstance({v8_value}, info.GetIsolate()) ? '
457             'V8{idl_type}::toNative(v8::Handle<v8::Object>::Cast({v8_value})) : 0')
458
459     return cpp_expression_format.format(arguments=arguments, idl_type=idl_type, v8_value=v8_value)
460
461
462 def v8_value_to_cpp_value_array_or_sequence(this_array_or_sequence_type, v8_value, index):
463     # Index is None for setters, index (starting at 0) for method arguments,
464     # and is used to provide a human-readable exception message
465     if index is None:
466         index = 0  # special case, meaning "setter"
467     else:
468         index += 1  # human-readable index
469     if (is_interface_type(this_array_or_sequence_type) and
470         this_array_or_sequence_type != 'Dictionary'):
471         this_cpp_type = None
472         expression_format = '(toRefPtrNativeArray<{array_or_sequence_type}, V8{array_or_sequence_type}>({v8_value}, {index}, info.GetIsolate()))'
473         add_includes_for_type(this_array_or_sequence_type)
474     else:
475         this_cpp_type = cpp_type(this_array_or_sequence_type)
476         expression_format = 'toNativeArray<{cpp_type}>({v8_value}, {index}, info.GetIsolate())'
477     expression = expression_format.format(array_or_sequence_type=this_array_or_sequence_type, cpp_type=this_cpp_type, index=index, v8_value=v8_value)
478     return expression
479
480
481 def v8_value_to_local_cpp_value(idl_type, extended_attributes, v8_value, variable_name, index=None):
482     """Returns an expression that converts a V8 value to a C++ value and stores it as a local value."""
483     this_cpp_type = cpp_type(idl_type, extended_attributes=extended_attributes, used_as_argument=True)
484
485     idl_type = preprocess_idl_type(idl_type)
486     if idl_type == 'DOMString':
487         format_string = 'V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID({cpp_type}, {variable_name}, {cpp_value})'
488     elif is_integer_type(idl_type):
489         format_string = 'V8TRYCATCH_EXCEPTION_VOID({cpp_type}, {variable_name}, {cpp_value}, exceptionState)'
490     else:
491         format_string = 'V8TRYCATCH_VOID({cpp_type}, {variable_name}, {cpp_value})'
492
493     cpp_value = v8_value_to_cpp_value(idl_type, extended_attributes, v8_value, index)
494     return format_string.format(cpp_type=this_cpp_type, cpp_value=cpp_value, variable_name=variable_name)
495
496
497 ################################################################################
498 # C++ -> V8
499 ################################################################################
500
501 def preprocess_idl_type(idl_type):
502     if is_enum(idl_type):
503         # Enumerations are internally DOMStrings
504         return 'DOMString'
505     if (idl_type == 'any' or is_callback_function(idl_type)):
506         return 'ScriptValue'
507     return idl_type
508
509
510 def preprocess_idl_type_and_value(idl_type, cpp_value, extended_attributes):
511     """Returns IDL type and value, with preliminary type conversions applied."""
512     idl_type = preprocess_idl_type(idl_type)
513     if idl_type == 'Promise':
514         idl_type = 'ScriptValue'
515     if idl_type in ['long long', 'unsigned long long']:
516         # long long and unsigned long long are not representable in ECMAScript;
517         # we represent them as doubles.
518         idl_type = 'double'
519         cpp_value = 'static_cast<double>(%s)' % cpp_value
520     # HTML5 says that unsigned reflected attributes should be in the range
521     # [0, 2^31). When a value isn't in this range, a default value (or 0)
522     # should be returned instead.
523     extended_attributes = extended_attributes or {}
524     if ('Reflect' in extended_attributes and
525         idl_type in ['unsigned long', 'unsigned short']):
526         cpp_value = cpp_value.replace('getUnsignedIntegralAttribute',
527                                       'getIntegralAttribute')
528         cpp_value = 'std::max(0, %s)' % cpp_value
529     return idl_type, cpp_value
530
531
532 def v8_conversion_type(idl_type, extended_attributes):
533     """Returns V8 conversion type, adding any additional includes.
534
535     The V8 conversion type is used to select the C++ -> V8 conversion function
536     or v8SetReturnValue* function; it can be an idl_type, a cpp_type, or a
537     separate name for the type of conversion (e.g., 'DOMWrapper').
538     """
539     extended_attributes = extended_attributes or {}
540     # Basic types, without additional includes
541     if idl_type in CPP_INT_TYPES:
542         return 'int'
543     if idl_type in CPP_UNSIGNED_TYPES:
544         return 'unsigned'
545     if idl_type == 'DOMString':
546         if 'TreatReturnedNullStringAs' not in extended_attributes:
547             return 'DOMString'
548         treat_returned_null_string_as = extended_attributes['TreatReturnedNullStringAs']
549         if treat_returned_null_string_as == 'Null':
550             return 'StringOrNull'
551         if treat_returned_null_string_as == 'Undefined':
552             return 'StringOrUndefined'
553         raise 'Unrecognized TreatReturnNullStringAs value: "%s"' % treat_returned_null_string_as
554     if is_basic_type(idl_type) or idl_type == 'ScriptValue':
555         return idl_type
556
557     # Data type with potential additional includes
558     this_array_or_sequence_type = array_or_sequence_type(idl_type)
559     if this_array_or_sequence_type:
560         if is_interface_type(this_array_or_sequence_type):
561             add_includes_for_type(this_array_or_sequence_type)
562         return 'array'
563
564     add_includes_for_type(idl_type)
565     if idl_type in V8_SET_RETURN_VALUE:  # Special v8SetReturnValue treatment
566         return idl_type
567
568     # Pointer type
569     return 'DOMWrapper'
570
571
572 V8_SET_RETURN_VALUE = {
573     'boolean': 'v8SetReturnValueBool(info, {cpp_value})',
574     'int': 'v8SetReturnValueInt(info, {cpp_value})',
575     'unsigned': 'v8SetReturnValueUnsigned(info, {cpp_value})',
576     'DOMString': 'v8SetReturnValueString(info, {cpp_value}, info.GetIsolate())',
577     # [TreatNullReturnValueAs]
578     'StringOrNull': 'v8SetReturnValueStringOrNull(info, {cpp_value}, info.GetIsolate())',
579     'StringOrUndefined': 'v8SetReturnValueStringOrUndefined(info, {cpp_value}, info.GetIsolate())',
580     'void': '',
581     # No special v8SetReturnValue* function (set value directly)
582     'float': 'v8SetReturnValue(info, {cpp_value})',
583     'double': 'v8SetReturnValue(info, {cpp_value})',
584     # No special v8SetReturnValue* function, but instead convert value to V8
585     # and then use general v8SetReturnValue.
586     'array': 'v8SetReturnValue(info, {cpp_value})',
587     'Date': 'v8SetReturnValue(info, {cpp_value})',
588     'EventHandler': 'v8SetReturnValue(info, {cpp_value})',
589     'ScriptValue': 'v8SetReturnValue(info, {cpp_value})',
590     'SerializedScriptValue': 'v8SetReturnValue(info, {cpp_value})',
591     # DOMWrapper
592     'DOMWrapperForMainWorld': 'v8SetReturnValueForMainWorld(info, {cpp_value})',
593     'DOMWrapperFast': 'v8SetReturnValueFast(info, {cpp_value}, {script_wrappable})',
594     'DOMWrapperDefault': 'v8SetReturnValue(info, {cpp_value})',
595 }
596
597
598 def v8_set_return_value(idl_type, cpp_value, extended_attributes=None, script_wrappable='', release=False, for_main_world=False):
599     """Returns a statement that converts a C++ value to a V8 value and sets it as a return value.
600
601     release: for union types, can be either False (False for all member types)
602              or a sequence (list or tuple) of booleans (if specified
603              individually).
604     """
605     def dom_wrapper_conversion_type():
606         if not script_wrappable:
607             return 'DOMWrapperDefault'
608         if for_main_world:
609             return 'DOMWrapperForMainWorld'
610         return 'DOMWrapperFast'
611
612     if is_union_type(idl_type):
613         return [
614             v8_set_return_value(union_member_type,
615                                 cpp_value + str(i),
616                                 extended_attributes,
617                                 script_wrappable,
618                                 release and release[i])
619                 for i, union_member_type in
620                 enumerate(idl_type.union_member_types)]
621     idl_type, cpp_value = preprocess_idl_type_and_value(idl_type, cpp_value, extended_attributes)
622     this_v8_conversion_type = v8_conversion_type(idl_type, extended_attributes)
623     # SetReturn-specific overrides
624     if this_v8_conversion_type in ['Date', 'EventHandler', 'ScriptValue', 'SerializedScriptValue', 'array']:
625         # Convert value to V8 and then use general v8SetReturnValue
626         cpp_value = cpp_value_to_v8_value(idl_type, cpp_value, extended_attributes=extended_attributes)
627     if this_v8_conversion_type == 'DOMWrapper':
628         this_v8_conversion_type = dom_wrapper_conversion_type()
629
630     format_string = V8_SET_RETURN_VALUE[this_v8_conversion_type]
631     if release:
632         cpp_value = '%s.release()' % cpp_value
633     statement = format_string.format(cpp_value=cpp_value, script_wrappable=script_wrappable)
634     return statement
635
636
637 CPP_VALUE_TO_V8_VALUE = {
638     # Built-in types
639     'Date': 'v8DateOrNull({cpp_value}, {isolate})',
640     'DOMString': 'v8String({isolate}, {cpp_value})',
641     'boolean': 'v8Boolean({cpp_value}, {isolate})',
642     'int': 'v8::Integer::New({isolate}, {cpp_value})',
643     'unsigned': 'v8::Integer::NewFromUnsigned({isolate}, {cpp_value})',
644     'float': 'v8::Number::New({isolate}, {cpp_value})',
645     'double': 'v8::Number::New({isolate}, {cpp_value})',
646     'void': 'v8Undefined()',
647     # Special cases
648     'EventHandler': '{cpp_value} ? v8::Handle<v8::Value>(V8AbstractEventListener::cast({cpp_value})->getListenerObject(imp->executionContext())) : v8::Handle<v8::Value>(v8::Null({isolate}))',
649     'ScriptValue': '{cpp_value}.v8Value()',
650     'SerializedScriptValue': '{cpp_value} ? {cpp_value}->deserialize() : v8::Handle<v8::Value>(v8::Null({isolate}))',
651     # General
652     'array': 'v8Array({cpp_value}, {isolate})',
653     'DOMWrapper': 'toV8({cpp_value}, {creation_context}, {isolate})',
654 }
655
656
657 def cpp_value_to_v8_value(idl_type, cpp_value, isolate='info.GetIsolate()', creation_context='', extended_attributes=None):
658     """Returns an expression that converts a C++ value to a V8 value."""
659     # the isolate parameter is needed for callback interfaces
660     idl_type, cpp_value = preprocess_idl_type_and_value(idl_type, cpp_value, extended_attributes)
661     this_v8_conversion_type = v8_conversion_type(idl_type, extended_attributes)
662     format_string = CPP_VALUE_TO_V8_VALUE[this_v8_conversion_type]
663     statement = format_string.format(cpp_value=cpp_value, isolate=isolate, creation_context=creation_context)
664     return statement