• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
31Spec:
32http://www.w3.org/TR/WebIDL/#es-type-mapping
33
34FIXME: Not currently used in build.
35This is a rewrite of the Perl IDL compiler in Python, but is not complete.
36Once it is complete, we will switch all IDL files over to Python at once.
37Until then, please work on the Perl IDL compiler.
38For details, see bug http://crbug.com/239771
39"""
40
41import posixpath
42import re
43
44from v8_globals import includes
45import idl_definitions  # for UnionType
46from v8_utilities import strip_suffix
47
48################################################################################
49# IDL types
50################################################################################
51
52BASIC_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
78enum_types = {}  # name -> values
79callback_function_types = set()
80
81
82def array_or_sequence_type(idl_type):
83    return array_type(idl_type) or sequence_type(idl_type)
84
85
86def array_type(idl_type):
87    matched = re.match(r'([\w\s]+)\[\]', idl_type)
88    return matched and matched.group(1)
89
90
91def is_basic_type(idl_type):
92    return idl_type in BASIC_TYPES
93
94
95def is_callback_function_type(idl_type):
96    return idl_type in callback_function_types
97
98
99def set_callback_function_types(callback_functions):
100    callback_function_types.update(callback_functions.keys())
101
102
103def 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
110def is_enum_type(idl_type):
111    return idl_type in enum_types
112
113
114def enum_values(idl_type):
115    return enum_types.get(idl_type)
116
117
118def set_enum_types(enumerations):
119    enum_types.update([[enum.name, enum.values]
120                       for enum in enumerations.values()])
121
122
123def 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
136def sequence_type(idl_type):
137    matched = re.match(r'sequence<([\w\s]+)>', idl_type)
138    return matched and matched.group(1)
139
140
141def is_union_type(idl_type):
142    return isinstance(idl_type, idl_definitions.IdlUnionType)
143
144
145################################################################################
146# V8-specific type handling
147################################################################################
148
149DOM_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])
168NON_WRAPPER_TYPES = set([
169    'CompareHow',
170    'Dictionary',
171    'MediaQueryListListener',
172    'NodeFilter',
173    'SerializedScriptValue',
174])
175TYPED_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
191def constructor_type(idl_type):
192    return strip_suffix(idl_type, 'Constructor')
193
194
195def 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
201def is_typed_array_type(idl_type):
202    return idl_type in TYPED_ARRAYS
203
204
205def 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
214CPP_TYPE_SAME_AS_IDL_TYPE = set([
215    'double',
216    'float',
217    'long long',
218    'unsigned long long',
219])
220CPP_INT_TYPES = set([
221    'byte',
222    'long',
223    'short',
224])
225CPP_UNSIGNED_TYPES = set([
226    'octet',
227    'unsigned int',
228    'unsigned long',
229    'unsigned short',
230])
231CPP_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
241def 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
284def 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
293def v8_type(interface_type):
294    return 'V8' + interface_type
295
296
297################################################################################
298# Includes
299################################################################################
300
301
302def includes_for_cpp_class(class_name, relative_dir_posix):
303    return set([posixpath.join('bindings', relative_dir_posix, class_name + '.h')])
304
305
306INCLUDES_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
320def 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
335def add_includes_for_type(idl_type):
336    includes.update(includes_for_type(idl_type))
337
338
339################################################################################
340# V8 -> C++
341################################################################################
342
343V8_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
370def 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
397def 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
416def 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
437def 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
446def 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
468def 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
510V8_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
535def 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
556CPP_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
576def 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