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++ <-> Dart:HTML). |
| 30 |
| 31 Extends IdlType and IdlUnionType with C++-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 from idl_types import IdlType, IdlUnionType, TYPE_NAMES |
| 42 import dart_attributes # for IdlType.constructor_type_name |
| 43 from dart_utilities import DartUtilities |
| 44 from v8_globals import includes |
| 45 |
| 46 |
| 47 ################################################################################ |
| 48 # CPP -specific handling of IDL types for Dart:Blink |
| 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, dart_type), used by constructor templates |
| 62 'ArrayBuffer': (None, 'ByteBuffer'), |
| 63 'ArrayBufferView': (None, 'ByteData'), |
| 64 'Float32Array': ('float', 'Float32List'), |
| 65 'Float64Array': ('double', 'Float64List'), |
| 66 'Int8Array': ('signed char', 'Int8List'), |
| 67 'Int16Array': ('short', 'Int16List'), |
| 68 'Int32Array': ('int', 'Int32List'), |
| 69 'Uint8Array': ('unsigned char', 'Uint8List'), |
| 70 'Uint8ClampedArray': ('unsigned char', 'Uint8ClampedList'), |
| 71 'Uint16Array': ('unsigned short', 'Uint16List'), |
| 72 'Uint32Array': ('unsigned int', 'Uint32List'), |
| 73 } |
| 74 |
| 75 IdlType.is_typed_array_type = property( |
| 76 lambda self: self.base_type in TYPED_ARRAYS) |
| 77 |
| 78 |
| 79 IdlType.is_wrapper_type = property( |
| 80 lambda self: (self.is_interface_type and |
| 81 self.base_type not in NON_WRAPPER_TYPES)) |
| 82 |
| 83 |
| 84 ################################################################################ |
| 85 # C++ types |
| 86 ################################################################################ |
| 87 |
| 88 CPP_TYPE_SAME_AS_IDL_TYPE = set([ |
| 89 'double', |
| 90 'float', |
| 91 'long long', |
| 92 'unsigned long long', |
| 93 ]) |
| 94 CPP_INT_TYPES = set([ |
| 95 'byte', |
| 96 'long', |
| 97 'short', |
| 98 ]) |
| 99 CPP_UNSIGNED_TYPES = set([ |
| 100 'octet', |
| 101 'unsigned int', |
| 102 'unsigned long', |
| 103 'unsigned short', |
| 104 ]) |
| 105 CPP_SPECIAL_CONVERSION_RULES = { |
| 106 'CompareHow': 'Range::CompareHow', |
| 107 'Date': 'double', |
| 108 'Dictionary': 'Dictionary', |
| 109 'EventHandler': 'EventListener*', |
| 110 'MediaQueryListListener': 'RefPtrWillBeRawPtr<MediaQueryListListener>', |
| 111 'Promise': 'ScriptPromise', |
| 112 'ScriptValue': 'ScriptValue', |
| 113 # FIXME: Eliminate custom bindings for XPathNSResolver http://crbug.com/345
529 |
| 114 'XPathNSResolver': 'RefPtrWillBeRawPtr<XPathNSResolver>', |
| 115 'boolean': 'bool', |
| 116 'unrestricted double': 'double', |
| 117 'unrestricted float': 'float', |
| 118 } |
| 119 |
| 120 |
| 121 def cpp_type(idl_type, extended_attributes=None, used_as_argument=False, used_in
_cpp_sequence=False): |
| 122 """Returns C++ type corresponding to IDL type. |
| 123 |
| 124 |idl_type| argument is of type IdlType, while return value is a string |
| 125 |
| 126 Args: |
| 127 idl_type: |
| 128 IdlType |
| 129 used_as_argument: |
| 130 bool, True if idl_type's raw/primitive C++ type should be returned. |
| 131 will_be_in_heap_object: |
| 132 bool, True if idl_type will be part of a possibly heap allocated |
| 133 object (e.g., appears as an element of a C++ heap vector type.) |
| 134 The C++ type of an interface type changes, if so. |
| 135 """ |
| 136 extended_attributes = extended_attributes or {} |
| 137 idl_type = idl_type.preprocessed_type |
| 138 |
| 139 # Composite types |
| 140 array_or_sequence_type = idl_type.array_or_sequence_type |
| 141 if array_or_sequence_type: |
| 142 vector_type = cpp_ptr_type('Vector', 'HeapVector', array_or_sequence_typ
e.gc_type) |
| 143 return cpp_template_type(vector_type, array_or_sequence_type.cpp_type_ar
gs(used_in_cpp_sequence=True)) |
| 144 |
| 145 # Simple types |
| 146 base_idl_type = idl_type.base_type |
| 147 |
| 148 if base_idl_type in CPP_TYPE_SAME_AS_IDL_TYPE: |
| 149 return base_idl_type |
| 150 if base_idl_type in CPP_INT_TYPES: |
| 151 return 'int' |
| 152 if base_idl_type in CPP_UNSIGNED_TYPES: |
| 153 return 'unsigned' |
| 154 if base_idl_type in CPP_SPECIAL_CONVERSION_RULES: |
| 155 return CPP_SPECIAL_CONVERSION_RULES[base_idl_type] |
| 156 |
| 157 if base_idl_type in NON_WRAPPER_TYPES: |
| 158 return 'RefPtr<%s>' % base_idl_type |
| 159 if base_idl_type in ('DOMString', 'ByteString', 'ScalarValueString'): |
| 160 if not used_as_argument: |
| 161 return 'String' |
| 162 return 'DartStringAdapter' |
| 163 |
| 164 if idl_type.is_typed_array_type and used_as_argument: |
| 165 return 'RefPtr<%s>' % base_idl_type |
| 166 if idl_type.is_callback_interface: |
| 167 return 'OwnPtr<%s>' % base_idl_type |
| 168 if idl_type.is_interface_type: |
| 169 implemented_as_class = idl_type.implemented_as |
| 170 if used_as_argument: |
| 171 return implemented_as_class + '*' |
| 172 new_type = 'Member' if used_in_cpp_sequence else 'RawPtr' |
| 173 ptr_type = cpp_ptr_type('RefPtr', new_type, idl_type.gc_type) |
| 174 return cpp_template_type(ptr_type, implemented_as_class) |
| 175 |
| 176 # Default, assume native type is a pointer with same type name as idl type |
| 177 return base_idl_type + '*' |
| 178 |
| 179 |
| 180 def cpp_type_union(idl_type, extended_attributes=None, used_as_argument=False, w
ill_be_in_heap_object=False): |
| 181 return (member_type.cpp_type for member_type in idl_type.member_types) |
| 182 |
| 183 # Allow access as idl_type.cpp_type if no arguments |
| 184 IdlType.cpp_type = property(cpp_type) |
| 185 IdlUnionType.cpp_type = property(cpp_type_union) |
| 186 IdlType.cpp_type_args = cpp_type |
| 187 IdlUnionType.cpp_type_args = cpp_type_union |
| 188 |
| 189 |
| 190 def cpp_template_type(template, inner_type): |
| 191 """Returns C++ template specialized to type, with space added if needed.""" |
| 192 if inner_type.endswith('>'): |
| 193 format_string = '{template}<{inner_type} >' |
| 194 else: |
| 195 format_string = '{template}<{inner_type}>' |
| 196 return format_string.format(template=template, inner_type=inner_type) |
| 197 |
| 198 |
| 199 def cpp_ptr_type(old_type, new_type, gc_type): |
| 200 if gc_type == 'GarbageCollectedObject': |
| 201 return new_type |
| 202 if gc_type == 'WillBeGarbageCollectedObject': |
| 203 if old_type == 'Vector': |
| 204 return 'WillBe' + new_type |
| 205 return old_type + 'WillBe' + new_type |
| 206 return old_type |
| 207 |
| 208 |
| 209 def v8_type(interface_name): |
| 210 return 'V8' + interface_name |
| 211 |
| 212 |
| 213 def dart_type(interface_name): |
| 214 return 'Dart' + str(interface_name) |
| 215 |
| 216 |
| 217 # [ImplementedAs] |
| 218 # This handles [ImplementedAs] on interface types, not [ImplementedAs] in the |
| 219 # interface being generated. e.g., given: |
| 220 # Foo.idl: interface Foo {attribute Bar bar}; |
| 221 # Bar.idl: [ImplementedAs=Zork] interface Bar {}; |
| 222 # when generating bindings for Foo, the [ImplementedAs] on Bar is needed. |
| 223 # This data is external to Foo.idl, and hence computed as global information in |
| 224 # compute_interfaces_info.py to avoid having to parse IDLs of all used interface
s. |
| 225 IdlType.implemented_as_interfaces = {} |
| 226 |
| 227 |
| 228 def implemented_as(idl_type): |
| 229 base_idl_type = idl_type.base_type |
| 230 if base_idl_type in IdlType.implemented_as_interfaces: |
| 231 return IdlType.implemented_as_interfaces[base_idl_type] |
| 232 return base_idl_type |
| 233 |
| 234 |
| 235 IdlType.implemented_as = property(implemented_as) |
| 236 |
| 237 IdlType.set_implemented_as_interfaces = classmethod( |
| 238 lambda cls, new_implemented_as_interfaces: |
| 239 cls.implemented_as_interfaces.update(new_implemented_as_interfaces)) |
| 240 |
| 241 # [GarbageCollected] |
| 242 IdlType.garbage_collected_types = set() |
| 243 |
| 244 IdlType.is_garbage_collected = property( |
| 245 lambda self: self.base_type in IdlType.garbage_collected_types) |
| 246 |
| 247 IdlType.set_garbage_collected_types = classmethod( |
| 248 lambda cls, new_garbage_collected_types: |
| 249 cls.garbage_collected_types.update(new_garbage_collected_types)) |
| 250 |
| 251 |
| 252 # [WillBeGarbageCollected] |
| 253 IdlType.will_be_garbage_collected_types = set() |
| 254 |
| 255 IdlType.is_will_be_garbage_collected = property( |
| 256 lambda self: self.base_type in IdlType.will_be_garbage_collected_types) |
| 257 |
| 258 IdlType.set_will_be_garbage_collected_types = classmethod( |
| 259 lambda cls, new_will_be_garbage_collected_types: |
| 260 cls.will_be_garbage_collected_types.update(new_will_be_garbage_collected
_types)) |
| 261 |
| 262 |
| 263 def gc_type(idl_type): |
| 264 if idl_type.is_garbage_collected: |
| 265 return 'GarbageCollectedObject' |
| 266 if idl_type.is_will_be_garbage_collected: |
| 267 return 'WillBeGarbageCollectedObject' |
| 268 return 'RefCountedObject' |
| 269 |
| 270 IdlType.gc_type = property(gc_type) |
| 271 |
| 272 |
| 273 ################################################################################ |
| 274 # Includes |
| 275 ################################################################################ |
| 276 |
| 277 def includes_for_cpp_class(class_name, relative_dir_posix): |
| 278 return set([posixpath.join('bindings', relative_dir_posix, class_name + '.h'
)]) |
| 279 |
| 280 # TODO(terry): Will we need this group header for dart:blink? |
| 281 INCLUDES_FOR_TYPE = { |
| 282 'object': set(), |
| 283 'CompareHow': set(), |
| 284 'Dictionary': set(['bindings/common/Dictionary.h']), |
| 285 'EventHandler': set(), |
| 286 'EventListener': set(), |
| 287 'HTMLCollection': set(['bindings/core/dart/DartHTMLCollection.h', |
| 288 'core/dom/ClassCollection.h', |
| 289 'core/dom/TagCollection.h', |
| 290 'core/html/HTMLCollection.h', |
| 291 'core/html/HTMLFormControlsCollection.h', |
| 292 'core/html/HTMLTableRowsCollection.h']), |
| 293 'MediaQueryListListener': set(['core/css/MediaQueryListListener.h']), |
| 294 'NodeList': set(['bindings/core/dart/DartNodeList.h', |
| 295 'core/dom/NameNodeList.h', |
| 296 'core/dom/NodeList.h', |
| 297 'core/dom/StaticNodeList.h', |
| 298 'core/html/LabelsNodeList.h']), |
| 299 'Promise': set(), |
| 300 'SerializedScriptValue': set(), |
| 301 'ScriptValue': set(['bindings/dart/DartScriptValue.h']), |
| 302 } |
| 303 |
| 304 |
| 305 def includes_for_type(idl_type): |
| 306 idl_type = idl_type.preprocessed_type |
| 307 |
| 308 # Composite types |
| 309 array_or_sequence_type = idl_type.array_or_sequence_type |
| 310 if array_or_sequence_type: |
| 311 return includes_for_type(array_or_sequence_type) |
| 312 |
| 313 # Simple types |
| 314 base_idl_type = idl_type.base_type |
| 315 if base_idl_type in INCLUDES_FOR_TYPE: |
| 316 return INCLUDES_FOR_TYPE[base_idl_type] |
| 317 if idl_type.is_basic_type: |
| 318 return set() |
| 319 if idl_type.is_typed_array_type: |
| 320 # Typed array factory methods are already provided by DartUtilities.h. |
| 321 return set([]) |
| 322 if base_idl_type.endswith('ConstructorConstructor'): |
| 323 # FIXME: rename to NamedConstructor |
| 324 # FIXME: replace with a [NamedConstructorAttribute] extended attribute |
| 325 # Ending with 'ConstructorConstructor' indicates a named constructor, |
| 326 # and these do not have header files, as they are part of the generated |
| 327 # bindings for the interface |
| 328 return set() |
| 329 if base_idl_type.endswith('Constructor'): |
| 330 # FIXME: replace with a [ConstructorAttribute] extended attribute |
| 331 base_idl_type = idl_type.constructor_type_name |
| 332 return set(['Dart%s.h' % base_idl_type]) |
| 333 |
| 334 IdlType.includes_for_type = property(includes_for_type) |
| 335 IdlUnionType.includes_for_type = property( |
| 336 lambda self: set.union(*[includes_for_type(member_type) |
| 337 for member_type in self.member_types])) |
| 338 |
| 339 |
| 340 def add_includes_for_type(idl_type): |
| 341 includes.update(idl_type.includes_for_type) |
| 342 |
| 343 IdlType.add_includes_for_type = add_includes_for_type |
| 344 IdlUnionType.add_includes_for_type = add_includes_for_type |
| 345 |
| 346 |
| 347 def includes_for_interface(interface_name): |
| 348 return IdlType(interface_name).includes_for_type |
| 349 |
| 350 |
| 351 def add_includes_for_interface(interface_name): |
| 352 includes.update(includes_for_interface(interface_name)) |
| 353 |
| 354 |
| 355 ################################################################################ |
| 356 # Dart -> C++ |
| 357 ################################################################################ |
| 358 |
| 359 # TODO(terry): Need to fix to handle getter/setters for onEvent. |
| 360 DART_FIX_ME = 'DART_UNIMPLEMENTED(/* Conversion unimplemented*/);' |
| 361 |
| 362 # For a given IDL type, the DartHandle to C++ conversion. |
| 363 DART_TO_CPP_VALUE = { |
| 364 # Basic |
| 365 'Date': 'DartUtilities::dartToDate(args, {index}, exception)', |
| 366 'DOMString': 'DartUtilities::dartToString{null_check}(args, {index}, excepti
on, {auto_scope})', |
| 367 'ByteString': 'DartUtilities::dartToByteString{null_check}(args, {index}, ex
ception, {auto_scope})', |
| 368 'ScalarValueString': 'DartUtilities::dartToScalarValueString{null_check}(arg
s, {index}, exception, {auto_scope})', |
| 369 'boolean': 'DartUtilities::dartToBool{null_check}(args, {index}, exception)'
, |
| 370 'float': 'static_cast<float>(DartUtilities::dartToDouble(args, {index}, exce
ption))', |
| 371 'unrestricted float': 'static_cast<float>(DartUtilities::dartToDouble(args,
{index}, exception))', |
| 372 'double': 'DartUtilities::dartToDouble(args, {index}, exception)', |
| 373 'unrestricted double': 'DartUtilities::dartToDouble(args, {index}, exception
)', |
| 374 # FIXME(vsm): Inconsistent with V8. |
| 375 'byte': 'DartUtilities::dartToUnsigned(args, {index}, exception)', |
| 376 'octet': 'DartUtilities::dartToUnsigned(args, {index}, exception)', |
| 377 'short': 'DartUtilities::dartToInt(args, {index}, exception)', |
| 378 'unsigned short': 'DartUtilities::dartToUnsigned(args, {index}, exception)', |
| 379 'long': 'DartUtilities::dartToInt(args, {index}, exception)', |
| 380 'unsigned long': 'DartUtilities::dartToUnsignedLongLong(args, {index}, excep
tion)', |
| 381 'long long': 'DartUtilities::dartToLongLong(args, {index}, exception)', |
| 382 'unsigned long long': 'DartUtilities::dartToUnsignedLongLong(args, {index},
exception)', |
| 383 # Interface types |
| 384 'CompareHow': 'static_cast<Range::CompareHow>(0) /* FIXME, DART_TO_CPP_VALUE
[CompareHow] */', |
| 385 'Dictionary': 'DartUtilities::dartToDictionary{null_check}(args, {index}, ex
ception)', |
| 386 'EventTarget': '0 /* FIXME, DART_TO_CPP_VALUE[EventTarget] */', |
| 387 'MediaQueryListListener': 'nullptr /* FIXME, DART_TO_CPP_VALUE[MediaQueryLis
tener] */', |
| 388 'NodeFilter': 'nullptr /* FIXME, DART_TO_CPP_VALUE[NodeFilter] */', |
| 389 'Promise': 'nullptr /* FIXME, DART_TO_CPP_VALUE[Promise] */', |
| 390 'SerializedScriptValue': 'nullptr /* FIXME, DART_TO_CPP_VALUE[SerializedScri
ptValue] */', |
| 391 'ScriptValue': 'DartUtilities::dartToScriptValue{null_check}(args, {index})'
, |
| 392 # FIXME(vsm): Why don't we have an entry for Window? V8 does. |
| 393 # I think I removed this as the Window object is more special in V8 - it's t
he |
| 394 # global context as well. Do we need to special case it? |
| 395 'XPathNSResolver': 'nullptr /* FIXME, DART_TO_CPP_VALUE[XPathNSResolver] */'
, |
| 396 # FIXME(vsm): This is an enum type (defined in StorageQuota.idl). |
| 397 # We should handle it automatically, but map to a String for now. |
| 398 'StorageType': 'DartUtilities::dartToString(args, {index}, exception, {auto_
scope})', |
| 399 } |
| 400 |
| 401 |
| 402 def dart_value_to_cpp_value(idl_type, interface_extended_attributes, extended_at
tributes, variable_name, |
| 403 null_check, index, auto_scope=True): |
| 404 # Composite types |
| 405 array_or_sequence_type = idl_type.array_or_sequence_type |
| 406 if array_or_sequence_type: |
| 407 return dart_value_to_cpp_value_array_or_sequence(array_or_sequence_type,
variable_name, index) |
| 408 |
| 409 # Simple types |
| 410 idl_type = idl_type.preprocessed_type |
| 411 add_includes_for_type(idl_type) |
| 412 base_idl_type = idl_type.base_type |
| 413 |
| 414 if 'EnforceRange' in extended_attributes: |
| 415 arguments = ', '.join([variable_name, 'EnforceRange', 'exceptionState']) |
| 416 elif idl_type.is_integer_type: # NormalConversion |
| 417 arguments = ', '.join([variable_name, 'es']) |
| 418 else: |
| 419 arguments = variable_name |
| 420 |
| 421 if base_idl_type in DART_TO_CPP_VALUE: |
| 422 cpp_expression_format = DART_TO_CPP_VALUE[base_idl_type] |
| 423 elif idl_type.is_typed_array_type: |
| 424 # FIXME(vsm): V8 generates a type check here as well. Do we need one? |
| 425 # FIXME(vsm): When do we call the externalized version? E.g., see |
| 426 # bindings/dart/custom/DartWaveShaperNodeCustom.cpp - it calls |
| 427 # DartUtilities::dartToExternalizedArrayBufferView instead. |
| 428 # V8 always converts null here |
| 429 cpp_expression_format = ('DartUtilities::dartTo{idl_type}WithNullCheck(a
rgs, {index}, exception)') |
| 430 elif idl_type.is_callback_interface: |
| 431 cpp_expression_format = ('Dart{idl_type}::create{null_check}(args, {inde
x}, exception)') |
| 432 else: |
| 433 cpp_expression_format = ('Dart{idl_type}::toNative{null_check}(args, {in
dex}, exception)') |
| 434 |
| 435 # We allow the calling context to force a null check to handle |
| 436 # some cases that require calling context info. V8 handles all |
| 437 # of this differently, and we may wish to reconsider this approach |
| 438 null_check = 'WithNullCheck' \ |
| 439 if null_check or allow_null(idl_type, interface_extended_attributes, ext
ended_attributes) else '' |
| 440 return cpp_expression_format.format(null_check=null_check, |
| 441 arguments=arguments, |
| 442 index=index, |
| 443 idl_type=base_idl_type, |
| 444 auto_scope=DartUtilities.bool_to_cpp(aut
o_scope)) |
| 445 |
| 446 |
| 447 def dart_value_to_cpp_value_array_or_sequence(array_or_sequence_type, variable_n
ame, index): |
| 448 # Index is None for setters, index (starting at 0) for method arguments, |
| 449 # and is used to provide a human-readable exception message |
| 450 |
| 451 if index is None: |
| 452 index = 0 # special case, meaning "setter" |
| 453 # else: |
| 454 # index += 1 # human-readable index |
| 455 if (array_or_sequence_type.is_interface_type and |
| 456 array_or_sequence_type.name != 'Dictionary'): |
| 457 this_cpp_type = array_or_sequence_type.cpp_type |
| 458 ref_ptr_type = 'Member' if array_or_sequence_type.is_will_be_garbage_col
lected else 'RefPtr' |
| 459 # FIXME(vsm): We're not using ref_ptr_type.... |
| 460 expression_format = 'DartUtilities::toNativeVector<{cpp_type} >(args, {i
ndex}, {variable_name}, exception)' |
| 461 add_includes_for_type(array_or_sequence_type) |
| 462 else: |
| 463 ref_ptr_type = None |
| 464 this_cpp_type = array_or_sequence_type.cpp_type |
| 465 expression_format = 'DartUtilities::toNativeVector<{cpp_type}>(args, {in
dex}, {variable_name}, exception)' |
| 466 expression = expression_format.format(array_or_sequence_type=array_or_sequen
ce_type.name, |
| 467 cpp_type=this_cpp_type, index=index, r
ef_ptr_type=ref_ptr_type, |
| 468 variable_name=variable_name) |
| 469 return expression |
| 470 |
| 471 |
| 472 def dart_value_to_local_cpp_value(idl_type, interface_extended_attributes, exten
ded_attributes, |
| 473 variable_name, null_check, index=None, auto_sc
ope=True): |
| 474 """Returns an expression that converts a Dart value to a C++ value as a loca
l value.""" |
| 475 idl_type = idl_type.preprocessed_type |
| 476 |
| 477 cpp_value = dart_value_to_cpp_value( |
| 478 idl_type, interface_extended_attributes, extended_attributes, |
| 479 variable_name, null_check, index, auto_scope) |
| 480 |
| 481 return cpp_value |
| 482 |
| 483 IdlType.dart_value_to_local_cpp_value = dart_value_to_local_cpp_value |
| 484 IdlUnionType.dart_value_to_local_cpp_value = dart_value_to_local_cpp_value |
| 485 |
| 486 |
| 487 # Insure that we don't use C++ reserved names. Today on default is a problem. |
| 488 def check_reserved_name(name): |
| 489 return 'default_value' if (name == 'default') else name |
| 490 |
| 491 |
| 492 ################################################################################ |
| 493 # C++ -> V8 |
| 494 ################################################################################ |
| 495 |
| 496 def preprocess_idl_type(idl_type): |
| 497 if idl_type.is_enum: |
| 498 # Enumerations are internally DOMStrings |
| 499 return IdlType('DOMString') |
| 500 if (idl_type.name == 'Any' or idl_type.is_callback_function): |
| 501 return IdlType('ScriptValue') |
| 502 return idl_type |
| 503 |
| 504 IdlType.preprocessed_type = property(preprocess_idl_type) |
| 505 IdlUnionType.preprocessed_type = property(preprocess_idl_type) |
| 506 |
| 507 |
| 508 def preprocess_idl_type_and_value(idl_type, cpp_value, extended_attributes): |
| 509 """Returns IDL type and value, with preliminary type conversions applied.""" |
| 510 idl_type = idl_type.preprocessed_type |
| 511 if idl_type.name == 'Promise': |
| 512 idl_type = IdlType('ScriptValue') |
| 513 # FIXME(vsm): V8 maps 'long long' and 'unsigned long long' to double |
| 514 # as they are not representable in ECMAScript. Should we do the same? |
| 515 |
| 516 # HTML5 says that unsigned reflected attributes should be in the range |
| 517 # [0, 2^31). When a value isn't in this range, a default value (or 0) |
| 518 # should be returned instead. |
| 519 extended_attributes = extended_attributes or {} |
| 520 if ('Reflect' in extended_attributes and |
| 521 idl_type.base_type in ['unsigned long', 'unsigned short']): |
| 522 cpp_value = cpp_value.replace('getUnsignedIntegralAttribute', |
| 523 'getIntegralAttribute') |
| 524 cpp_value = 'std::max(0, %s)' % cpp_value |
| 525 return idl_type, cpp_value |
| 526 |
| 527 |
| 528 def dart_conversion_type(idl_type, extended_attributes): |
| 529 """Returns Dart conversion type, adding any additional includes. |
| 530 |
| 531 The Dart conversion type is used to select the C++ -> Dart conversion functi
on |
| 532 or setDart*ReturnValue function; it can be an idl_type, a cpp_type, or a |
| 533 separate name for the type of conversion (e.g., 'DOMWrapper'). |
| 534 """ |
| 535 extended_attributes = extended_attributes or {} |
| 536 |
| 537 # Composite types |
| 538 array_or_sequence_type = idl_type.array_or_sequence_type |
| 539 if array_or_sequence_type: |
| 540 if array_or_sequence_type.is_interface_type: |
| 541 add_includes_for_type(array_or_sequence_type) |
| 542 return 'array' |
| 543 |
| 544 # Simple types |
| 545 base_idl_type = idl_type.base_type |
| 546 # Basic types, without additional includes |
| 547 if base_idl_type in CPP_INT_TYPES or base_idl_type == 'long long': |
| 548 return 'int' |
| 549 if base_idl_type in CPP_UNSIGNED_TYPES or base_idl_type == 'unsigned long lo
ng': |
| 550 return 'unsigned' |
| 551 if base_idl_type == 'DOMString': |
| 552 if 'TreatReturnedNullStringAs' not in extended_attributes: |
| 553 return 'DOMString' |
| 554 treat_returned_null_string_as = extended_attributes['TreatReturnedNullSt
ringAs'] |
| 555 if treat_returned_null_string_as == 'Null': |
| 556 return 'StringOrNull' |
| 557 if treat_returned_null_string_as == 'Undefined': |
| 558 return 'StringOrUndefined' |
| 559 raise 'Unrecognized TreatReturnNullStringAs value: "%s"' % treat_returne
d_null_string_as |
| 560 if idl_type.is_basic_type or base_idl_type == 'ScriptValue': |
| 561 return base_idl_type |
| 562 |
| 563 # Data type with potential additional includes |
| 564 add_includes_for_type(idl_type) |
| 565 if base_idl_type in DART_SET_RETURN_VALUE: # Special dartSetReturnValue tre
atment |
| 566 return base_idl_type |
| 567 |
| 568 # Typed arrays don't have special Dart* classes for Dart. |
| 569 if idl_type.is_typed_array_type: |
| 570 if base_idl_type == 'ArrayBuffer': |
| 571 return 'ArrayBuffer' |
| 572 else: |
| 573 return 'TypedList' |
| 574 |
| 575 # Pointer type |
| 576 return 'DOMWrapper' |
| 577 |
| 578 IdlType.dart_conversion_type = dart_conversion_type |
| 579 |
| 580 |
| 581 DART_SET_RETURN_VALUE = { |
| 582 'boolean': 'Dart_SetBooleanReturnValue(args, {cpp_value})', |
| 583 'int': 'DartUtilities::setDartIntegerReturnValue(args, {cpp_value})', |
| 584 'unsigned': 'DartUtilities::setDartUnsignedLongLongReturnValue(args, {cpp_va
lue})', |
| 585 'DOMString': 'DartUtilities::setDartStringReturnValue(args, {cpp_value}, {au
to_scope})', |
| 586 # FIXME(terry): Need to handle checking to byte values > 255 throwing except
ion. |
| 587 'ByteString': 'DartUtilities::setDartByteStringReturnValue(args, {cpp_value}
, {auto_scope})', |
| 588 # FIXME(terry): Need to make valid unicode; match UTF-16 to U+FFFD REPLACEM
ENT CHARACTER. |
| 589 'ScalarValueString': 'DartUtilities::setDartScalarValueStringReturnValue(arg
s, {cpp_value}, {auto_scope})', |
| 590 # [TreatNullReturnValueAs] |
| 591 'StringOrNull': 'DartUtilities::setDartStringReturnValueWithNullCheck(args,
{cpp_value}, {auto_scope})', |
| 592 # FIXME(vsm): How should we handle undefined? |
| 593 'StringOrUndefined': 'DartUtilities::setDartStringReturnValue(args, {cpp_val
ue}, {auto_scope})', |
| 594 'void': '', |
| 595 # We specialize these as well in Dart. |
| 596 'float': 'Dart_SetDoubleReturnValue(args, {cpp_value})', |
| 597 'unrestricted float': 'Dart_SetDoubleReturnValue(args, {cpp_value})', |
| 598 'double': 'Dart_SetDoubleReturnValue(args, {cpp_value})', |
| 599 'unrestricted double': 'Dart_SetDoubleReturnValue(args, {cpp_value})', |
| 600 # No special function, but instead convert value to Dart_Handle |
| 601 # and then use general Dart_SetReturnValue. |
| 602 'array': 'Dart_SetReturnValue(args, {cpp_value})', |
| 603 'Date': 'Dart_SetReturnValue(args, {cpp_value})', |
| 604 'EventHandler': DART_FIX_ME, |
| 605 'ScriptValue': 'Dart_SetReturnValue(args, {cpp_value})', |
| 606 'SerializedScriptValue': DART_FIX_ME, |
| 607 # DOMWrapper |
| 608 # TODO(terry): Remove ForMainWorld stuff. |
| 609 'DOMWrapperForMainWorld': DART_FIX_ME, |
| 610 # FIXME(vsm): V8 has a fast path. Do we? |
| 611 'DOMWrapperFast': 'Dart{type_name}::returnToDart(args, WTF::getPtr({cpp_valu
e}), {auto_scope})', |
| 612 'DOMWrapperDefault': 'Dart{type_name}::returnToDart(args, {cpp_value}, {auto
_scope})', |
| 613 # Typed arrays don't have special Dart* classes for Dart. |
| 614 'ArrayBuffer': 'Dart_SetReturnValue(args, DartUtilities::arrayBufferToDart({
cpp_value}))', |
| 615 'TypedList': 'Dart_SetReturnValue(args, DartUtilities::arrayBufferViewToDart
({cpp_value}))', |
| 616 'Dictionary': DART_FIX_ME, |
| 617 } |
| 618 |
| 619 |
| 620 def dart_set_return_value(idl_type, cpp_value, |
| 621 extended_attributes=None, script_wrappable='', |
| 622 release=False, for_main_world=False, |
| 623 auto_scope=True): |
| 624 """Returns a statement that converts a C++ value to a Dart value and sets it
as a return value. |
| 625 |
| 626 """ |
| 627 def dom_wrapper_conversion_type(): |
| 628 if not script_wrappable: |
| 629 return 'DOMWrapperDefault' |
| 630 if for_main_world: |
| 631 return 'DOMWrapperForMainWorld' |
| 632 return 'DOMWrapperFast' |
| 633 |
| 634 idl_type, cpp_value = preprocess_idl_type_and_value(idl_type, cpp_value, ext
ended_attributes) |
| 635 this_dart_conversion_type = idl_type.dart_conversion_type(extended_attribute
s) |
| 636 # SetReturn-specific overrides |
| 637 if this_dart_conversion_type in ['Date', 'EventHandler', 'ScriptValue', 'Ser
ializedScriptValue', 'array']: |
| 638 # Convert value to Dart and then use general Dart_SetReturnValue |
| 639 # FIXME(vsm): Why do we differ from V8 here? It doesn't have a |
| 640 # creation_context. |
| 641 creation_context = '' |
| 642 if this_dart_conversion_type == 'array': |
| 643 # FIXME: This is not right if the base type is a primitive, DOMStrin
g, etc. |
| 644 # What is the right check for base type? |
| 645 if idl_type.base_type not in DART_TO_CPP_VALUE: |
| 646 creation_context = '<Dart%s>' % idl_type.base_type |
| 647 |
| 648 cpp_value = idl_type.cpp_value_to_dart_value(cpp_value, creation_context
=creation_context, |
| 649 extended_attributes=extende
d_attributes) |
| 650 if this_dart_conversion_type == 'DOMWrapper': |
| 651 this_dart_conversion_type = dom_wrapper_conversion_type() |
| 652 |
| 653 format_string = DART_SET_RETURN_VALUE[this_dart_conversion_type] |
| 654 |
| 655 if release: |
| 656 cpp_value = '%s.release()' % cpp_value |
| 657 statement = format_string.format(cpp_value=cpp_value, |
| 658 type_name=idl_type.name, |
| 659 script_wrappable=script_wrappable, |
| 660 auto_scope=DartUtilities.bool_to_cpp(auto_s
cope)) |
| 661 return statement |
| 662 |
| 663 |
| 664 def dart_set_return_value_union(idl_type, cpp_value, extended_attributes=None, |
| 665 script_wrappable='', release=False, for_main_world
=False, |
| 666 auto_scope=True): |
| 667 """ |
| 668 release: can be either False (False for all member types) or |
| 669 a sequence (list or tuple) of booleans (if specified individually). |
| 670 """ |
| 671 |
| 672 return [ |
| 673 # FIXME(vsm): Why do we use 'result' instead of cpp_value as V8? |
| 674 member_type.dart_set_return_value('result' + str(i), |
| 675 extended_attributes, |
| 676 script_wrappable, |
| 677 release and release[i], |
| 678 for_main_world, |
| 679 auto_scope) |
| 680 for i, member_type in |
| 681 enumerate(idl_type.member_types)] |
| 682 |
| 683 IdlType.dart_set_return_value = dart_set_return_value |
| 684 IdlUnionType.dart_set_return_value = dart_set_return_value_union |
| 685 |
| 686 IdlType.release = property(lambda self: self.is_interface_type) |
| 687 IdlUnionType.release = property( |
| 688 lambda self: [member_type.is_interface_type |
| 689 for member_type in self.member_types]) |
| 690 |
| 691 |
| 692 CPP_VALUE_TO_DART_VALUE = { |
| 693 # Built-in types |
| 694 # FIXME(vsm): V8 uses DateOrNull - do we need a null check? |
| 695 'Date': 'DartUtilities::dateToDart({cpp_value})', |
| 696 'DOMString': 'DartUtilities::stringToDartString({cpp_value})', |
| 697 'boolean': 'DartUtilities::boolToDart({cpp_value})', |
| 698 'int': 'DartUtilities::intToDart({cpp_value})', |
| 699 'unsigned': 'DartUtilities::unsignedLongLongToDart({cpp_value})', |
| 700 'float': 'DartUtilities::doubleToDart({cpp_value})', |
| 701 'unrestricted float': 'DartUtilities::doubleToDart({cpp_value})', |
| 702 'double': 'DartUtilities::doubleToDart({cpp_value})', |
| 703 'unrestricted double': 'DartUtilities::doubleToDart({cpp_value})', |
| 704 # FIXME(vsm): Dart_Null? |
| 705 'void': '', |
| 706 # Special cases |
| 707 'EventHandler': '-----OOPS TO DART-EVENT---', |
| 708 # We need to generate the NullCheck version in some cases. |
| 709 'ScriptValue': 'DartUtilities::scriptValueToDart({cpp_value})', |
| 710 'SerializedScriptValue': 'DartUtilities::serializedScriptValueToDart({cpp_va
lue})', |
| 711 # General |
| 712 'array': 'DartDOMWrapper::vectorToDart{creation_context}({cpp_value})', |
| 713 'DOMWrapper': 'Dart{idl_type}::toDart({cpp_value})', |
| 714 } |
| 715 |
| 716 |
| 717 def cpp_value_to_dart_value(idl_type, cpp_value, creation_context='', extended_a
ttributes=None): |
| 718 """Returns an expression that converts a C++ value to a Dart value.""" |
| 719 # the isolate parameter is needed for callback interfaces |
| 720 idl_type, cpp_value = preprocess_idl_type_and_value(idl_type, cpp_value, ext
ended_attributes) |
| 721 this_dart_conversion_type = idl_type.dart_conversion_type(extended_attribute
s) |
| 722 format_string = CPP_VALUE_TO_DART_VALUE[this_dart_conversion_type] |
| 723 statement = format_string.format( |
| 724 cpp_value=cpp_value, creation_context=creation_context, |
| 725 idl_type=idl_type.base_type) |
| 726 return statement |
| 727 |
| 728 IdlType.cpp_value_to_dart_value = cpp_value_to_dart_value |
| 729 |
| 730 |
| 731 # Override idl_type.name to not suffix orNull to the name, in Dart we always |
| 732 # test for null e.g., |
| 733 # |
| 734 # bool isNull = false; |
| 735 # TYPE* result = receiver->GETTER(isNull); |
| 736 # if (isNull) |
| 737 # return; |
| 738 # |
| 739 def dart_name(idl_type): |
| 740 """Return type name. |
| 741 |
| 742 http://heycam.github.io/webidl/#dfn-type-name |
| 743 """ |
| 744 base_type = idl_type.base_type |
| 745 base_type_name = TYPE_NAMES.get(base_type, base_type) |
| 746 if idl_type.is_array: |
| 747 return base_type_name + 'Array' |
| 748 if idl_type.is_sequence: |
| 749 return base_type_name + 'Sequence' |
| 750 return base_type_name |
| 751 |
| 752 IdlType.name = property(dart_name) |
| 753 IdlUnionType.name = property(dart_name) |
| 754 |
| 755 |
| 756 def typechecked_interface(extended_attributes): |
| 757 return ('TypeChecking' in extended_attributes and\ |
| 758 DartUtilities.extended_attribute_value_contains(extended_attributes[
'TypeChecking'], 'Interface')) |
| 759 |
| 760 |
| 761 def typechecked_argument(idl_type, interface_extended_attributes, extended_attri
butes): |
| 762 return (idl_type.is_wrapper_type and |
| 763 (typechecked_interface(interface_extended_attributes) or |
| 764 (typechecked_interface(extended_attributes)))) |
| 765 |
| 766 |
| 767 # If True use the WithNullCheck version when converting. |
| 768 def allow_null(idl_type, interface_extended_attributes, extended_attributes): |
| 769 if idl_type.base_type in ('DOMString', 'ByteString', 'ScalarValueString'): |
| 770 # This logic is in cpp_types in v8_types.py, since they handle |
| 771 # this using the V8StringResource type. We handle it here |
| 772 if (extended_attributes.get('TreatNullAs') == 'NullString' or |
| 773 extended_attributes.get('TreatUndefinedAs') == 'NullString'): |
| 774 return True |
| 775 |
| 776 if extended_attributes.get('Default') == 'NullString': |
| 777 return True |
| 778 |
| 779 if extended_attributes.get('Default') == 'Undefined': |
| 780 return True |
| 781 |
| 782 if idl_type.is_nullable: |
| 783 return True |
| 784 |
| 785 return False |
| 786 else: |
| 787 # This logic is implemented in the methods.cpp template in V8 |
| 788 if (idl_type.is_nullable or |
| 789 (not typechecked_argument(idl_type, interface_extended_attributes, ex
tended_attributes))): |
| 790 return True |
| 791 |
| 792 if extended_attributes.get('Default') == 'Undefined': |
| 793 return True |
| 794 |
| 795 return False |
OLD | NEW |