Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / bindings / scripts / 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 Extends IdlType and IdlUnionType with V8-specific properties, methods, and
32 class methods.
33
34 Spec:
35 http://www.w3.org/TR/WebIDL/#es-type-mapping
36
37 Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
38 """
39
40 import posixpath
41
42 from idl_types import IdlTypeBase, IdlType, IdlUnionType, IdlArrayOrSequenceType
43 import v8_attributes  # for IdlType.constructor_type_name
44 from v8_globals import includes
45
46
47 ################################################################################
48 # V8-specific handling of IDL types
49 ################################################################################
50
51 NON_WRAPPER_TYPES = frozenset([
52     'CompareHow',
53     'Dictionary',
54     'EventHandler',
55     'EventListener',
56     'MediaQueryListListener',
57     'NodeFilter',
58     'SerializedScriptValue',
59 ])
60 TYPED_ARRAYS = {
61     # (cpp_type, v8_type), used by constructor templates
62     'ArrayBuffer': None,
63     'ArrayBufferView': None,
64     'Float32Array': ('float', 'v8::kExternalFloatArray'),
65     'Float64Array': ('double', 'v8::kExternalDoubleArray'),
66     'Int8Array': ('signed char', 'v8::kExternalByteArray'),
67     'Int16Array': ('short', 'v8::kExternalShortArray'),
68     'Int32Array': ('int', 'v8::kExternalIntArray'),
69     'Uint8Array': ('unsigned char', 'v8::kExternalUnsignedByteArray'),
70     'Uint8ClampedArray': ('unsigned char', 'v8::kExternalPixelArray'),
71     'Uint16Array': ('unsigned short', 'v8::kExternalUnsignedShortArray'),
72     'Uint32Array': ('unsigned int', 'v8::kExternalUnsignedIntArray'),
73 }
74
75 IdlTypeBase.is_typed_array_element_type = False
76 IdlType.is_typed_array_element_type = property(
77     lambda self: self.base_type in TYPED_ARRAYS)
78
79
80 IdlTypeBase.is_wrapper_type = False
81 IdlType.is_wrapper_type = property(
82     lambda self: (self.is_interface_type and
83                   self.base_type not in NON_WRAPPER_TYPES))
84
85
86 ################################################################################
87 # C++ types
88 ################################################################################
89
90 CPP_TYPE_SAME_AS_IDL_TYPE = set([
91     'double',
92     'float',
93     'long long',
94     'unsigned long long',
95 ])
96 CPP_INT_TYPES = set([
97     'byte',
98     'long',
99     'short',
100 ])
101 CPP_UNSIGNED_TYPES = set([
102     'octet',
103     'unsigned int',
104     'unsigned long',
105     'unsigned short',
106 ])
107 CPP_SPECIAL_CONVERSION_RULES = {
108     'CompareHow': 'Range::CompareHow',
109     'Date': 'double',
110     'Dictionary': 'Dictionary',
111     'EventHandler': 'EventListener*',
112     'MediaQueryListListener': 'RefPtrWillBeRawPtr<MediaQueryListListener>',
113     'NodeFilter': 'RefPtrWillBeRawPtr<NodeFilter>',
114     'Promise': 'ScriptPromise',
115     'ScriptValue': 'ScriptValue',
116     # FIXME: Eliminate custom bindings for XPathNSResolver  http://crbug.com/345529
117     'XPathNSResolver': 'RefPtrWillBeRawPtr<XPathNSResolver>',
118     'boolean': 'bool',
119     'unrestricted double': 'double',
120     'unrestricted float': 'float',
121 }
122
123
124 def cpp_type(idl_type, extended_attributes=None, raw_type=False, used_as_rvalue_type=False, used_as_variadic_argument=False, used_in_cpp_sequence=False):
125     """Returns C++ type corresponding to IDL type.
126
127     |idl_type| argument is of type IdlType, while return value is a string
128
129     Args:
130         idl_type:
131             IdlType
132         raw_type:
133             bool, True if idl_type's raw/primitive C++ type should be returned.
134         used_as_rvalue_type:
135             bool, True if the C++ type is used as an argument or the return
136             type of a method.
137         used_as_variadic_argument:
138             bool, True if the C++ type is used as a variadic argument of a method.
139         used_in_cpp_sequence:
140             bool, True if the C++ type is used as an element of a container.
141             Containers can be an array, a sequence or a dictionary.
142     """
143     def string_mode():
144         if extended_attributes.get('TreatNullAs') == 'EmptyString':
145             return 'TreatNullAsEmptyString'
146         if idl_type.is_nullable or extended_attributes.get('TreatNullAs') == 'NullString':
147             if extended_attributes.get('TreatUndefinedAs') == 'NullString':
148                 return 'TreatNullAndUndefinedAsNullString'
149             return 'TreatNullAsNullString'
150         return ''
151
152     extended_attributes = extended_attributes or {}
153     idl_type = idl_type.preprocessed_type
154
155     # Array or sequence types
156     if used_as_variadic_argument:
157         native_array_element_type = idl_type
158     else:
159         native_array_element_type = idl_type.native_array_element_type
160     if native_array_element_type:
161         vector_type = cpp_ptr_type('Vector', 'HeapVector', native_array_element_type.gc_type)
162         vector_template_type = cpp_template_type(vector_type, native_array_element_type.cpp_type_args(used_in_cpp_sequence=True))
163         if used_as_rvalue_type:
164             return 'const %s&' % vector_template_type
165         return vector_template_type
166
167     # Simple types
168     base_idl_type = idl_type.base_type
169
170     if base_idl_type in CPP_TYPE_SAME_AS_IDL_TYPE:
171         return base_idl_type
172     if base_idl_type in CPP_INT_TYPES:
173         return 'int'
174     if base_idl_type in CPP_UNSIGNED_TYPES:
175         return 'unsigned'
176     if base_idl_type in CPP_SPECIAL_CONVERSION_RULES:
177         return CPP_SPECIAL_CONVERSION_RULES[base_idl_type]
178
179     if base_idl_type in NON_WRAPPER_TYPES:
180         return ('PassRefPtr<%s>' if used_as_rvalue_type else 'RefPtr<%s>') % base_idl_type
181     if idl_type.is_string_type:
182         if not raw_type:
183             return 'String'
184         return 'V8StringResource<%s>' % string_mode()
185
186     if idl_type.is_typed_array_element_type and raw_type:
187         return base_idl_type + '*'
188     if idl_type.is_interface_type:
189         implemented_as_class = idl_type.implemented_as
190         if raw_type:
191             return implemented_as_class + '*'
192         new_type = 'Member' if used_in_cpp_sequence else 'RawPtr'
193         ptr_type = cpp_ptr_type(('PassRefPtr' if used_as_rvalue_type else 'RefPtr'), new_type, idl_type.gc_type)
194         return cpp_template_type(ptr_type, implemented_as_class)
195     # Default, assume native type is a pointer with same type name as idl type
196     return base_idl_type + '*'
197
198
199 def cpp_type_initializer(idl_type):
200     """Returns a string containing a C++ initialization statement for the
201     corresponding type.
202
203     |idl_type| argument is of type IdlType.
204     """
205
206     if (idl_type.is_numeric_type):
207         return ' = 0'
208     if idl_type.base_type == 'boolean':
209         return ' = false'
210     return ''
211
212
213 def cpp_type_union(idl_type, extended_attributes=None, raw_type=False):
214     # FIXME: Need to revisit the design of union support.
215     # http://crbug.com/240176
216     return None
217
218
219 def cpp_type_initializer_union(idl_type):
220     return (member_type.cpp_type_initializer for member_type in idl_type.member_types)
221
222
223 # Allow access as idl_type.cpp_type if no arguments
224 IdlTypeBase.cpp_type = property(cpp_type)
225 IdlTypeBase.cpp_type_initializer = property(cpp_type_initializer)
226 IdlTypeBase.cpp_type_args = cpp_type
227 IdlUnionType.cpp_type = property(cpp_type_union)
228 IdlUnionType.cpp_type_initializer = property(cpp_type_initializer_union)
229 IdlUnionType.cpp_type_args = cpp_type_union
230
231
232 IdlTypeBase.native_array_element_type = None
233 IdlArrayOrSequenceType.native_array_element_type = property(
234     lambda self: self.element_type)
235
236
237 def cpp_template_type(template, inner_type):
238     """Returns C++ template specialized to type, with space added if needed."""
239     if inner_type.endswith('>'):
240         format_string = '{template}<{inner_type} >'
241     else:
242         format_string = '{template}<{inner_type}>'
243     return format_string.format(template=template, inner_type=inner_type)
244
245
246 def cpp_ptr_type(old_type, new_type, gc_type):
247     if gc_type == 'GarbageCollectedObject':
248         return new_type
249     if gc_type == 'WillBeGarbageCollectedObject':
250         if old_type == 'Vector':
251             return 'WillBe' + new_type
252         return old_type + 'WillBe' + new_type
253     return old_type
254
255
256 def v8_type(interface_name):
257     return 'V8' + interface_name
258
259
260 # [ImplementedAs]
261 # This handles [ImplementedAs] on interface types, not [ImplementedAs] in the
262 # interface being generated. e.g., given:
263 #   Foo.idl: interface Foo {attribute Bar bar};
264 #   Bar.idl: [ImplementedAs=Zork] interface Bar {};
265 # when generating bindings for Foo, the [ImplementedAs] on Bar is needed.
266 # This data is external to Foo.idl, and hence computed as global information in
267 # compute_interfaces_info.py to avoid having to parse IDLs of all used interfaces.
268 IdlType.implemented_as_interfaces = {}
269
270
271 def implemented_as(idl_type):
272     base_idl_type = idl_type.base_type
273     if base_idl_type in IdlType.implemented_as_interfaces:
274         return IdlType.implemented_as_interfaces[base_idl_type]
275     return base_idl_type
276
277
278 IdlType.implemented_as = property(implemented_as)
279
280 IdlType.set_implemented_as_interfaces = classmethod(
281     lambda cls, new_implemented_as_interfaces:
282         cls.implemented_as_interfaces.update(new_implemented_as_interfaces))
283
284
285 # [GarbageCollected]
286 IdlType.garbage_collected_types = set()
287
288 IdlTypeBase.is_garbage_collected = False
289 IdlType.is_garbage_collected = property(
290     lambda self: self.base_type in IdlType.garbage_collected_types)
291
292 IdlType.set_garbage_collected_types = classmethod(
293     lambda cls, new_garbage_collected_types:
294         cls.garbage_collected_types.update(new_garbage_collected_types))
295
296
297 # [WillBeGarbageCollected]
298 IdlType.will_be_garbage_collected_types = set()
299
300 IdlTypeBase.is_will_be_garbage_collected = False
301 IdlType.is_will_be_garbage_collected = property(
302     lambda self: self.base_type in IdlType.will_be_garbage_collected_types)
303
304 IdlType.set_will_be_garbage_collected_types = classmethod(
305     lambda cls, new_will_be_garbage_collected_types:
306         cls.will_be_garbage_collected_types.update(new_will_be_garbage_collected_types))
307
308
309 def gc_type(idl_type):
310     if idl_type.is_garbage_collected:
311         return 'GarbageCollectedObject'
312     if idl_type.is_will_be_garbage_collected:
313         return 'WillBeGarbageCollectedObject'
314     return 'RefCountedObject'
315
316 IdlTypeBase.gc_type = property(gc_type)
317
318
319 ################################################################################
320 # Includes
321 ################################################################################
322
323 def includes_for_cpp_class(class_name, relative_dir_posix):
324     return set([posixpath.join('bindings', relative_dir_posix, class_name + '.h')])
325
326
327 INCLUDES_FOR_TYPE = {
328     'object': set(),
329     'CompareHow': set(),
330     'Dictionary': set(['bindings/core/v8/Dictionary.h']),
331     'EventHandler': set(['bindings/core/v8/V8AbstractEventListener.h',
332                          'bindings/core/v8/V8EventListenerList.h']),
333     'EventListener': set(['bindings/core/v8/BindingSecurity.h',
334                           'bindings/core/v8/V8EventListenerList.h',
335                           'core/frame/LocalDOMWindow.h']),
336     'HTMLCollection': set(['bindings/core/v8/V8HTMLCollection.h',
337                            'core/dom/ClassCollection.h',
338                            'core/dom/TagCollection.h',
339                            'core/html/HTMLCollection.h',
340                            'core/html/HTMLFormControlsCollection.h',
341                            'core/html/HTMLTableRowsCollection.h']),
342     'MediaQueryListListener': set(['core/css/MediaQueryListListener.h']),
343     'NodeList': set(['bindings/core/v8/V8NodeList.h',
344                      'core/dom/NameNodeList.h',
345                      'core/dom/NodeList.h',
346                      'core/dom/StaticNodeList.h',
347                      'core/html/LabelsNodeList.h']),
348     'Promise': set(['bindings/core/v8/ScriptPromise.h']),
349     'SerializedScriptValue': set(['bindings/core/v8/SerializedScriptValue.h']),
350     'ScriptValue': set(['bindings/core/v8/ScriptValue.h']),
351 }
352
353
354 def includes_for_type(idl_type):
355     idl_type = idl_type.preprocessed_type
356
357     # Simple types
358     base_idl_type = idl_type.base_type
359     if base_idl_type in INCLUDES_FOR_TYPE:
360         return INCLUDES_FOR_TYPE[base_idl_type]
361     if idl_type.is_basic_type:
362         return set()
363     if idl_type.is_typed_array_element_type:
364         return set(['bindings/core/v8/custom/V8%sCustom.h' % base_idl_type])
365     if base_idl_type.endswith('ConstructorConstructor'):
366         # FIXME: rename to NamedConstructor
367         # FIXME: replace with a [NamedConstructorAttribute] extended attribute
368         # Ending with 'ConstructorConstructor' indicates a named constructor,
369         # and these do not have header files, as they are part of the generated
370         # bindings for the interface
371         return set()
372     if base_idl_type.endswith('Constructor'):
373         # FIXME: replace with a [ConstructorAttribute] extended attribute
374         base_idl_type = idl_type.constructor_type_name
375     if base_idl_type not in component_dir:
376         return set()
377     return set(['bindings/%s/v8/V8%s.h' % (component_dir[base_idl_type],
378                                            base_idl_type)])
379
380 IdlType.includes_for_type = property(includes_for_type)
381 IdlUnionType.includes_for_type = property(
382     lambda self: set.union(*[includes_for_type(member_type)
383                              for member_type in self.member_types]))
384 IdlArrayOrSequenceType.includes_for_type = property(
385     lambda self: self.element_type.includes_for_type)
386
387
388 def add_includes_for_type(idl_type):
389     includes.update(idl_type.includes_for_type)
390
391 IdlTypeBase.add_includes_for_type = add_includes_for_type
392
393
394 def includes_for_interface(interface_name):
395     return IdlType(interface_name).includes_for_type
396
397
398 def add_includes_for_interface(interface_name):
399     includes.update(includes_for_interface(interface_name))
400
401
402 def impl_should_use_nullable_container(idl_type):
403     return not(idl_type.cpp_type_has_null_value)
404
405 IdlTypeBase.impl_should_use_nullable_container = property(
406     impl_should_use_nullable_container)
407
408
409 def impl_includes_for_type(idl_type, interfaces_info):
410     includes_for_type = set()
411     if idl_type.impl_should_use_nullable_container:
412         includes_for_type.add('bindings/core/v8/Nullable.h')
413
414     idl_type = idl_type.preprocessed_type
415     native_array_element_type = idl_type.native_array_element_type
416     if native_array_element_type:
417         includes_for_type.update(impl_includes_for_type(
418                 native_array_element_type, interfaces_info))
419         includes_for_type.add('wtf/Vector.h')
420
421     if idl_type.is_string_type:
422         includes_for_type.add('wtf/text/WTFString.h')
423     if idl_type.name in interfaces_info:
424         interface_info = interfaces_info[idl_type.name]
425         includes_for_type.add(interface_info['include_path'])
426     return includes_for_type
427
428 IdlTypeBase.impl_includes_for_type = impl_includes_for_type
429
430
431 component_dir = {}
432
433
434 def set_component_dirs(new_component_dirs):
435     component_dir.update(new_component_dirs)
436
437
438 ################################################################################
439 # V8 -> C++
440 ################################################################################
441
442 V8_VALUE_TO_CPP_VALUE = {
443     # Basic
444     'Date': 'toCoreDate({v8_value})',
445     'DOMString': '{v8_value}',
446     'ByteString': 'toByteString({arguments})',
447     'ScalarValueString': 'toScalarValueString({arguments})',
448     'boolean': '{v8_value}->BooleanValue()',
449     'float': 'static_cast<float>({v8_value}->NumberValue())',
450     'unrestricted float': 'static_cast<float>({v8_value}->NumberValue())',
451     'double': 'static_cast<double>({v8_value}->NumberValue())',
452     'unrestricted double': 'static_cast<double>({v8_value}->NumberValue())',
453     'byte': 'toInt8({arguments})',
454     'octet': 'toUInt8({arguments})',
455     'short': 'toInt16({arguments})',
456     'unsigned short': 'toUInt16({arguments})',
457     'long': 'toInt32({arguments})',
458     'unsigned long': 'toUInt32({arguments})',
459     'long long': 'toInt64({arguments})',
460     'unsigned long long': 'toUInt64({arguments})',
461     # Interface types
462     'CompareHow': 'static_cast<Range::CompareHow>({v8_value}->Int32Value())',
463     'Dictionary': 'Dictionary({v8_value}, {isolate})',
464     'EventTarget': 'V8DOMWrapper::isDOMWrapper({v8_value}) ? toWrapperTypeInfo(v8::Handle<v8::Object>::Cast({v8_value}))->toEventTarget(v8::Handle<v8::Object>::Cast({v8_value})) : 0',
465     'MediaQueryListListener': 'MediaQueryListListener::create(ScriptState::current({isolate}), ScriptValue(ScriptState::current({isolate}), {v8_value}))',
466     'NodeFilter': 'toNodeFilter({v8_value}, info.Holder(), ScriptState::current({isolate}))',
467     'Promise': 'ScriptPromise::cast(ScriptState::current({isolate}), {v8_value})',
468     'SerializedScriptValue': 'SerializedScriptValue::create({v8_value}, {isolate})',
469     'ScriptValue': 'ScriptValue(ScriptState::current({isolate}), {v8_value})',
470     'Window': 'toDOMWindow({v8_value}, {isolate})',
471     'XPathNSResolver': 'toXPathNSResolver({v8_value}, {isolate})',
472 }
473
474
475 def v8_value_to_cpp_value(idl_type, extended_attributes, v8_value, index, isolate):
476     if idl_type.name == 'void':
477         return ''
478
479     # Array or sequence types
480     native_array_element_type = idl_type.native_array_element_type
481     if native_array_element_type:
482         return v8_value_to_cpp_value_array_or_sequence(native_array_element_type, v8_value, index)
483
484     # Simple types
485     idl_type = idl_type.preprocessed_type
486     add_includes_for_type(idl_type)
487     base_idl_type = idl_type.base_type
488
489     if 'EnforceRange' in extended_attributes:
490         arguments = ', '.join([v8_value, 'EnforceRange', 'exceptionState'])
491     elif idl_type.may_raise_exception_on_conversion:
492         arguments = ', '.join([v8_value, 'exceptionState'])
493     else:
494         arguments = v8_value
495
496     if base_idl_type in V8_VALUE_TO_CPP_VALUE:
497         cpp_expression_format = V8_VALUE_TO_CPP_VALUE[base_idl_type]
498     elif idl_type.is_typed_array_element_type:
499         cpp_expression_format = (
500             '{v8_value}->Is{idl_type}() ? '
501             'V8{idl_type}::toNative(v8::Handle<v8::{idl_type}>::Cast({v8_value})) : 0')
502     elif idl_type.is_dictionary:
503         cpp_expression_format = 'V8{idl_type}::toNative({isolate}, {v8_value})'
504     else:
505         cpp_expression_format = (
506             'V8{idl_type}::toNativeWithTypeCheck({isolate}, {v8_value})')
507
508     return cpp_expression_format.format(arguments=arguments, idl_type=base_idl_type, v8_value=v8_value, isolate=isolate)
509
510
511 def v8_value_to_cpp_value_array_or_sequence(native_array_element_type, v8_value, index, isolate='info.GetIsolate()'):
512     # Index is None for setters, index (starting at 0) for method arguments,
513     # and is used to provide a human-readable exception message
514     if index is None:
515         index = 0  # special case, meaning "setter"
516     else:
517         index += 1  # human-readable index
518     if (native_array_element_type.is_interface_type and
519         native_array_element_type.name != 'Dictionary'):
520         this_cpp_type = None
521         ref_ptr_type = cpp_ptr_type('RefPtr', 'Member', native_array_element_type.gc_type)
522         expression_format = '(to{ref_ptr_type}NativeArray<{native_array_element_type}, V8{native_array_element_type}>({v8_value}, {index}, {isolate}))'
523         add_includes_for_type(native_array_element_type)
524     else:
525         ref_ptr_type = None
526         this_cpp_type = native_array_element_type.cpp_type
527         expression_format = 'toNativeArray<{cpp_type}>({v8_value}, {index}, {isolate})'
528     expression = expression_format.format(native_array_element_type=native_array_element_type.name, cpp_type=this_cpp_type, index=index, ref_ptr_type=ref_ptr_type, v8_value=v8_value, isolate=isolate)
529     return expression
530
531
532 def v8_value_to_local_cpp_value(idl_type, extended_attributes, v8_value, variable_name, index=None, declare_variable=True, isolate='info.GetIsolate()', used_in_private_script=False, return_promise=False):
533     """Returns an expression that converts a V8 value to a C++ value and stores it as a local value."""
534
535     # FIXME: Support union type.
536     if idl_type.is_union_type:
537         return ''
538
539     this_cpp_type = idl_type.cpp_type_args(extended_attributes=extended_attributes, raw_type=True)
540
541     idl_type = idl_type.preprocessed_type
542     cpp_value = v8_value_to_cpp_value(idl_type, extended_attributes, v8_value, index, isolate)
543     args = [variable_name, cpp_value]
544     if idl_type.base_type == 'DOMString':
545         macro = 'TOSTRING_DEFAULT' if used_in_private_script else 'TOSTRING_VOID'
546     elif idl_type.may_raise_exception_on_conversion:
547         macro = 'TONATIVE_DEFAULT_EXCEPTIONSTATE' if used_in_private_script else 'TONATIVE_VOID_EXCEPTIONSTATE'
548         args.append('exceptionState')
549     else:
550         macro = 'TONATIVE_DEFAULT' if used_in_private_script else 'TONATIVE_VOID'
551
552     if used_in_private_script:
553         args.append('false')
554
555     # Macros come in several variants, to minimize expensive creation of
556     # v8::TryCatch.
557     suffix = ''
558
559     if return_promise:
560         suffix += '_PROMISE'
561         args.append('info')
562         if macro == 'TONATIVE_VOID_EXCEPTIONSTATE':
563             args.append('ScriptState::current(%s)' % isolate)
564
565     if declare_variable:
566         args.insert(0, this_cpp_type)
567     else:
568         suffix += '_INTERNAL'
569
570     return '%s(%s)' % (macro + suffix, ', '.join(args))
571
572 IdlTypeBase.v8_value_to_local_cpp_value = v8_value_to_local_cpp_value
573
574
575 ################################################################################
576 # C++ -> V8
577 ################################################################################
578
579 def preprocess_idl_type(idl_type):
580     if idl_type.is_enum:
581         # Enumerations are internally DOMStrings
582         return IdlType('DOMString')
583     if (idl_type.name == 'Any' or idl_type.is_callback_function):
584         return IdlType('ScriptValue')
585     return idl_type
586
587 IdlTypeBase.preprocessed_type = property(preprocess_idl_type)
588
589
590 def preprocess_idl_type_and_value(idl_type, cpp_value, extended_attributes):
591     """Returns IDL type and value, with preliminary type conversions applied."""
592     idl_type = idl_type.preprocessed_type
593     if idl_type.name == 'Promise':
594         idl_type = IdlType('ScriptValue')
595     if idl_type.base_type in ['long long', 'unsigned long long']:
596         # long long and unsigned long long are not representable in ECMAScript;
597         # we represent them as doubles.
598         idl_type = IdlType('double', is_nullable=idl_type.is_nullable)
599         cpp_value = 'static_cast<double>(%s)' % cpp_value
600     # HTML5 says that unsigned reflected attributes should be in the range
601     # [0, 2^31). When a value isn't in this range, a default value (or 0)
602     # should be returned instead.
603     extended_attributes = extended_attributes or {}
604     if ('Reflect' in extended_attributes and
605         idl_type.base_type in ['unsigned long', 'unsigned short']):
606         cpp_value = cpp_value.replace('getUnsignedIntegralAttribute',
607                                       'getIntegralAttribute')
608         cpp_value = 'std::max(0, static_cast<int>(%s))' % cpp_value
609     return idl_type, cpp_value
610
611
612 def v8_conversion_type(idl_type, extended_attributes):
613     """Returns V8 conversion type, adding any additional includes.
614
615     The V8 conversion type is used to select the C++ -> V8 conversion function
616     or v8SetReturnValue* function; it can be an idl_type, a cpp_type, or a
617     separate name for the type of conversion (e.g., 'DOMWrapper').
618     """
619     extended_attributes = extended_attributes or {}
620
621     # FIXME: Support union type.
622     if idl_type.is_union_type:
623         return ''
624
625     # Array or sequence types
626     native_array_element_type = idl_type.native_array_element_type
627     if native_array_element_type:
628         if native_array_element_type.is_interface_type:
629             add_includes_for_type(native_array_element_type)
630         return 'array'
631
632     # Simple types
633     base_idl_type = idl_type.base_type
634     # Basic types, without additional includes
635     if base_idl_type in CPP_INT_TYPES:
636         return 'int'
637     if base_idl_type in CPP_UNSIGNED_TYPES:
638         return 'unsigned'
639     if idl_type.is_string_type:
640         if idl_type.is_nullable:
641             return 'StringOrNull'
642         if 'TreatReturnedNullStringAs' not in extended_attributes:
643             return base_idl_type
644         treat_returned_null_string_as = extended_attributes['TreatReturnedNullStringAs']
645         if treat_returned_null_string_as == 'Null':
646             return 'StringOrNull'
647         if treat_returned_null_string_as == 'Undefined':
648             return 'StringOrUndefined'
649         raise 'Unrecognized TreatReturnedNullStringAs value: "%s"' % treat_returned_null_string_as
650     if idl_type.is_basic_type or base_idl_type == 'ScriptValue':
651         return base_idl_type
652
653     # Data type with potential additional includes
654     add_includes_for_type(idl_type)
655     if base_idl_type in V8_SET_RETURN_VALUE:  # Special v8SetReturnValue treatment
656         return base_idl_type
657
658     # Pointer type
659     return 'DOMWrapper'
660
661 IdlTypeBase.v8_conversion_type = v8_conversion_type
662
663
664 V8_SET_RETURN_VALUE = {
665     'boolean': 'v8SetReturnValueBool(info, {cpp_value})',
666     'int': 'v8SetReturnValueInt(info, {cpp_value})',
667     'unsigned': 'v8SetReturnValueUnsigned(info, {cpp_value})',
668     'DOMString': 'v8SetReturnValueString(info, {cpp_value}, info.GetIsolate())',
669     'ByteString': 'v8SetReturnValueString(info, {cpp_value}, info.GetIsolate())',
670     'ScalarValueString': 'v8SetReturnValueString(info, {cpp_value}, info.GetIsolate())',
671     # [TreatReturnedNullStringAs]
672     'StringOrNull': 'v8SetReturnValueStringOrNull(info, {cpp_value}, info.GetIsolate())',
673     'StringOrUndefined': 'v8SetReturnValueStringOrUndefined(info, {cpp_value}, info.GetIsolate())',
674     'void': '',
675     # No special v8SetReturnValue* function (set value directly)
676     'float': 'v8SetReturnValue(info, {cpp_value})',
677     'unrestricted float': 'v8SetReturnValue(info, {cpp_value})',
678     'double': 'v8SetReturnValue(info, {cpp_value})',
679     'unrestricted double': 'v8SetReturnValue(info, {cpp_value})',
680     # No special v8SetReturnValue* function, but instead convert value to V8
681     # and then use general v8SetReturnValue.
682     'array': 'v8SetReturnValue(info, {cpp_value})',
683     'Date': 'v8SetReturnValue(info, {cpp_value})',
684     'EventHandler': 'v8SetReturnValue(info, {cpp_value})',
685     'ScriptValue': 'v8SetReturnValue(info, {cpp_value})',
686     'SerializedScriptValue': 'v8SetReturnValue(info, {cpp_value})',
687     # DOMWrapper
688     'DOMWrapperForMainWorld': 'v8SetReturnValueForMainWorld(info, WTF::getPtr({cpp_value}))',
689     'DOMWrapperFast': 'v8SetReturnValueFast(info, WTF::getPtr({cpp_value}), {script_wrappable})',
690     'DOMWrapperDefault': 'v8SetReturnValue(info, {cpp_value})',
691 }
692
693
694 def v8_set_return_value(idl_type, cpp_value, extended_attributes=None, script_wrappable='', release=False, for_main_world=False):
695     """Returns a statement that converts a C++ value to a V8 value and sets it as a return value.
696
697     """
698     def dom_wrapper_conversion_type():
699         if not script_wrappable:
700             return 'DOMWrapperDefault'
701         if for_main_world:
702             return 'DOMWrapperForMainWorld'
703         return 'DOMWrapperFast'
704
705     idl_type, cpp_value = preprocess_idl_type_and_value(idl_type, cpp_value, extended_attributes)
706     this_v8_conversion_type = idl_type.v8_conversion_type(extended_attributes)
707     # SetReturn-specific overrides
708     if this_v8_conversion_type in ['Date', 'EventHandler', 'ScriptValue', 'SerializedScriptValue', 'array']:
709         # Convert value to V8 and then use general v8SetReturnValue
710         cpp_value = idl_type.cpp_value_to_v8_value(cpp_value, extended_attributes=extended_attributes)
711     if this_v8_conversion_type == 'DOMWrapper':
712         this_v8_conversion_type = dom_wrapper_conversion_type()
713
714     format_string = V8_SET_RETURN_VALUE[this_v8_conversion_type]
715     # FIXME: oilpan: Remove .release() once we remove all RefPtrs from generated code.
716     if release:
717         cpp_value = '%s.release()' % cpp_value
718     statement = format_string.format(cpp_value=cpp_value, script_wrappable=script_wrappable)
719     return statement
720
721
722 def v8_set_return_value_union(idl_type, cpp_value, extended_attributes=None, script_wrappable='', release=False, for_main_world=False):
723     # FIXME: Need to revisit the design of union support.
724     # http://crbug.com/240176
725     return None
726
727
728 IdlTypeBase.v8_set_return_value = v8_set_return_value
729 IdlUnionType.v8_set_return_value = v8_set_return_value_union
730
731 IdlType.release = property(lambda self: self.is_interface_type)
732 IdlUnionType.release = property(
733     lambda self: [member_type.is_interface_type
734                   for member_type in self.member_types])
735 IdlArrayOrSequenceType.release = False
736
737
738 CPP_VALUE_TO_V8_VALUE = {
739     # Built-in types
740     'Date': 'v8DateOrNaN({cpp_value}, {isolate})',
741     'DOMString': 'v8String({isolate}, {cpp_value})',
742     'ByteString': 'v8String({isolate}, {cpp_value})',
743     'ScalarValueString': 'v8String({isolate}, {cpp_value})',
744     'boolean': 'v8Boolean({cpp_value}, {isolate})',
745     'int': 'v8::Integer::New({isolate}, {cpp_value})',
746     'unsigned': 'v8::Integer::NewFromUnsigned({isolate}, {cpp_value})',
747     'float': 'v8::Number::New({isolate}, {cpp_value})',
748     'unrestricted float': 'v8::Number::New({isolate}, {cpp_value})',
749     'double': 'v8::Number::New({isolate}, {cpp_value})',
750     'unrestricted double': 'v8::Number::New({isolate}, {cpp_value})',
751     'void': 'v8Undefined()',
752     # [TreatReturnedNullStringAs]
753     'StringOrNull': '{cpp_value}.isNull() ? v8::Handle<v8::Value>(v8::Null({isolate})) : v8String({isolate}, {cpp_value})',
754     'StringOrUndefined': '{cpp_value}.isNull() ? v8Undefined() : v8String({isolate}, {cpp_value})',
755     # Special cases
756     'EventHandler': '{cpp_value} ? v8::Handle<v8::Value>(V8AbstractEventListener::cast({cpp_value})->getListenerObject(impl->executionContext())) : v8::Handle<v8::Value>(v8::Null({isolate}))',
757     'ScriptValue': '{cpp_value}.v8Value()',
758     'SerializedScriptValue': '{cpp_value} ? {cpp_value}->deserialize() : v8::Handle<v8::Value>(v8::Null({isolate}))',
759     # General
760     'array': 'v8Array({cpp_value}, {creation_context}, {isolate})',
761     'DOMWrapper': 'toV8({cpp_value}, {creation_context}, {isolate})',
762 }
763
764
765 def cpp_value_to_v8_value(idl_type, cpp_value, isolate='info.GetIsolate()', creation_context='info.Holder()', extended_attributes=None):
766     """Returns an expression that converts a C++ value to a V8 value."""
767     # the isolate parameter is needed for callback interfaces
768     idl_type, cpp_value = preprocess_idl_type_and_value(idl_type, cpp_value, extended_attributes)
769     this_v8_conversion_type = idl_type.v8_conversion_type(extended_attributes)
770     format_string = CPP_VALUE_TO_V8_VALUE[this_v8_conversion_type]
771     statement = format_string.format(cpp_value=cpp_value, isolate=isolate, creation_context=creation_context)
772     return statement
773
774 IdlTypeBase.cpp_value_to_v8_value = cpp_value_to_v8_value
775
776
777 def literal_cpp_value(idl_type, idl_literal):
778     """Converts an expression that is a valid C++ literal for this type."""
779     # FIXME: add validation that idl_type and idl_literal are compatible
780     literal_value = str(idl_literal)
781     if idl_type.base_type in CPP_UNSIGNED_TYPES:
782         return literal_value + 'u'
783     return literal_value
784
785 IdlType.literal_cpp_value = literal_cpp_value
786
787
788 ################################################################################
789 # Utility properties for nullable types
790 ################################################################################
791
792
793 def cpp_type_has_null_value(idl_type):
794     # - String types (String/AtomicString) represent null as a null string,
795     #   i.e. one for which String::isNull() returns true.
796     # - Wrapper types (raw pointer or RefPtr/PassRefPtr) represent null as
797     #   a null pointer.
798     return idl_type.is_string_type or idl_type.is_wrapper_type
799
800 IdlTypeBase.cpp_type_has_null_value = property(cpp_type_has_null_value)
801
802
803 def is_implicit_nullable(idl_type):
804     # Nullable type where the corresponding C++ type supports a null value.
805     return idl_type.is_nullable and idl_type.cpp_type_has_null_value
806
807
808 def is_explicit_nullable(idl_type):
809     # Nullable type that isn't implicit nullable (see above.) For such types,
810     # we use Nullable<T> or similar explicit ways to represent a null value.
811     return idl_type.is_nullable and not idl_type.is_implicit_nullable
812
813 IdlTypeBase.is_implicit_nullable = property(is_implicit_nullable)
814 IdlUnionType.is_implicit_nullable = False
815 IdlTypeBase.is_explicit_nullable = property(is_explicit_nullable)