OLD | NEW |
| (Empty) |
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 # FIXME: Eliminate custom bindings for XPathNSResolver http://crbug.com/345
529 | |
246 'XPathNSResolver': 'RefPtrWillBeRawPtr<XPathNSResolver>', | |
247 'boolean': 'bool', | |
248 } | |
249 | |
250 def cpp_type(idl_type, extended_attributes=None, used_as_argument=False): | |
251 """Returns C++ type corresponding to IDL type.""" | |
252 def string_mode(): | |
253 # FIXME: the Web IDL spec requires 'EmptyString', not 'NullString', | |
254 # but we use NullString for performance. | |
255 if extended_attributes.get('TreatNullAs') != 'NullString': | |
256 return '' | |
257 if extended_attributes.get('TreatUndefinedAs') != 'NullString': | |
258 return 'WithNullCheck' | |
259 return 'WithUndefinedOrNullCheck' | |
260 | |
261 extended_attributes = extended_attributes or {} | |
262 idl_type = preprocess_idl_type(idl_type) | |
263 | |
264 if idl_type in CPP_TYPE_SAME_AS_IDL_TYPE: | |
265 return idl_type | |
266 if idl_type in CPP_INT_TYPES: | |
267 return 'int' | |
268 if idl_type in CPP_UNSIGNED_TYPES: | |
269 return 'unsigned' | |
270 if idl_type in CPP_SPECIAL_CONVERSION_RULES: | |
271 return CPP_SPECIAL_CONVERSION_RULES[idl_type] | |
272 if idl_type in NON_WRAPPER_TYPES: | |
273 return 'RefPtr<%s>' % idl_type | |
274 if idl_type == 'DOMString': | |
275 if not used_as_argument: | |
276 return 'String' | |
277 return 'V8StringResource<%s>' % string_mode() | |
278 if is_union_type(idl_type): | |
279 # Attribute 'union_member_types' use is ok, but pylint can't infer this | |
280 # pylint: disable=E1103 | |
281 return (cpp_type(union_member_type) | |
282 for union_member_type in idl_type.union_member_types) | |
283 this_array_or_sequence_type = array_or_sequence_type(idl_type) | |
284 if this_array_or_sequence_type: | |
285 return cpp_template_type('Vector', cpp_type(this_array_or_sequence_type)
) | |
286 | |
287 if is_typed_array_type(idl_type) and used_as_argument: | |
288 return idl_type + '*' | |
289 if is_interface_type(idl_type): | |
290 implemented_as_class = implemented_as(idl_type) | |
291 if used_as_argument: | |
292 return implemented_as_class + '*' | |
293 if is_will_be_garbage_collected(idl_type): | |
294 return cpp_template_type('RefPtrWillBeRawPtr', implemented_as_class) | |
295 return cpp_template_type('RefPtr', implemented_as_class) | |
296 # Default, assume native type is a pointer with same type name as idl type | |
297 return idl_type + '*' | |
298 | |
299 | |
300 def cpp_template_type(template, inner_type): | |
301 """Returns C++ template specialized to type, with space added if needed.""" | |
302 if inner_type.endswith('>'): | |
303 format_string = '{template}<{inner_type} >' | |
304 else: | |
305 format_string = '{template}<{inner_type}>' | |
306 return format_string.format(template=template, inner_type=inner_type) | |
307 | |
308 | |
309 def v8_type(interface_type): | |
310 return 'V8' + interface_type | |
311 | |
312 | |
313 # [ImplementedAs] | |
314 # This handles [ImplementedAs] on interface types, not [ImplementedAs] in the | |
315 # interface being generated. e.g., given: | |
316 # Foo.idl: interface Foo {attribute Bar bar}; | |
317 # Bar.idl: [ImplementedAs=Zork] interface Bar {}; | |
318 # when generating bindings for Foo, the [ImplementedAs] on Bar is needed. | |
319 # This data is external to Foo.idl, and hence computed as global information in | |
320 # compute_dependencies.py to avoid having to parse IDLs of all used interfaces. | |
321 implemented_as_interfaces = {} | |
322 | |
323 | |
324 def implemented_as(idl_type): | |
325 if idl_type in implemented_as_interfaces: | |
326 return implemented_as_interfaces[idl_type] | |
327 return idl_type | |
328 | |
329 | |
330 def set_implemented_as_interfaces(new_implemented_as_interfaces): | |
331 implemented_as_interfaces.update(new_implemented_as_interfaces) | |
332 | |
333 | |
334 # [WillBeGarbageCollected] | |
335 will_be_garbage_collected_types = set() | |
336 | |
337 | |
338 def is_will_be_garbage_collected(idl_type): | |
339 return idl_type in will_be_garbage_collected_types | |
340 | |
341 | |
342 def set_will_be_garbage_collected_types(new_will_be_garbage_collected_types): | |
343 will_be_garbage_collected_types.update(new_will_be_garbage_collected_types) | |
344 | |
345 | |
346 ################################################################################ | |
347 # Includes | |
348 ################################################################################ | |
349 | |
350 def includes_for_cpp_class(class_name, relative_dir_posix): | |
351 return set([posixpath.join('bindings', relative_dir_posix, class_name + '.h'
)]) | |
352 | |
353 | |
354 INCLUDES_FOR_TYPE = { | |
355 'object': set(), | |
356 'CompareHow': set(), | |
357 'Dictionary': set(['bindings/v8/Dictionary.h']), | |
358 'EventHandler': set(['bindings/v8/V8AbstractEventListener.h', | |
359 'bindings/v8/V8EventListenerList.h']), | |
360 'EventListener': set(['bindings/v8/BindingSecurity.h', | |
361 'bindings/v8/V8EventListenerList.h', | |
362 'core/frame/DOMWindow.h']), | |
363 'MediaQueryListListener': set(['core/css/MediaQueryListListener.h']), | |
364 'Promise': set(['bindings/v8/ScriptPromise.h']), | |
365 'SerializedScriptValue': set(['bindings/v8/SerializedScriptValue.h']), | |
366 'ScriptValue': set(['bindings/v8/ScriptValue.h']), | |
367 } | |
368 | |
369 def includes_for_type(idl_type): | |
370 idl_type = preprocess_idl_type(idl_type) | |
371 if idl_type in INCLUDES_FOR_TYPE: | |
372 return INCLUDES_FOR_TYPE[idl_type] | |
373 if is_basic_type(idl_type): | |
374 return set() | |
375 if is_typed_array_type(idl_type): | |
376 return set(['bindings/v8/custom/V8%sCustom.h' % idl_type]) | |
377 this_array_or_sequence_type = array_or_sequence_type(idl_type) | |
378 if this_array_or_sequence_type: | |
379 return includes_for_type(this_array_or_sequence_type) | |
380 if is_union_type(idl_type): | |
381 # Attribute 'union_member_types' use is ok, but pylint can't infer this | |
382 # pylint: disable=E1103 | |
383 return set.union(*[ | |
384 includes_for_type(union_member_type) | |
385 for union_member_type in idl_type.union_member_types]) | |
386 if idl_type.endswith('ConstructorConstructor'): | |
387 # FIXME: rename to NamedConstructor | |
388 # Ending with 'ConstructorConstructor' indicates a named constructor, | |
389 # and these do not have header files, as they are part of the generated | |
390 # bindings for the interface | |
391 return set() | |
392 if idl_type.endswith('Constructor'): | |
393 idl_type = constructor_type(idl_type) | |
394 return set(['V8%s.h' % idl_type]) | |
395 | |
396 | |
397 def add_includes_for_type(idl_type): | |
398 includes.update(includes_for_type(idl_type)) | |
399 | |
400 | |
401 ################################################################################ | |
402 # V8 -> C++ | |
403 ################################################################################ | |
404 | |
405 V8_VALUE_TO_CPP_VALUE = { | |
406 # Basic | |
407 'Date': 'toCoreDate({v8_value})', | |
408 'DOMString': '{v8_value}', | |
409 'boolean': '{v8_value}->BooleanValue()', | |
410 'float': 'static_cast<float>({v8_value}->NumberValue())', | |
411 'double': 'static_cast<double>({v8_value}->NumberValue())', | |
412 'byte': 'toInt8({arguments})', | |
413 'octet': 'toUInt8({arguments})', | |
414 'short': 'toInt16({arguments})', | |
415 'unsigned short': 'toUInt16({arguments})', | |
416 'long': 'toInt32({arguments})', | |
417 'unsigned long': 'toUInt32({arguments})', | |
418 'long long': 'toInt64({arguments})', | |
419 'unsigned long long': 'toUInt64({arguments})', | |
420 # Interface types | |
421 'CompareHow': 'static_cast<Range::CompareHow>({v8_value}->Int32Value())', | |
422 'Dictionary': 'Dictionary({v8_value}, info.GetIsolate())', | |
423 'EventTarget': 'V8DOMWrapper::isDOMWrapper({v8_value}) ? toWrapperTypeInfo(v
8::Handle<v8::Object>::Cast({v8_value}))->toEventTarget(v8::Handle<v8::Object>::
Cast({v8_value})) : 0', | |
424 'MediaQueryListListener': 'MediaQueryListListener::create(ScriptValue({v8_va
lue}, info.GetIsolate()))', | |
425 'NodeFilter': 'toNodeFilter({v8_value}, info.GetIsolate())', | |
426 'Promise': 'ScriptPromise({v8_value}, info.GetIsolate())', | |
427 'SerializedScriptValue': 'SerializedScriptValue::create({v8_value}, info.Get
Isolate())', | |
428 'ScriptValue': 'ScriptValue({v8_value}, info.GetIsolate())', | |
429 'Window': 'toDOMWindow({v8_value}, info.GetIsolate())', | |
430 'XPathNSResolver': 'toXPathNSResolver({v8_value}, info.GetIsolate())', | |
431 } | |
432 | |
433 | |
434 def v8_value_to_cpp_value(idl_type, extended_attributes, v8_value, index): | |
435 this_array_or_sequence_type = array_or_sequence_type(idl_type) | |
436 if this_array_or_sequence_type: | |
437 return v8_value_to_cpp_value_array_or_sequence(this_array_or_sequence_ty
pe, v8_value, index) | |
438 | |
439 idl_type = preprocess_idl_type(idl_type) | |
440 add_includes_for_type(idl_type) | |
441 | |
442 if 'EnforceRange' in extended_attributes: | |
443 arguments = ', '.join([v8_value, 'EnforceRange', 'exceptionState']) | |
444 elif is_integer_type(idl_type): # NormalConversion | |
445 arguments = ', '.join([v8_value, 'exceptionState']) | |
446 else: | |
447 arguments = v8_value | |
448 | |
449 if idl_type in V8_VALUE_TO_CPP_VALUE: | |
450 cpp_expression_format = V8_VALUE_TO_CPP_VALUE[idl_type] | |
451 elif is_typed_array_type(idl_type): | |
452 cpp_expression_format = ( | |
453 '{v8_value}->Is{idl_type}() ? ' | |
454 'V8{idl_type}::toNative(v8::Handle<v8::{idl_type}>::Cast({v8_value})
) : 0') | |
455 else: | |
456 cpp_expression_format = ( | |
457 'V8{idl_type}::toNativeWithTypeCheck(info.GetIsolate(), {v8_value})'
) | |
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_valu
e, 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{a
rray_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_s
equence_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, variabl
e_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}, {varia
ble_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, i
ndex) | |
494 return format_string.format(cpp_type=this_cpp_type, cpp_value=cpp_value, var
iable_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['TreatReturnedNullSt
ringAs'] | |
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_returne
d_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.GetIso
late())', | |
579 'StringOrUndefined': 'v8SetReturnValueStringOrUndefined(info, {cpp_value}, i
nfo.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_wr
appable='', release=False, for_main_world=False): | |
599 """Returns a statement that converts a C++ value to a V8 value and sets it a
s 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, ext
ended_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', 'Seria
lizedScriptValue', 'array']: | |
625 # Convert value to V8 and then use general v8SetReturnValue | |
626 cpp_value = cpp_value_to_v8_value(idl_type, cpp_value, extended_attribut
es=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=scrip
t_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::Han
dle<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()', crea
tion_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, ext
ended_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, creat
ion_context=creation_context) | |
664 return statement | |
OLD | NEW |