Home | History | Annotate | Download | only in unstable
      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     # integer types
     61     # http://www.w3.org/TR/WebIDL/#dfn-integer-type
     62     'byte',
     63     'octet',
     64     'short',
     65     'unsigned short',
     66     # int and unsigned are not IDL types
     67     'long',
     68     'unsigned long',
     69     'long long',
     70     'unsigned long long',
     71     # http://www.w3.org/TR/WebIDL/#idl-types
     72     'DOMString',
     73     'Date',
     74     # http://www.w3.org/TR/WebIDL/#es-type-mapping
     75     'void',
     76 ])
     77 
     78 enum_types = {}  # name -> values
     79 callback_function_types = set()
     80 
     81 
     82 def array_or_sequence_type(idl_type):
     83     return array_type(idl_type) or sequence_type(idl_type)
     84 
     85 
     86 def array_type(idl_type):
     87     matched = re.match(r'([\w\s]+)\[\]', idl_type)
     88     return matched and matched.group(1)
     89 
     90 
     91 def is_basic_type(idl_type):
     92     return idl_type in BASIC_TYPES
     93 
     94 
     95 def is_callback_function_type(idl_type):
     96     return idl_type in callback_function_types
     97 
     98 
     99 def set_callback_function_types(callback_functions):
    100     callback_function_types.update(callback_functions.keys())
    101 
    102 
    103 def is_composite_type(idl_type):
    104     return (idl_type == 'any' or
    105             array_type(idl_type) or
    106             sequence_type(idl_type) or
    107             is_union_type(idl_type))
    108 
    109 
    110 def is_enum_type(idl_type):
    111     return idl_type in enum_types
    112 
    113 
    114 def enum_values(idl_type):
    115     return enum_types.get(idl_type)
    116 
    117 
    118 def set_enum_types(enumerations):
    119     enum_types.update([[enum.name, enum.values]
    120                        for enum in enumerations.values()])
    121 
    122 
    123 def is_interface_type(idl_type):
    124     # Anything that is not another type is an interface type.
    125     # http://www.w3.org/TR/WebIDL/#idl-types
    126     # http://www.w3.org/TR/WebIDL/#idl-interface
    127     # In C++ these are RefPtr or PassRefPtr types.
    128     return not(is_basic_type(idl_type) or
    129                is_composite_type(idl_type) or
    130                is_callback_function_type(idl_type) or
    131                is_enum_type(idl_type) or
    132                idl_type == 'object' or
    133                idl_type == 'Promise')  # Promise will be basic in future
    134 
    135 
    136 def sequence_type(idl_type):
    137     matched = re.match(r'sequence<([\w\s]+)>', idl_type)
    138     return matched and matched.group(1)
    139 
    140 
    141 def is_union_type(idl_type):
    142     return isinstance(idl_type, idl_definitions.IdlUnionType)
    143 
    144 
    145 ################################################################################
    146 # V8-specific type handling
    147 ################################################################################
    148 
    149 DOM_NODE_TYPES = set([
    150     'Attr',
    151     'CDATASection',
    152     'CharacterData',
    153     'Comment',
    154     'Document',
    155     'DocumentFragment',
    156     'DocumentType',
    157     'Element',
    158     'Entity',
    159     'HTMLDocument',
    160     'Node',
    161     'Notation',
    162     'ProcessingInstruction',
    163     'ShadowRoot',
    164     'SVGDocument',
    165     'Text',
    166     'TestNode',
    167 ])
    168 NON_WRAPPER_TYPES = set([
    169     'CompareHow',
    170     'Dictionary',
    171     'MediaQueryListListener',
    172     'NodeFilter',
    173     'SerializedScriptValue',
    174 ])
    175 TYPED_ARRAYS = {
    176     # (cpp_type, v8_type), used by constructor templates
    177     'ArrayBuffer': None,
    178     'ArrayBufferView': None,
    179     'Float32Array': ('float', 'v8::kExternalFloatArray'),
    180     'Float64Array': ('double', 'v8::kExternalDoubleArray'),
    181     'Int8Array': ('signed char', 'v8::kExternalByteArray'),
    182     'Int16Array': ('short', 'v8::kExternalShortArray'),
    183     'Int32Array': ('int', 'v8::kExternalIntArray'),
    184     'Uint8Array': ('unsigned char', 'v8::kExternalUnsignedByteArray'),
    185     'Uint8ClampedArray': ('unsigned char', 'v8::kExternalPixelArray'),
    186     'Uint16Array': ('unsigned short', 'v8::kExternalUnsignedShortArray'),
    187     'Uint32Array': ('unsigned int', 'v8::kExternalUnsignedIntArray'),
    188 }
    189 
    190 
    191 def constructor_type(idl_type):
    192     return strip_suffix(idl_type, 'Constructor')
    193 
    194 
    195 def is_dom_node_type(idl_type):
    196     return (idl_type in DOM_NODE_TYPES or
    197             (idl_type.startswith(('HTML', 'SVG')) and
    198              idl_type.endswith('Element')))
    199 
    200 
    201 def is_typed_array_type(idl_type):
    202     return idl_type in TYPED_ARRAYS
    203 
    204 
    205 def is_wrapper_type(idl_type):
    206     return (is_interface_type(idl_type) and
    207             idl_type not in NON_WRAPPER_TYPES)
    208 
    209 
    210 ################################################################################
    211 # C++ types
    212 ################################################################################
    213 
    214 CPP_TYPE_SAME_AS_IDL_TYPE = set([
    215     'double',
    216     'float',
    217     'long long',
    218     'unsigned long long',
    219 ])
    220 CPP_INT_TYPES = set([
    221     'byte',
    222     'long',
    223     'short',
    224 ])
    225 CPP_UNSIGNED_TYPES = set([
    226     'octet',
    227     'unsigned int',
    228     'unsigned long',
    229     'unsigned short',
    230 ])
    231 CPP_SPECIAL_CONVERSION_RULES = {
    232     'CompareHow': 'Range::CompareHow',
    233     'Date': 'double',
    234     'Dictionary': 'Dictionary',
    235     'EventHandler': 'EventListener*',
    236     'Promise': 'ScriptPromise',
    237     'any': 'ScriptValue',
    238     'boolean': 'bool',
    239 }
    240 
    241 def cpp_type(idl_type, extended_attributes=None, used_as_argument=False):
    242     """Returns C++ type corresponding to IDL type."""
    243     def string_mode():
    244         # FIXME: the Web IDL spec requires 'EmptyString', not 'NullString',
    245         # but we use NullString for performance.
    246         if extended_attributes.get('TreatNullAs') != 'NullString':
    247             return ''
    248         if extended_attributes.get('TreatUndefinedAs') != 'NullString':
    249             return 'WithNullCheck'
    250         return 'WithUndefinedOrNullCheck'
    251 
    252     extended_attributes = extended_attributes or {}
    253     idl_type = preprocess_idl_type(idl_type)
    254 
    255     if idl_type in CPP_TYPE_SAME_AS_IDL_TYPE:
    256         return idl_type
    257     if idl_type in CPP_INT_TYPES:
    258         return 'int'
    259     if idl_type in CPP_UNSIGNED_TYPES:
    260         return 'unsigned'
    261     if idl_type in CPP_SPECIAL_CONVERSION_RULES:
    262         return CPP_SPECIAL_CONVERSION_RULES[idl_type]
    263     if (idl_type in NON_WRAPPER_TYPES or
    264         idl_type == 'XPathNSResolver'):  # FIXME: eliminate this special case
    265         return 'RefPtr<%s>' % idl_type
    266     if idl_type == 'DOMString':
    267         if not used_as_argument:
    268             return 'String'
    269         return 'V8StringResource<%s>' % string_mode()
    270     if is_union_type(idl_type):
    271         raise Exception('UnionType is not supported')
    272     this_array_or_sequence_type = array_or_sequence_type(idl_type)
    273     if this_array_or_sequence_type:
    274         return cpp_template_type('Vector', cpp_type(this_array_or_sequence_type))
    275 
    276     if is_typed_array_type and used_as_argument:
    277         return idl_type + '*'
    278     if is_interface_type(idl_type) and not used_as_argument:
    279         return cpp_template_type('RefPtr', idl_type)
    280     # Default, assume native type is a pointer with same type name as idl type
    281     return idl_type + '*'
    282 
    283 
    284 def cpp_template_type(template, inner_type):
    285     """Returns C++ template specialized to type, with space added if needed."""
    286     if inner_type.endswith('>'):
    287         format_string = '{template}<{inner_type} >'
    288     else:
    289         format_string = '{template}<{inner_type}>'
    290     return format_string.format(template=template, inner_type=inner_type)
    291 
    292 
    293 def v8_type(interface_type):
    294     return 'V8' + interface_type
    295 
    296 
    297 ################################################################################
    298 # Includes
    299 ################################################################################
    300 
    301 
    302 def includes_for_cpp_class(class_name, relative_dir_posix):
    303     return set([posixpath.join('bindings', relative_dir_posix, class_name + '.h')])
    304 
    305 
    306 INCLUDES_FOR_TYPE = {
    307     'any': set(['bindings/v8/ScriptValue.h']),
    308     'object': set(),
    309     'Dictionary': set(['bindings/v8/Dictionary.h']),
    310     'EventHandler': set(['bindings/v8/V8AbstractEventListener.h',
    311                          'bindings/v8/V8EventListenerList.h']),
    312     'EventListener': set(['bindings/v8/BindingSecurity.h',
    313                           'bindings/v8/V8EventListenerList.h',
    314                           'core/frame/DOMWindow.h']),
    315     'MediaQueryListListener': set(['core/css/MediaQueryListListener.h']),
    316     'Promise': set(['bindings/v8/ScriptPromise.h']),
    317     'SerializedScriptValue': set(['bindings/v8/SerializedScriptValue.h']),
    318 }
    319 
    320 def includes_for_type(idl_type):
    321     if idl_type in INCLUDES_FOR_TYPE:
    322         return INCLUDES_FOR_TYPE[idl_type]
    323     if is_basic_type(idl_type) or is_enum_type(idl_type):
    324         return set()
    325     if is_typed_array_type(idl_type):
    326         return set(['bindings/v8/custom/V8%sCustom.h' % idl_type])
    327     this_array_or_sequence_type = array_or_sequence_type(idl_type)
    328     if this_array_or_sequence_type:
    329         return includes_for_type(this_array_or_sequence_type)
    330     if idl_type.endswith('Constructor'):
    331         idl_type = constructor_type(idl_type)
    332     return set(['V8%s.h' % idl_type])
    333 
    334 
    335 def add_includes_for_type(idl_type):
    336     includes.update(includes_for_type(idl_type))
    337 
    338 
    339 ################################################################################
    340 # V8 -> C++
    341 ################################################################################
    342 
    343 V8_VALUE_TO_CPP_VALUE = {
    344     # Basic
    345     'Date': 'toWebCoreDate({v8_value})',
    346     'DOMString': '{v8_value}',
    347     'boolean': '{v8_value}->BooleanValue()',
    348     'float': 'static_cast<float>({v8_value}->NumberValue())',
    349     'double': 'static_cast<double>({v8_value}->NumberValue())',
    350     'byte': 'toInt8({arguments})',
    351     'octet': 'toUInt8({arguments})',
    352     'short': 'toInt16({arguments})',
    353     'unsigned short': 'toUInt16({arguments})',
    354     'long': 'toInt32({arguments})',
    355     'unsigned long': 'toUInt32({arguments})',
    356     'long long': 'toInt64({arguments})',
    357     'unsigned long long': 'toUInt64({arguments})',
    358     # Interface types
    359     'any': 'ScriptValue({v8_value}, info.GetIsolate())',
    360     'CompareHow': 'static_cast<Range::CompareHow>({v8_value}->Int32Value())',
    361     'Dictionary': 'Dictionary({v8_value}, info.GetIsolate())',
    362     'MediaQueryListListener': 'MediaQueryListListener::create(ScriptValue({v8_value}, info.GetIsolate()))',
    363     'NodeFilter': 'toNodeFilter({v8_value}, info.GetIsolate())',
    364     'Promise': 'ScriptPromise({v8_value})',
    365     'SerializedScriptValue': 'SerializedScriptValue::create({v8_value}, info.GetIsolate())',
    366     'XPathNSResolver': 'toXPathNSResolver({v8_value}, info.GetIsolate())',
    367 }
    368 
    369 
    370 def v8_value_to_cpp_value(idl_type, extended_attributes, v8_value, index):
    371     this_array_or_sequence_type = array_or_sequence_type(idl_type)
    372     if this_array_or_sequence_type:
    373         return v8_value_to_cpp_value_array_or_sequence(this_array_or_sequence_type, v8_value, index)
    374 
    375     idl_type = preprocess_idl_type(idl_type)
    376     add_includes_for_type(idl_type)
    377 
    378     if 'EnforceRange' in extended_attributes:
    379         arguments = ', '.join([v8_value, 'EnforceRange', 'ok'])
    380     else:  # NormalConversion
    381         arguments = v8_value
    382 
    383     if idl_type in V8_VALUE_TO_CPP_VALUE:
    384         cpp_expression_format = V8_VALUE_TO_CPP_VALUE[idl_type]
    385     elif is_typed_array_type(idl_type):
    386         cpp_expression_format = (
    387             '{v8_value}->Is{idl_type}() ? '
    388             'V8{idl_type}::toNative(v8::Handle<v8::{idl_type}>::Cast({v8_value})) : 0')
    389     else:
    390         cpp_expression_format = (
    391             'V8{idl_type}::hasInstance({v8_value}, info.GetIsolate(), worldType(info.GetIsolate())) ? '
    392             'V8{idl_type}::toNative(v8::Handle<v8::Object>::Cast({v8_value})) : 0')
    393 
    394     return cpp_expression_format.format(arguments=arguments, idl_type=idl_type, v8_value=v8_value)
    395 
    396 
    397 def v8_value_to_cpp_value_array_or_sequence(this_array_or_sequence_type, v8_value, index):
    398     # Index is None for setters, index (starting at 0) for method arguments,
    399     # and is used to provide a human-readable exception message
    400     if index is None:
    401         index = 0  # special case, meaning "setter"
    402     else:
    403         index += 1  # human-readable index
    404     if (is_interface_type(this_array_or_sequence_type) and
    405         this_array_or_sequence_type != 'Dictionary'):
    406         this_cpp_type = None
    407         expression_format = '(toRefPtrNativeArray<{array_or_sequence_type}, V8{array_or_sequence_type}>({v8_value}, {index}, info.GetIsolate()))'
    408         add_includes_for_type(this_array_or_sequence_type)
    409     else:
    410         this_cpp_type = cpp_type(this_array_or_sequence_type)
    411         expression_format = 'toNativeArray<{cpp_type}>({v8_value}, {index}, info.GetIsolate())'
    412     expression = expression_format.format(array_or_sequence_type=this_array_or_sequence_type, cpp_type=this_cpp_type, index=index, v8_value=v8_value)
    413     return expression
    414 
    415 
    416 def v8_value_to_local_cpp_value(idl_type, extended_attributes, v8_value, variable_name, index=None):
    417     """Returns an expression that converts a V8 value to a C++ value and stores it as a local value."""
    418     this_cpp_type = cpp_type(idl_type, extended_attributes=extended_attributes, used_as_argument=True)
    419 
    420     idl_type = preprocess_idl_type(idl_type)
    421     if idl_type == 'DOMString':
    422         format_string = 'V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID({cpp_type}, {variable_name}, {cpp_value})'
    423     elif 'EnforceRange' in extended_attributes:
    424         format_string = 'V8TRYCATCH_WITH_TYPECHECK_VOID({cpp_type}, {variable_name}, {cpp_value}, info.GetIsolate())'
    425     else:
    426         format_string = 'V8TRYCATCH_VOID({cpp_type}, {variable_name}, {cpp_value})'
    427 
    428     cpp_value = v8_value_to_cpp_value(idl_type, extended_attributes, v8_value, index)
    429     return format_string.format(cpp_type=this_cpp_type, cpp_value=cpp_value, variable_name=variable_name)
    430 
    431 
    432 ################################################################################
    433 # C++ -> V8
    434 ################################################################################
    435 
    436 
    437 def preprocess_idl_type(idl_type):
    438     if is_enum_type(idl_type):
    439         # Enumerations are internally DOMStrings
    440         return 'DOMString'
    441     if is_callback_function_type(idl_type):
    442         return 'ScriptValue'
    443     return idl_type
    444 
    445 
    446 def preprocess_idl_type_and_value(idl_type, cpp_value, extended_attributes):
    447     """Returns IDL type and value, with preliminary type conversions applied."""
    448     idl_type = preprocess_idl_type(idl_type)
    449     if idl_type in ['Promise', 'any']:
    450         idl_type = 'ScriptValue'
    451     if idl_type in ['long long', 'unsigned long long']:
    452         # long long and unsigned long long are not representable in ECMAScript;
    453         # we represent them as doubles.
    454         idl_type = 'double'
    455         cpp_value = 'static_cast<double>(%s)' % cpp_value
    456     # HTML5 says that unsigned reflected attributes should be in the range
    457     # [0, 2^31). When a value isn't in this range, a default value (or 0)
    458     # should be returned instead.
    459     extended_attributes = extended_attributes or {}
    460     if ('Reflect' in extended_attributes and
    461         idl_type in ['unsigned long', 'unsigned short']):
    462         cpp_value = cpp_value.replace('getUnsignedIntegralAttribute',
    463                                       'getIntegralAttribute')
    464         cpp_value = 'std::max(0, %s)' % cpp_value
    465     return idl_type, cpp_value
    466 
    467 
    468 def v8_conversion_type(idl_type, extended_attributes):
    469     """Returns V8 conversion type, adding any additional includes.
    470 
    471     The V8 conversion type is used to select the C++ -> V8 conversion function
    472     or v8SetReturnValue* function; it can be an idl_type, a cpp_type, or a
    473     separate name for the type of conversion (e.g., 'DOMWrapper').
    474     """
    475     extended_attributes = extended_attributes or {}
    476     # Basic types, without additional includes
    477     if idl_type in CPP_INT_TYPES:
    478         return 'int'
    479     if idl_type in CPP_UNSIGNED_TYPES:
    480         return 'unsigned'
    481     if idl_type == 'DOMString':
    482         if 'TreatReturnedNullStringAs' not in extended_attributes:
    483             return 'DOMString'
    484         treat_returned_null_string_as = extended_attributes['TreatReturnedNullStringAs']
    485         if treat_returned_null_string_as == 'Null':
    486             return 'StringOrNull'
    487         if treat_returned_null_string_as == 'Undefined':
    488             return 'StringOrUndefined'
    489         raise 'Unrecognized TreatReturnNullStringAs value: "%s"' % treat_returned_null_string_as
    490     if is_basic_type(idl_type) or idl_type == 'ScriptValue':
    491         return idl_type
    492 
    493     # Data type with potential additional includes
    494     this_array_or_sequence_type = array_or_sequence_type(idl_type)
    495     if this_array_or_sequence_type:
    496         if is_interface_type(this_array_or_sequence_type):
    497             add_includes_for_type(this_array_or_sequence_type)
    498         return 'array'
    499 
    500     add_includes_for_type(idl_type)
    501     if idl_type in V8_SET_RETURN_VALUE:  # Special v8SetReturnValue treatment
    502         return idl_type
    503 
    504     # Pointer type
    505     includes.add('wtf/GetPtr.h')  # FIXME: remove if can eliminate WTF::getPtr
    506     includes.add('wtf/RefPtr.h')
    507     return 'DOMWrapper'
    508 
    509 
    510 V8_SET_RETURN_VALUE = {
    511     'boolean': 'v8SetReturnValueBool(info, {cpp_value})',
    512     'int': 'v8SetReturnValueInt(info, {cpp_value})',
    513     'unsigned': 'v8SetReturnValueUnsigned(info, {cpp_value})',
    514     'DOMString': 'v8SetReturnValueString(info, {cpp_value}, info.GetIsolate())',
    515     # [TreatNullReturnValueAs]
    516     'StringOrNull': 'v8SetReturnValueStringOrNull(info, {cpp_value}, info.GetIsolate())',
    517     'StringOrUndefined': 'v8SetReturnValueStringOrUndefined(info, {cpp_value}, info.GetIsolate())',
    518     'void': '',
    519     # No special v8SetReturnValue* function (set value directly)
    520     'float': 'v8SetReturnValue(info, {cpp_value})',
    521     'double': 'v8SetReturnValue(info, {cpp_value})',
    522     # No special v8SetReturnValue* function, but instead convert value to V8
    523     # and then use general v8SetReturnValue.
    524     'array': 'v8SetReturnValue(info, {cpp_value})',
    525     'Date': 'v8SetReturnValue(info, {cpp_value})',
    526     'EventHandler': 'v8SetReturnValue(info, {cpp_value})',
    527     'ScriptValue': 'v8SetReturnValue(info, {cpp_value})',
    528     'SerializedScriptValue': 'v8SetReturnValue(info, {cpp_value})',
    529     # DOMWrapper
    530     'DOMWrapperFast': 'v8SetReturnValueFast(info, {cpp_value}, {script_wrappable})',
    531     'DOMWrapperDefault': 'v8SetReturnValue(info, {cpp_value})',
    532 }
    533 
    534 
    535 def v8_set_return_value(idl_type, cpp_value, extended_attributes=None, script_wrappable=''):
    536     """Returns a statement that converts a C++ value to a V8 value and sets it as a return value."""
    537     def dom_wrapper_conversion_type():
    538         if not script_wrappable:
    539             return 'DOMWrapperDefault'
    540         return 'DOMWrapperFast'
    541 
    542     idl_type, cpp_value = preprocess_idl_type_and_value(idl_type, cpp_value, extended_attributes)
    543     this_v8_conversion_type = v8_conversion_type(idl_type, extended_attributes)
    544     # SetReturn-specific overrides
    545     if this_v8_conversion_type in ['Date', 'EventHandler', 'ScriptValue', 'SerializedScriptValue', 'array']:
    546         # Convert value to V8 and then use general v8SetReturnValue
    547         cpp_value = cpp_value_to_v8_value(idl_type, cpp_value, extended_attributes=extended_attributes)
    548     if this_v8_conversion_type == 'DOMWrapper':
    549         this_v8_conversion_type = dom_wrapper_conversion_type()
    550 
    551     format_string = V8_SET_RETURN_VALUE[this_v8_conversion_type]
    552     statement = format_string.format(cpp_value=cpp_value, script_wrappable=script_wrappable)
    553     return statement
    554 
    555 
    556 CPP_VALUE_TO_V8_VALUE = {
    557     # Built-in types
    558     'Date': 'v8DateOrNull({cpp_value}, {isolate})',
    559     'DOMString': 'v8String({isolate}, {cpp_value})',
    560     'boolean': 'v8Boolean({cpp_value}, {isolate})',
    561     'int': 'v8::Integer::New({isolate}, {cpp_value})',
    562     'unsigned': 'v8::Integer::NewFromUnsigned({isolate}, {cpp_value})',
    563     'float': 'v8::Number::New({isolate}, {cpp_value})',
    564     'double': 'v8::Number::New({isolate}, {cpp_value})',
    565     'void': 'v8Undefined()',
    566     # Special cases
    567     'EventHandler': '{cpp_value} ? v8::Handle<v8::Value>(V8AbstractEventListener::cast({cpp_value})->getListenerObject(imp->executionContext())) : v8::Handle<v8::Value>(v8::Null({isolate}))',
    568     'ScriptValue': '{cpp_value}.v8Value()',
    569     'SerializedScriptValue': '{cpp_value} ? {cpp_value}->deserialize() : v8::Handle<v8::Value>(v8::Null({isolate}))',
    570     # General
    571     'array': 'v8Array({cpp_value}, {isolate})',
    572     'DOMWrapper': 'toV8({cpp_value}, {creation_context}, {isolate})',
    573 }
    574 
    575 
    576 def cpp_value_to_v8_value(idl_type, cpp_value, isolate='info.GetIsolate()', creation_context='', extended_attributes=None):
    577     """Returns an expression that converts a C++ value to a V8 value."""
    578     # the isolate parameter is needed for callback interfaces
    579     idl_type, cpp_value = preprocess_idl_type_and_value(idl_type, cpp_value, extended_attributes)
    580     this_v8_conversion_type = v8_conversion_type(idl_type, extended_attributes)
    581     format_string = CPP_VALUE_TO_V8_VALUE[this_v8_conversion_type]
    582     statement = format_string.format(cpp_value=cpp_value, isolate=isolate, creation_context=creation_context)
    583     return statement
    584