Flutter Engine
The Flutter Engine
generator.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2# Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
3# for details. All rights reserved. Use of this source code is governed by a
4# BSD-style license that can be found in the LICENSE file.
5"""This module provides shared functionality for systems to generate
6Dart APIs from the IDL database."""
7
8import copy
9import json
10import monitored
11import os
12import re
13from functools import cmp_to_key
14from itertools import zip_longest
15from htmlrenamer import custom_html_constructors, html_interface_renames, \
16 typed_array_renames
17
18_pure_interfaces = monitored.Set('generator._pure_interfaces', [
19 'AbstractWorker',
20 'CanvasPath',
21 'ChildNode',
22 'DocumentAnimation',
23 'DocumentFontFaceSet',
24 'DocumentFullscreen',
25 'DocumentXPathEvaluator',
26 'ElementAnimation',
27 'ElementFullscreen',
28 'EventListener',
29 'GlobalEventHandlers',
30 'ImageBitmapFactories',
31 'MediaQueryListListener',
32 'MouseEventHitRegion',
33 'MutationCallback',
34 'NavigatorCPU',
35 'NavigatorEvents',
36 'NavigatorID',
37 'NavigatorLanguage',
38 'NavigatorOnLine',
39 'ParentNode',
40 'SVGDocument',
41 'SVGExternalResourcesRequired',
42 'SVGFilterPrimitiveStandardAttributes',
43 'SVGFitToViewBox',
44 'SVGTests',
45 'SVGURIReference',
46 'SVGZoomAndPan',
47 'TimeoutHandler',
48 'URLUtils',
49 'URLUtilsReadOnly',
50 'WebGLRenderingContextBase',
51 'WindowBase64',
52 'WindowEventHandlers',
53 'WindowImageBitmapFactories',
54 'WindowPagePopup',
55 'WindowTimers',
56])
57
58_safe_interfaces = monitored.Set(
59 'generator._safe_interfaces',
60 [
61 'double',
62 'Float32Array',
63 'Float64Array',
64 'Int8Array',
65 'Int16Array',
66 'Int32Array',
67 'Uint8Array',
68 'Uint8ClampedArray',
69 'Uint16Array',
70 'Uint32Array',
71 'ArrayBufferView',
72 'ArrayBuffer',
73 'SourceBuffer', # IDL lies about this class being a pure interface.
74 'Console', # this one is a bit of a hack as our console implementation
75 # in dart:html is non-standard for legacy reasons.
76 'AudioContext',
77 'AudioSourceNode',
78 'WebGLVertexArrayObjectOES', # Added a polyfill for this.
79 # Types where we can get access to the prototype easily enough.
80 # We might consider in the future treating these are regular interface types.
81 'StereoPannerNode',
82 'PannerNode',
83 'AudioNode',
84 'FontFaceSet',
85 'MemoryInfo',
86 'ConsoleBase',
87 'Geolocation',
88 'Animation',
89 'SourceBufferList',
90 'GamepadList',
91
92 # The following classes are enabled just to get the build to go.
93 # SpeechRecognitionResultList isn't really allowed but the codegen creates
94 # invalid output otherwise.
95 'SpeechRecognitionResultList',
96 'SQLResultSetRowList',
97 ])
98
99# These are interfaces that we have to treat as safe for dart2js and dartium
100# but going in dev compiler we should not treat as safe as these classes
101# really aren't guaranteed to have a stable interface name.
102_safe_interfaces_legacy = monitored.Set('generator._safe_interfaces_legacy', [
103 'ANGLEInstancedArrays',
104 'Bluetooth',
105 'Body',
106 'NonDocumentTypeChildNode',
107 'CHROMIUMSubscribeUniform',
108 'CHROMIUMValuebuffer',
109 'GeofencingRegion',
110 'Coordinates',
111 'DOMFileSystem',
112 'DirectoryEntry',
113 'DOMFileSystemSync',
114 'Entry',
115 'Database',
116 'DeprecatedStorageInfo',
117 'DeprecatedStorageQuota',
118 'DeviceAcceleration',
119 'DeviceRotationRate',
120 'DirectoryReader',
121 'EntrySync',
122 'DirectoryEntrySync',
123 'DirectoryReaderSync',
124 'NonElementParentNode',
125 'EXTBlendMinMax',
126 'EXTFragDepth',
127 'EXTShaderTextureLOD',
128 'EXTTextureFilterAnisotropic',
129 'EXTsRGB',
130 'EffectModel',
131 'FileEntry',
132 'FileEntrySync',
133 'FileWriter',
134 'FileWriterSync',
135 'FontFaceSetLoadEvent',
136 'Geofencing',
137 'Geoposition',
138 'Iterator',
139 'MediaDeviceInfo',
140 'MediaStreamTrackEvent',
141 'Metadata',
142 'NavigatorStorageUtils',
143 'StorageQuota',
144 'NavigatorUserMediaError',
145 'OESElementIndexUint',
146 'OESStandardDerivatives',
147 'OESTextureFloat',
148 'OESTextureFloatLinear',
149 'OESTextureHalfFloat',
150 'OESTextureHalfFloatLinear',
151 'OESVertexArrayObject',
152 'PagePopupController',
153 'PluginPlaceholderElement',
154 'PositionError',
155 'RTCDTMFSender',
156 'RTCDataChannel',
157 'RTCDataChannelEvent',
158 'RTCStatsReport',
159 'RTCStatsResponse',
160 'ReadableByteStreamReader',
161 'ReadableStreamReader',
162 'ResourceProgressEvent',
163 'SQLError',
164 'SQLResultSet',
165 'SQLTransaction',
166 'SharedArrayBuffer',
167 'SourceInfo',
168 'SpeechRecognitionAlternative',
169 'SpeechRecognitionResult',
170 'SpeechSynthesis',
171 'SpeechSynthesisVoice',
172 'StorageInfo',
173 'StyleMedia',
174 'WebGL2RenderingContextBase',
175 'WebGLCompressedTextureATC',
176 'WebGLCompressedTextureETC1',
177 'WebGLCompressedTexturePVRTC',
178 'WebGLCompressedTextureS3TC',
179 'WebGLDebugRendererInfo',
180 'WebGLDebugShaders',
181 'WebGLDepthTexture',
182 'WebGLDrawBuffers',
183 'WebGLLoseContext',
184 'WorkerConsole',
185 'WorkerPerformance',
186 'XPathNSResolver',
187])
188
189# Classes we should just suppress?
190# SpeechGrammarList and friends
191
192
193def IsPureInterface(interface_name, database):
194 if (interface_name in _pure_interfaces):
195 return True
196 if (interface_name in _safe_interfaces or
197 interface_name in _safe_interfaces_legacy or
198 database.HasInterface(interface_name)):
199 return False
200
201 interface = database.GetInterface(interface_name)
202
203 if 'Constructor' in interface.ext_attrs:
204 return False
205
206 return interface.is_no_interface_object
207
208
209#
210# Classes which have native constructors but which we are suppressing because
211# they are not cross-platform.
212#
213_suppressed_native_constructors = monitored.Set(
214 'generator._suppressed_native_constructors', [
215 'DocumentFragment',
216 'Range',
217 'Text',
218 ])
219
220_custom_types = monitored.Set('generator._custom_types',
221 list(typed_array_renames.keys()))
222
223
224def IsCustomType(interface_name):
225 return interface_name in _custom_types
226
227
228_methods_with_named_formals = monitored.Set(
229 'generator._methods_with_named_formals', [
230 'DirectoryEntry.getDirectory',
231 'DirectoryEntry.getFile',
232 'Entry.copyTo',
233 'Entry.moveTo',
234 'HTMLInputElement.setRangeText',
235 'HTMLTextAreaElement.setRangeText',
236 'XMLHttpRequest.open',
237 ])
238
239
240def hasNamedFormals(full_name):
241 return full_name in _methods_with_named_formals
242
243
244def ReturnValueConversionHack(idl_type, value, interface_name):
245 if idl_type == 'SVGMatrix':
246 return '%sTearOff::create(%s)' % (idl_type, value)
247 elif ((idl_type == 'SVGAngle' and interface_name != 'SVGAnimatedAngle') or
248 (idl_type == 'SVGTransform' and interface_name == 'SVGSVGElement')):
249 # Somewhere in the IDL it probably specifies whether we need to call
250 # create or not.
251 return 'SVGPropertyTearOff<%s>::create(%s)' % (idl_type, value)
252
253 return value
254
255
256#
257# Renames for attributes that have names that are not legal Dart names.
258#
259_dart_attribute_renames = monitored.Dict('generator._dart_attribute_renames', {
260 'default': 'defaultValue',
261})
262
263#
264# Interface version of the DOM needs to delegate typed array constructors to a
265# factory provider.
266#
267interface_factories = monitored.Dict('generator.interface_factories', {})
268
269#
270# Custom native specs for the dart2js dom.
271#
272_dart2js_dom_custom_native_specs = monitored.Dict(
273 'generator._dart2js_dom_custom_native_specs',
274 {
275
276 # Nodes with different tags in different browsers can be listed as multiple
277 # tags here provided there is not conflict in usage (e.g. browser X has tag
278 # T and no other browser has tag T).
279 'AnalyserNode':
280 'AnalyserNode,RealtimeAnalyserNode',
281 'AudioContext':
282 'AudioContext,webkitAudioContext',
283 'ChannelMergerNode':
284 'ChannelMergerNode,AudioChannelMerger',
285 'ChannelSplitterNode':
286 'ChannelSplitterNode,AudioChannelSplitter',
287 'DOMRect':
288 'ClientRect,DOMRect',
289 'DOMRectList':
290 'ClientRectList,DOMRectList',
291 'CSSStyleDeclaration':
292 # IE Firefox
293 'CSSStyleDeclaration,MSStyleCSSProperties,CSS2Properties',
294 'ApplicationCache':
295 'ApplicationCache,DOMApplicationCache,OfflineResourceList',
296 'DirectoryEntry':
297 #Chrome Edge/Opera
298 'DirectoryEntry,webkitFileSystemDirectoryEntry,FileSystemDirectoryEntry',
299 'DirectoryReader':
300 #Chrome Edge Opera
301 'DirectoryReader,WebKitDirectoryReader,webkitFileSystemDirectoryReader,FileSystemDirectoryReader',
302 'DOMFileSystem':
303 #Chrome Edge Opera
304 'DOMFileSystem,WebKitFileSystem,webkitFileSystem,FileSystem',
305 'Entry':
306 #Chrome Edge
307 'Entry,webkitFileSystemEntry,FileSystemEntry',
308 'Event':
309 'Event,InputEvent,SubmitEvent', # Workaround for issue 40901.
310 'FileEntry':
311 #Chrome Edge
312 'FileEntry,webkitFileSystemFileEntry,FileSystemFileEntry',
313 'HTMLTableCellElement':
314 'HTMLTableCellElement,HTMLTableDataCellElement,HTMLTableHeaderCellElement',
315 'GainNode':
316 'GainNode,AudioGainNode',
317 'IDBOpenDBRequest':
318 'IDBOpenDBRequest,IDBVersionChangeRequest',
319 'MouseEvent':
320 'MouseEvent,DragEvent',
321 'MutationObserver':
322 'MutationObserver,WebKitMutationObserver',
323 'NamedNodeMap':
324 'NamedNodeMap,MozNamedAttrMap',
325 'NodeList':
326 'NodeList,RadioNodeList',
327 'OscillatorNode':
328 'OscillatorNode,Oscillator',
329 'PannerNode':
330 'PannerNode,AudioPannerNode,webkitAudioPannerNode',
331 'Position':
332 'Position,GeolocationPosition',
333 'PositionError':
334 'PositionError,GeolocationPositionError',
335 'RTCPeerConnection':
336 'RTCPeerConnection,webkitRTCPeerConnection,mozRTCPeerConnection',
337 'RTCIceCandidate':
338 'RTCIceCandidate,mozRTCIceCandidate',
339 'RTCSessionDescription':
340 'RTCSessionDescription,mozRTCSessionDescription',
341 'RTCDataChannel':
342 'RTCDataChannel,DataChannel',
343 'ScriptProcessorNode':
344 'ScriptProcessorNode,JavaScriptAudioNode',
345 'SpeechRecognition':
346 'SpeechRecognition,webkitSpeechRecognition',
347 'TransitionEvent':
348 'TransitionEvent,WebKitTransitionEvent',
349 'CSSKeyframeRule':
350 'CSSKeyframeRule,MozCSSKeyframeRule,WebKitCSSKeyframeRule',
351 'CSSKeyframesRule':
352 'CSSKeyframesRule,MozCSSKeyframesRule,WebKitCSSKeyframesRule',
353
354 # webgl extensions are sometimes named directly after the getExtension
355 # parameter (e.g on Firefox).
356 'ANGLEInstancedArrays':
357 'ANGLEInstancedArrays,ANGLE_instanced_arrays',
358 'EXTsRGB':
359 'EXTsRGB,EXT_sRGB',
360 'EXTBlendMinMax':
361 'EXTBlendMinMax,EXT_blend_minmax',
362 'EXTFragDepth':
363 'EXTFragDepth,EXT_frag_depth',
364 'EXTShaderTextureLOD':
365 'EXTShaderTextureLOD,EXT_shader_texture_lod',
366 'EXTTextureFilterAnisotropic':
367 'EXTTextureFilterAnisotropic,EXT_texture_filter_anisotropic',
368 'OESElementIndexUint':
369 'OESElementIndexUint,OES_element_index_uint',
370 'OESStandardDerivatives':
371 'OESStandardDerivatives,OES_standard_derivatives',
372 'OESTextureFloat':
373 'OESTextureFloat,OES_texture_float',
374 'OESTextureFloatLinear':
375 'OESTextureFloatLinear,OES_texture_float_linear',
376 'OESTextureHalfFloat':
377 'OESTextureHalfFloat,OES_texture_half_float',
378 'OESTextureHalfFloatLinear':
379 'OESTextureHalfFloatLinear,OES_texture_half_float_linear',
380 'OESVertexArrayObject':
381 'OESVertexArrayObject,OES_vertex_array_object',
382 'WebGLCompressedTextureATC':
383 'WebGLCompressedTextureATC,WEBGL_compressed_texture_atc',
384 'WebGLCompressedTextureETC1':
385 'WebGLCompressedTextureETC1,WEBGL_compressed_texture_etc1',
386 'WebGLCompressedTexturePVRTC':
387 'WebGLCompressedTexturePVRTC,WEBGL_compressed_texture_pvrtc',
388 'WebGLCompressedTextureS3TC':
389 'WebGLCompressedTextureS3TC,WEBGL_compressed_texture_s3tc',
390 'WebGLDebugRendererInfo':
391 'WebGLDebugRendererInfo,WEBGL_debug_renderer_info',
392 'WebGLDebugShaders':
393 'WebGLDebugShaders,WEBGL_debug_shaders',
394 'WebGLDepthTexture':
395 'WebGLDepthTexture,WEBGL_depth_texture',
396 'WebGLDrawBuffers':
397 'WebGLDrawBuffers,WEBGL_draw_buffers',
398 'WebGLLoseContext':
399 'WebGLLoseContext,WebGLExtensionLoseContext,WEBGL_lose_context',
400 },
401 dart2jsOnly=True)
402
403
404def IsRegisteredType(type_name):
405 return type_name in _idl_type_registry
406
407
408def MakeNativeSpec(javascript_binding_name):
409 if javascript_binding_name in _dart2js_dom_custom_native_specs:
410 return _dart2js_dom_custom_native_specs[javascript_binding_name]
411 else:
412 # Make the class 'hidden' so it is dynamically patched at runtime. This
413 # is useful for browser compat.
414 return javascript_binding_name
415
416
417def MatchSourceFilter(thing):
418 return 'WebKit' in thing.annotations or 'Dart' in thing.annotations
419
420
421# Legacy Python 2 way to sort lists. Group by type, and then sort by value.
422class MultitypeSortKey:
423
424 def __init__(self, value):
425 self.value = value
426
427 def __lt__(self, other):
428 try:
429 return self.value < other.value
430 except TypeError:
431 return str(type(self)) < str(type(other))
432
433
434class ParamInfo(object):
435 """Holder for various information about a parameter of a Dart operation.
436
437 Attributes:
438 name: Name of parameter.
439 type_id: Original type id. None for merged types.
440 is_optional: Parameter optionality.
441 """
442
443 def __init__(self, name, type_id, is_optional, is_nullable, default_value,
444 default_value_is_null):
445 self.name = name
446 self.type_id = type_id
447 self.is_optional = is_optional
448 self.is_nullable = is_nullable
449 self.default_value = default_value
450 self.default_value_is_null = default_value_is_null
451
452 def Copy(self):
453 return ParamInfo(self.name, self.type_id, self.is_optional,
454 self.is_nullable, self.default_value,
455 self.default_value_is_null)
456
457 def __repr__(self):
458 content = ('name = %s, type_id = %s, is_optional = %s, '
459 'is_nullable = %s, default_value = %s, '
460 'default_value_is_null %s') % (
461 self.name, self.type_id, self.is_optional,
462 self.is_nullable, self.default_value,
463 self.default_value_is_null)
464 return '<ParamInfo(%s)>' % content
465
466
467def GetCallbackHandlers(interface):
468 callback_handlers = []
469 callback_handlers = [
470 operation for operation in interface.operations
471 if operation.id == 'handleEvent' or operation.id == 'handleMessage'
472 ]
473 if callback_handlers == []:
474 callback_handlers = [
475 operation for operation in interface.operations
476 if operation.id == 'handleItem'
477 ]
478 return callback_handlers
479
480
481def GetCallbackInfo(interface):
482 """For the given interface, find operations that take callbacks (for use in
483 auto-transforming callbacks into futures)."""
484 callback_handlers = GetCallbackHandlers(interface)
485 return AnalyzeOperation(interface, callback_handlers)
486
487
488# Given a list of overloaded arguments, render dart arguments.
489def _BuildArguments(args, interface, constructor=False):
490
491 # TODO(srujzs): Determine if this should really be turning false instead of
492 # argument.optional as the default. For NNBD, we'll derive parameter
493 # nullability from argument.optional but leave optionality otherwise alone.
494 def IsOptional(argument):
495 if 'Callback' in argument.ext_attrs:
496 # Optional callbacks arguments are treated as optional
497 # arguments.
498 return argument.optional
499 if constructor:
500 # FIXME: Optional constructors arguments should not be treated
501 # as optional arguments.
502 return argument.optional
503 if 'DartForceOptional' in argument.ext_attrs:
504 return True
505 return False
506
507 # Given a list of overloaded arguments, choose a suitable name.
508 def OverloadedName(args):
509 return '_OR_'.join(sorted(set(arg.id for arg in args)))
510
511 def DartType(idl_type_name):
512 if idl_type_name in _idl_type_registry:
513 return _idl_type_registry[idl_type_name].dart_type or idl_type_name
514 return idl_type_name
515
516 # Given a list of overloaded arguments, choose a suitable type.
517 def OverloadedType(args):
518 type_ids = sorted(set(arg.type.id for arg in args))
519 if len(set(DartType(arg.type.id) for arg in args)) == 1:
520 nullable = False
521 for arg in args:
522 # If the 'TreatNullAs' attribute exists, the param technically
523 # is nullable. The conversion happens in the browser.
524 nullable = nullable or getattr(arg.type, 'nullable', False) or \
525 'TreatNullAs' in arg.ext_attrs
526 return (type_ids[0], nullable)
527 else:
528 return (None, False)
529
530 # Given a list of overloaded default values, choose a suitable one.
531 def OverloadedDefault(args):
532 defaults = sorted(set(arg.default_value for arg in args),
533 key=MultitypeSortKey)
534 if len(set(DartType(arg.type.id) for arg in args)) == 1:
535 null_default = False
536 for arg in args:
537 null_default = null_default or arg.default_value_is_null
538 return (defaults[0], null_default)
539 else:
540 return (None, False)
541
542 result = []
543
544 is_optional = False
545 # Process overloaded arguments across a set of overloaded operations.
546 # Each tuple in args corresponds to overloaded arguments with the same name.
547 for arg_tuple in list(zip_longest(*args)):
548 is_optional = is_optional or any(
549 arg is None or IsOptional(arg) for arg in arg_tuple)
550 filtered = list(filter(None, arg_tuple))
551 (type_id, is_nullable) = OverloadedType(filtered)
552 name = OverloadedName(filtered)
553 (default_value, default_value_is_null) = OverloadedDefault(filtered)
554
555 # For nullability determination, we'll use the arguments' optionality
556 # instead of the IsOptional method above.
557 optional_argument = any(arg is None or arg.optional or
558 'DartForceOptional' in arg.ext_attrs for arg in arg_tuple)
559
560 if optional_argument and (default_value == 'Undefined' or
561 default_value == None or default_value_is_null):
562 is_nullable = True
563
564 result.append(
565 ParamInfo(name, type_id, is_optional, is_nullable, default_value,
566 default_value_is_null))
567
568 return result
569
570
571# Argument default value is one that we suppress
572# FIXME(leafp) We may wish to eliminate this special treatment of optional
573# arguments entirely, since default values are being used more pervasively
574# in the IDL now.
575def HasSuppressedOptionalDefault(argument):
576 return (
577 argument.default_value == 'Undefined') or argument.default_value_is_null
578
579
580def IsOptional(argument):
581 return argument.optional and (not(HasSuppressedOptionalDefault(argument))) \
582 or 'DartForceOptional' in argument.ext_attrs
583
584def OperationTypeIsNullable(operation):
585 if hasattr(operation.type, 'nullable'):
586 if operation.type.nullable:
587 return True
588 if operation.type.id == 'any':
589 # any is assumed to be nullable
590 return True
591
592 return False
593
594def AnalyzeOperation(interface, operations):
595 """Makes operation calling convention decision for a set of overloads.
596
597 Returns: An OperationInfo object.
598 """
599 # split operations with optional args into multiple operations
600 split_operations = []
601 for operation in operations:
602 for i in range(0, len(operation.arguments)):
603 if IsOptional(operation.arguments[i]):
604 new_operation = copy.deepcopy(operation)
605 new_operation.arguments = new_operation.arguments[:i]
606 split_operations.append(new_operation)
607 split_operations.append(operation)
608 # Zip together arguments from each overload by position, then convert
609 # to a dart argument.
610 info = OperationInfo()
611 info.operations = operations
612 info.overloads = split_operations
613 info.declared_name = operations[0].id
614 info.name = operations[0].ext_attrs.get('DartName', info.declared_name)
615 info.constructor_name = None
616 info.js_name = info.declared_name
617 info.type_name = operations[0].type.id # TODO: widen.
618 info.type_nullable = OperationTypeIsNullable(operations[0])
619 info.param_infos = _BuildArguments(
620 [op.arguments for op in split_operations], interface)
621 full_name = '%s.%s' % (interface.id, info.declared_name)
622 info.requires_named_arguments = full_name in _methods_with_named_formals
623 # The arguments in that the original operation took as callbacks (for
624 # conversion to futures).
625 info.callback_args = []
626 return info
627
628
629def ConvertToFuture(info):
630 """Given an OperationInfo object, convert the operation's signature so that it
631 instead uses futures instead of callbacks."""
632 new_info = copy.deepcopy(info)
633
634 def IsNotCallbackType(param):
635 type_id = param.type_id
636 if type_id is None:
637 return False
638 else:
639 return 'Callback' not in type_id
640
641 # Success callback is the first argument (change if this no longer holds).
642 new_info.callback_args = list(
643 filter(lambda x: not IsNotCallbackType(x), new_info.param_infos))
644 new_info.param_infos = list(filter(IsNotCallbackType, new_info.param_infos))
645 new_info.type_name = 'Future'
646
647 return new_info
648
649
650def AnalyzeConstructor(interface):
651 """Returns an OperationInfo object for the constructor.
652
653 Returns None if the interface has no Constructor.
654 """
655 if interface.id in _suppressed_native_constructors:
656 return None
657
658 if 'Constructor' in interface.ext_attrs:
659 name = None
660 overloads = interface.ext_attrs['Constructor']
661 idl_args = [[] if f is None else f.arguments for f in overloads]
662 elif 'NamedConstructor' in interface.ext_attrs:
663 func_value = interface.ext_attrs.get('NamedConstructor')
664 idl_args = [func_value.arguments]
665 name = func_value.id
666 else:
667 return None
668
669 info = OperationInfo()
670 info.overloads = None
671 info.idl_args = idl_args
672 info.declared_name = name
673 info.name = name
674 info.constructor_name = ('_' if interface.id in custom_html_constructors
675 else None)
676 info.js_name = name
677 info.type_name = interface.id
678 info.param_infos = _BuildArguments(idl_args, interface, constructor=True)
679 info.requires_named_arguments = False
680 info.pure_dart_constructor = False
681 return info
682
683
684def IsDartListType(type):
685 return type == 'List' or type.startswith('sequence<')
686
687
688def IsDartCollectionType(type):
689 return IsDartListType(type)
690
691
692def FindMatchingAttribute(interface, attr1):
693 matches = [attr2 for attr2 in interface.attributes if attr1.id == attr2.id]
694 if matches:
695 assert len(matches) == 1
696 return matches[0]
697 return None
698
699
700def DartDomNameOfAttribute(attr):
701 """Returns the Dart name for an IDLAttribute.
702
703 attr.id is the 'native' or JavaScript name.
704
705 To ensure uniformity, work with the true IDL name until as late a possible,
706 e.g. translate to the Dart name when generating Dart code.
707 """
708 name = attr.id
709 name = _dart_attribute_renames.get(name, name)
710 name = attr.ext_attrs.get('DartName', None) or name
711 return name
712
713
714def TypeOrNothing(dart_type, comment=None, nullable=False):
715 """Returns string for declaring something with |dart_type| in a context
716 where a type may be omitted.
717 The string is empty or has a trailing space.
718 """
719 nullability_operator = '?' if nullable else ''
720 if dart_type == 'dynamic':
721 if comment:
722 return '/*%s*/ ' % comment # Just a comment foo(/*T*/ x)
723 else:
724 return '' # foo(x) looks nicer than foo(var|dynamic x)
725 else:
726 return dart_type + nullability_operator + ' '
727
728
729def TypeOrVar(dart_type, comment=None):
730 """Returns string for declaring something with |dart_type| in a context
731 where if a type is omitted, 'var' must be used instead."""
732 if dart_type == 'dynamic':
733 if comment:
734 return 'var /*%s*/' % comment # e.g. var /*T*/ x;
735 else:
736 return 'var' # e.g. var x;
737 else:
738 return dart_type
739
740
741class OperationInfo(object):
742 """Holder for various derived information from a set of overloaded operations.
743
744 Attributes:
745 overloads: A list of IDL operation overloads with the same name.
746 name: A string, the simple name of the operation.
747 constructor_name: A string, the name of the constructor iff the constructor
748 is named, e.g. 'fromList' in Int8Array.fromList(list).
749 type_name: A string, the name of the return type of the operation.
750 type_nullable: Whether or not the return type is nullable.
751 param_infos: A list of ParamInfo.
752 factory_parameters: A list of parameters used for custom designed Factory
753 calls.
754 """
755
756 def __init__(self):
757 self.factory_parameters = None
758 self.type_nullable = False
759
760 def ParametersAsDecVarLists(self, rename_type, force_optional=False):
761 """ Returns a tuple (required, optional, named), where:
762 required is a list of parameter declarations corresponding to the
763 required parameters
764 optional is a list of parameter declarations corresponding to the
765 optional parameters
766 named is a boolean which is true if the optional parameters should
767 be named
768 A parameter declaration is a tuple (dec, var) where var is the
769 variable name, and dec is a string suitable for declaring the
770 variable in a parameter list. That is, dec + var is a valid
771 parameter declaration.
772 """
773
774 def FormatParam(param):
775 # Is the type a typedef if so it's a union so it's dynamic.
776 # TODO(terry): This may have to change for dart2js for code shaking the
777 # return types (unions) needs to be emitted with @create
778 # annotations and/or with JS('type1|type2',...)
779 if hasattr(
780 rename_type,
781 '__self__') and rename_type.__self__._database.HasTypeDef(
782 param.type_id):
783 dart_type = 'dynamic'
784 else:
785 dart_type = rename_type(
786 param.type_id) if param.type_id else 'dynamic'
787 # Special handling for setlike IDL forEach operation.
788 if dart_type is None and param.type_id.endswith('ForEachCallback'):
789 dart_type = param.type_id
790 return (TypeOrNothing(dart_type, param.type_id, param.is_nullable or
791 param.is_optional), param.name)
792
793 required = []
794 optional = []
795 for param_info in self.param_infos:
796 if param_info.is_optional:
797 optional.append(FormatParam(param_info))
798 else:
799 if optional:
800 raise Exception(
801 'Optional parameters cannot precede required ones: ' +
802 str(param_info))
803 required.append(FormatParam(param_info))
804 needs_named = optional and self.requires_named_arguments and not force_optional
805 return (required, optional, needs_named)
806
807 def ParametersAsDecStringList(self, rename_type, force_optional=False):
808 """Returns a list of strings where each string corresponds to a parameter
809 declaration. All of the optional/named parameters if any will appear as
810 a single entry at the end of the list.
811 """
812 (required, optional, needs_named) = \
813 self.ParametersAsDecVarLists(rename_type, force_optional)
814
815 def FormatParam(dec):
816 return dec[0] + dec[1]
817
818 argtexts = list(map(FormatParam, required))
819 if optional:
820 left_bracket, right_bracket = '{}' if needs_named else '[]'
821 argtexts.append(left_bracket +
822 ', '.join(map(FormatParam, optional)) +
823 right_bracket)
824 return argtexts
825
826 def ParametersAsDeclaration(self, rename_type, force_optional=False):
827 p_list = self.ParametersAsDecStringList(rename_type, force_optional)
828 return ', '.join(p_list)
829
830 def NumberOfRequiredInDart(self):
831 """ Returns a number of required arguments in Dart declaration of
832 the operation.
833 """
834 return len(list(filter(lambda i: not i.is_optional, self.param_infos)))
835
836 def ParametersAsArgumentList(self,
837 parameter_count=None,
838 ignore_named_parameters=False):
839 """Returns a string of the parameter names suitable for passing the
840 parameters as arguments.
841 """
842
843 def param_name(param_info):
844 if self.requires_named_arguments and param_info.is_optional and not ignore_named_parameters:
845 return '%s : %s' % (param_info.name, param_info.name)
846 else:
847 return param_info.name
848
849 if parameter_count is None:
850 parameter_count = len(self.param_infos)
851 return ', '.join(map(param_name, self.param_infos[:parameter_count]))
852
853 """ Check if a parameter to a Future API is a Dictionary argument and if its optional.
854 Used for any Promised based operation to correctly convert from Map to Dictionary then
855 perform the PromiseToFuture call.
856 """
857
858 def dictionaryArgumentName(self, parameter_count=None):
859 parameter_count = len(self.param_infos)
860 for argument in self.param_infos[:parameter_count]:
861 if argument.type_id == 'Dictionary':
862 return [argument.name, argument.is_optional]
863 return None
864
865 def isCallback(self, type_registry, type_id):
866 if type_id and not type_id.endswith('[]'):
867 callback_type = type_registry._database._all_interfaces[type_id]
868 return callback_type.operations[0].id == 'handleEvent' if len(
869 callback_type.operations) > 0 else False
870 else:
871 return False
872
873 def ParametersAsListOfVariables(self,
874 parameter_count=None,
875 type_registry=None,
876 dart_js_interop=False,
877 backend=None):
878 """Returns a list of the first parameter_count parameter names
879 as raw variables.
880 """
881 isRemoveOperation = self.name == 'removeEventListener' or self.name == 'removeListener'
882
883 if parameter_count is None:
884 parameter_count = len(self.param_infos)
885 if not type_registry:
886 return [p.name for p in self.param_infos[:parameter_count]]
887 else:
888 parameters = []
889 for p in self.param_infos[:parameter_count]:
890 type_id = p.type_id
891 # Unwrap the type to get the JsObject if Type is:
892 #
893 # - type_id is None then it's probably a union type or overloaded
894 # it's a dynamic/any type
895 # - type is Object
896 #
897 if (wrap_unwrap_type_blink(type_id, type_registry)):
898 type_is_callback = self.isCallback(type_registry, type_id)
899 if (dart_js_interop and type_id == 'EventListener' and
900 self.name in [
901 'addEventListener', 'removeEventListener'
902 ]):
903 # Events fired need use a JSFunction not a anonymous closure to
904 # insure the event can really be removed.
905 parameters.append('js.allowInterop(%s)' % p.name)
906 elif dart_js_interop and type_is_callback and not (
907 isRemoveOperation):
908 # Any remove operation that has a a callback doesn't need wrapping.
909 # TODO(terry): Kind of hacky but handles all the cases we care about
910 callback_type = type_registry._database._all_interfaces[
911 type_id]
912 callback_args_decl = []
913 callback_args_call = []
914 for callback_arg in callback_type.operations[
915 0].arguments:
916 if dart_js_interop:
917 dart_type = '' # For non-primitives we will be passing JsObject for non-primitives, so ignore types
918 else:
919 dart_type = type_registry.DartType(
920 callback_arg.type.id) + ' '
921 callback_args_decl.append(
922 '%s%s' % (dart_type, callback_arg.id))
923 if wrap_unwrap_type_blink(callback_arg.type.id,
924 type_registry):
925 callback_args_call.append(callback_arg.id)
926 else:
927 callback_args_call.append(callback_arg.id)
928 parameters.append(
929 '(%s) => %s(%s)' % (", ".join(callback_args_decl),
930 p.name,
931 ", ".join(callback_args_call)))
932 else:
933 parameters.append(p.name)
934 else:
935 if dart_js_interop:
936 conversion = backend._InputConversion(
937 p.type_id, self.declared_name)
938 passParam = p.name
939 if conversion:
940 # Need to pass the IDL Dictionary from Dart Map to JavaScript object.
941 passParam = '{0}({1})'.format(
942 conversion.function_name, p.name)
943 else:
944 passParam = p.name
945 parameters.append(passParam)
946
947 return parameters
948
949 def ParametersAsStringOfVariables(self, parameter_count=None):
950 """Returns a string containing the first parameter_count parameter names
951 as raw variables, comma separated.
952 """
953 return ', '.join(self.ParametersAsListOfVariables(parameter_count))
954
955 def IsStatic(self):
956 is_static = self.overloads[0].is_static
957 assert any([is_static == o.is_static for o in self.overloads])
958 return is_static
959
960 def _ConstructorFullName(self, rename_type):
961 if self.constructor_name:
962 return rename_type(self.type_name) + '.' + self.constructor_name
963 else:
964 # TODO(antonm): temporary ugly hack.
965 # While in transition phase we allow both DOM's ArrayBuffer
966 # and dart:typed_data's ByteBuffer for IDLs' ArrayBuffers,
967 # hence ArrayBuffer is mapped to dynamic in arguments and return
968 # values. To compensate for that when generating ArrayBuffer itself,
969 # we need to lie a bit:
970 if self.type_name == 'ArrayBuffer': return 'ByteBuffer'
971 return rename_type(self.type_name)
972
973
974def _ConstantOutputOrder(a, b):
975 """Canonical output ordering for constants."""
976 return (a.id > b.id) - (a.id < b.id)
977
978
979ConstantOutputOrder = cmp_to_key(_ConstantOutputOrder)
980
981
982def _FormatNameList(names):
983 """Returns JavaScript array literal expression with one name per line."""
984 #names = sorted(names)
985 if len(names) <= 1:
986 expression_string = str(names) # e.g. ['length']
987 else:
988 expression_string = ',\n '.join(str(names).split(','))
989 expression_string = expression_string.replace('[', '[\n ')
990 return expression_string
991
992
993def IndentText(text, indent):
994 """Format lines of text with indent."""
995
996 def FormatLine(line):
997 if line.strip():
998 return '%s%s\n' % (indent, line)
999 else:
1000 return '\n'
1001
1002 return ''.join(FormatLine(line) for line in text.split('\n'))
1003
1004
1005# Given a sorted sequence of type identifiers, return an appropriate type
1006# name
1007def TypeName(type_ids, interface):
1008 # Dynamically type this field for now.
1009 return 'dynamic'
1010
1011
1012# ------------------------------------------------------------------------------
1013
1014
1015class Conversion(object):
1016 """Represents a way of converting between types."""
1017
1018 def __init__(self, name, input_type, output_type, nullable_input=False,
1019 nullable_output=False):
1020 # input_type is the type of the API input (and the argument type of the
1021 # conversion function)
1022 # output_type is the type of the API output (and the result type of the
1023 # conversion function)
1024 self.function_name = name
1025 self.input_type = input_type
1026 self.output_type = output_type
1027 self.nullable_input = nullable_input or input_type == 'dynamic'
1028 self.nullable_output = nullable_output or output_type == 'dynamic'
1029
1030
1031# "TYPE DIRECTION INTERFACE.MEMBER" -> conversion
1032# Specific member of interface
1033# "TYPE DIRECTION INTERFACE.*" -> conversion
1034# All members of interface getting (setting) with type.
1035# "TYPE DIRECTION" -> conversion
1036# All getters (setters) of type.
1037#
1038# where DIRECTION is 'get' for getters and operation return values, 'set' for
1039# setters and operation arguments. INTERFACE and MEMBER are the idl names.
1040#
1041
1042_serialize_SSV = Conversion('convertDartToNative_SerializedScriptValue',
1043 'dynamic', 'dynamic')
1044
1045dart2js_conversions = monitored.Dict(
1046 'generator.dart2js_conversions',
1047 {
1048 # Used to convert Dart function to a JS callback typedef (old style).
1049 'Callback set':
1050 Conversion('convertDartClosureToJS', 'dynamic', 'dynamic'),
1051 'Date get':
1052 Conversion('convertNativeToDart_DateTime', 'dynamic', 'DateTime'),
1053 'Date set':
1054 Conversion('convertDartToNative_DateTime', 'DateTime', 'dynamic'),
1055 # Wrap non-local Windows. We need to check EventTarget (the base type)
1056 # as well. Note, there are no functions that take a non-local Window
1057 # as a parameter / setter.
1058 'Window get':
1059 Conversion('_convertNativeToDart_Window', 'dynamic', 'WindowBase',
1060 nullable_output=True),
1061 'EventTarget get':
1062 Conversion('_convertNativeToDart_EventTarget', 'dynamic',
1063 'EventTarget', nullable_output=True),
1064 'EventTarget set':
1065 Conversion('_convertDartToNative_EventTarget', 'EventTarget',
1066 'dynamic', nullable_input=True),
1067 'WebGLContextAttributes get':
1068 Conversion('convertNativeToDart_ContextAttributes', 'dynamic',
1069 'ContextAttributes'),
1070 'ImageData get':
1071 Conversion('convertNativeToDart_ImageData', 'dynamic', 'ImageData'),
1072 'ImageData set':
1073 Conversion('convertDartToNative_ImageData', 'ImageData', 'dynamic',
1074 nullable_input=True),
1075 'Dictionary get':
1076 Conversion('convertNativeToDart_Dictionary', 'dynamic', 'Map',
1077 nullable_output=True),
1078 'Dictionary set':
1079 Conversion('convertDartToNative_Dictionary', 'Map', 'dynamic',
1080 nullable_input=True),
1081 'sequence<DOMString> set':
1082 Conversion('convertDartToNative_StringArray', 'List<String>', 'List'),
1083 'any set IDBObjectStore.add':
1084 _serialize_SSV,
1085 'any set IDBObjectStore.put':
1086 _serialize_SSV,
1087 'any set IDBCursor.update':
1088 _serialize_SSV,
1089 'any get SQLResultSetRowList.item':
1090 Conversion('convertNativeToDart_Dictionary', 'dynamic', 'Map',
1091 nullable_output=True),
1092
1093 # postMessage
1094 'SerializedScriptValue set':
1095 _serialize_SSV,
1096 'any set CompositorWorkerGlobalScope.postMessage':
1097 _serialize_SSV,
1098 'any set DedicatedWorkerGlobalScope.postMessage':
1099 _serialize_SSV,
1100 'any set MessagePort.postMessage':
1101 _serialize_SSV,
1102 'any set Window.postMessage':
1103 _serialize_SSV,
1104 'any set _DOMWindowCrossFrame.postMessage':
1105 _serialize_SSV,
1106 'any set Worker.postMessage':
1107 _serialize_SSV,
1108 'any set ServiceWorker.postMessage':
1109 _serialize_SSV,
1110 '* get CustomEvent.detail':
1111 Conversion('convertNativeToDart_SerializedScriptValue', 'dynamic',
1112 'dynamic'),
1113
1114 # receiving message via MessageEvent
1115 '* get MessageEvent.data':
1116 Conversion('convertNativeToDart_SerializedScriptValue', 'dynamic',
1117 'dynamic'),
1118
1119 # TODO(alanknight): This generates two variations for dart2js, because of
1120 # the optional argument, but not in Dartium. Should do the same for both.
1121 'any set History.pushState':
1122 _serialize_SSV,
1123 'any set History.replaceState':
1124 _serialize_SSV,
1125 '* get History.state':
1126 Conversion('convertNativeToDart_SerializedScriptValue', 'dynamic',
1127 'dynamic'),
1128 '* get PopStateEvent.state':
1129 Conversion('convertNativeToDart_SerializedScriptValue', 'dynamic',
1130 'dynamic'),
1131
1132 # IDBAny is problematic. Some uses are just a union of other IDB types,
1133 # which need no conversion.. Others include data values which require
1134 # serialized script value processing.
1135 '* get IDBCursorWithValue.value':
1136 Conversion('_convertNativeToDart_IDBAny', 'dynamic', 'dynamic'),
1137
1138 # This is problematic. The result property of IDBRequest is used for
1139 # all requests. Read requests like IDBDataStore.getObject need
1140 # conversion, but other requests like opening a database return
1141 # something that does not need conversion.
1142 '* get IDBRequest.result':
1143 Conversion('_convertNativeToDart_IDBAny', 'dynamic', 'dynamic'),
1144
1145 # "source: On getting, returns the IDBObjectStore or IDBIndex that the
1146 # cursor is iterating. ...". So we should not try to convert it.
1147 '* get IDBCursor.source':
1148 None,
1149
1150 # Should be either a DOMString, an Array of DOMStrings or null.
1151 '* get IDBObjectStore.keyPath':
1152 None,
1153 '* get XMLHttpRequest.response':
1154 Conversion('_convertNativeToDart_XHR_Response', 'dynamic', 'dynamic'),
1155 },
1156 dart2jsOnly=True)
1157
1158
1159def FindConversion(idl_type, direction, interface, member):
1160 table = dart2js_conversions
1161 return (table.get('%s %s %s.%s' % (idl_type, direction, interface, member))
1162 or table.get('* %s %s.%s' % (direction, interface, member)) or
1163 table.get('%s %s %s.*' % (idl_type, direction, interface)) or
1164 table.get('%s %s' % (idl_type, direction)))
1165 return None
1166
1167
1168# ------------------------------------------------------------------------------
1169
1170
1171class IDLTypeInfo(object):
1172
1173 def __init__(self, idl_type, data):
1174 self._idl_type = idl_type
1175 self._data = data
1176
1177 def idl_type(self):
1178 return self._idl_type
1179
1180 def dart_type(self):
1181 return self._data.dart_type or self._idl_type
1182
1183 def narrow_dart_type(self):
1184 return self.dart_type()
1185
1186 def interface_name(self):
1187 raise NotImplementedError()
1188
1189 def implementation_name(self):
1190 raise NotImplementedError()
1191
1192 def has_generated_interface(self):
1193 raise NotImplementedError()
1194
1195 def list_item_type(self):
1196 raise NotImplementedError()
1197
1198 def merged_interface(self):
1199 return None
1200
1201 def merged_into(self):
1202 return None
1203
1204 def native_type(self):
1205 return self._data.native_type or self._idl_type
1206
1207 def bindings_class(self):
1208 return 'Dart%s' % self.idl_type()
1209
1210 def vector_to_dart_template_parameter(self):
1211 return self.native_type()
1212
1213 def to_native_info(self, idl_node, interface_name, callback_name):
1214 cls = self.bindings_class()
1215
1216 if 'Callback' in idl_node.ext_attrs:
1217 return '%s.release()', 'OwnPtr<%s>' % self.native_type(
1218 ), cls, 'create'
1219
1220 # This is a hack to handle property references correctly.
1221 if (self.native_type() in [
1222 'SVGPropertyTearOff<SVGAngle>', 'SVGPropertyTearOff<SVGAngle>*',
1223 'SVGMatrixTearOff'
1224 ] and (callback_name != 'createSVGTransformFromMatrixCallback' or
1225 interface_name != 'SVGTransformList')):
1226 argument_expression_template = '%s->propertyReference()'
1227 type = '%s*' % self.native_type()
1228 elif self.custom_to_native():
1229 type = 'RefPtr<%s>' % self.native_type()
1230 argument_expression_template = '%s.get()'
1231 else:
1232 type = '%s*' % self.native_type()
1233 argument_expression_template = '%s'
1234 return argument_expression_template, type, cls, 'toNative'
1235
1236 def pass_native_by_ref(self):
1237 return False
1238
1239 def custom_to_native(self):
1240 return self._data.custom_to_native
1241
1242 def parameter_type(self):
1243 return '%s*' % self.native_type()
1244
1245 def webcore_includes(self):
1246 WTF_INCLUDES = [
1247 'ArrayBuffer',
1248 'ArrayBufferView',
1249 'Float32Array',
1250 'Float64Array',
1251 'Int8Array',
1252 'Int16Array',
1253 'Int32Array',
1254 'Uint8Array',
1255 'Uint8ClampedArray',
1256 'Uint16Array',
1257 'Uint32Array',
1258 ]
1259
1260 if self._idl_type in WTF_INCLUDES:
1261 return ['<wtf/%s.h>' % self.native_type()]
1262
1263 # TODO(vsm): Why does this need special casing?
1264 if self._idl_type == 'AnalyserNode':
1265 return ['"AnalyserNode.h"', '<wtf/Uint8Array.h>']
1266
1267 if not self._idl_type.startswith('SVG'):
1268 return ['"%s.h"' % self.native_type()]
1269
1270 include = self._idl_type
1271 return ['"%s.h"' % include] + _svg_supplemental_includes
1272
1273 def receiver(self):
1274 return 'receiver->'
1275
1276 def conversion_includes(self):
1277 includes = [self._idl_type] + (self._data.conversion_includes or [])
1278 return ['"Dart%s.h"' % include for include in includes]
1279
1280 def to_dart_conversion(self, value, interface_name=None, attributes=None):
1281 return 'Dart%s::toDart(%s)' % (self._idl_type, value)
1282
1283 def return_to_dart_conversion(self,
1284 value,
1285 auto_dart_scope_setup,
1286 interface_name=None,
1287 attributes=None):
1288 auto_dart_scope = 'true' if auto_dart_scope_setup else 'false'
1289 return 'Dart%s::returnToDart(args, %s, %s)' % (
1290 self._idl_type,
1291 ReturnValueConversionHack(self._idl_type, value,
1292 interface_name), auto_dart_scope)
1293
1294 def custom_to_dart(self):
1295 return self._data.custom_to_dart
1296
1297
1298class InterfaceIDLTypeInfo(IDLTypeInfo):
1299
1300 def __init__(self, idl_type, data, dart_interface_name, type_registry):
1301 super(InterfaceIDLTypeInfo, self).__init__(idl_type, data)
1302 self._dart_interface_name = dart_interface_name
1303 self._type_registry = type_registry
1304
1305 def dart_type(self):
1306 if self._data.dart_type:
1307 return self._data.dart_type
1308 if self.list_item_type() and not self.has_generated_interface():
1309 item_nullable = '?' if self._data.item_type_nullable else ''
1310 return 'List<%s%s>' % (self._type_registry.TypeInfo(
1311 self._data.item_type).dart_type(), item_nullable)
1312 return self._dart_interface_name
1313
1314 def narrow_dart_type(self):
1315 if self.list_item_type():
1316 return self.implementation_name()
1317 # TODO(podivilov): only primitive and collection types should override
1318 # dart_type.
1319 if self._data.dart_type != None:
1320 return self.dart_type()
1321 if IsPureInterface(self.idl_type(), self._type_registry._database):
1322 return self.idl_type()
1323 return self.interface_name()
1324
1325 def interface_name(self):
1326 return self._dart_interface_name
1327
1328 def implementation_name(self):
1329 implementation_name = self._dart_interface_name
1330
1331 if not self.has_generated_interface():
1332 implementation_name = '_%s' % implementation_name
1333
1334 return implementation_name
1335
1336 def native_type(self):
1337 database = self._type_registry._database
1338
1339 if database.HasInterface(self.idl_type()):
1340 interface = database.GetInterface(self.idl_type())
1341 if 'ImplementedAs' in interface.ext_attrs:
1342 return interface.ext_attrs['ImplementedAs']
1343 return super(InterfaceIDLTypeInfo, self).native_type()
1344
1345 def has_generated_interface(self):
1346 return not self._data.suppress_interface
1347
1348 def list_item_type(self):
1349 return self._data.item_type
1350
1351 def list_item_type_nullable(self):
1352 return self._data.item_type_nullable
1353
1354 def merged_interface(self):
1355 # All constants, attributes, and operations of merged interface should be
1356 # added to this interface. Merged idl interface does not have corresponding
1357 # Dart generated interface, and all references to merged idl interface
1358 # (e.g. parameter types, return types, parent interfaces) should be replaced
1359 # with this interface. There are two important restrictions:
1360 # 1) Merged and target interfaces shouldn't have common members, otherwise
1361 # there would be duplicated declarations in generated Dart code.
1362 # 2) Merged interface should be direct child of target interface, so the
1363 # children of merged interface are not affected by the merge.
1364 # As a consequence, target interface implementation and its direct children
1365 # interface implementations should implement merged attribute accessors and
1366 # operations. For example, SVGElement and Element implementation classes
1367 # should implement HTMLElement.insertAdjacentElement(),
1368 # HTMLElement.innerHTML, etc.
1369 return self._data.merged_interface
1370
1371 def merged_into(self):
1372 return self._data.merged_into
1373
1374
1375class CallbackIDLTypeInfo(IDLTypeInfo):
1376
1377 def __init__(self, idl_type, data):
1378 super(CallbackIDLTypeInfo, self).__init__(idl_type, data)
1379
1380 def interface_name(self):
1381 return self.dart_type()
1382
1383 def implementation_name(self):
1384 return self.dart_type()
1385
1386 def list_item_type(self):
1387 return self._data.item_type
1388
1389
1390def array_type(data_type):
1391 matched = re.match(r'([\w\d_\s]+)\[\]', data_type)
1392 if not matched:
1393 return None
1394 return matched.group(1)
1395
1396
1397class SequenceIDLTypeInfo(IDLTypeInfo):
1398
1399 def __init__(self, idl_type, data, item_info):
1400 super(SequenceIDLTypeInfo, self).__init__(idl_type, data)
1401 self._item_info = item_info
1402
1403 def dart_type(self):
1404 darttype = self._item_info.dart_type()
1405 return 'List' if darttype is None else 'List<%s>' % darttype
1406
1407 def interface_name(self):
1408 return self.dart_type()
1409
1410 def implementation_name(self):
1411 return self.dart_type()
1412
1413 def vector_to_dart_template_parameter(self):
1414 raise Exception('sequences of sequences are not supported yet')
1415
1416 def to_native_info(self, idl_node, interface_name, callback_name):
1417 item_native_type = self._item_info.vector_to_dart_template_parameter()
1418 if isinstance(self._item_info, PrimitiveIDLTypeInfo):
1419 return '%s', 'Vector<%s>' % item_native_type, 'DartUtilities', 'toNativeVector<%s>' % item_native_type
1420 return '%s', 'Vector< RefPtr<%s> >' % item_native_type, 'DartUtilities', 'toNativeVector< RefPtr<%s> >' % item_native_type
1421
1422 def parameter_type(self):
1423 native_type = self.native_type()
1424 if array_type(native_type):
1425 return 'const Vector<RefPtr<%s> > &' % array_type(native_type)
1426
1427 return native_type
1428
1429 def pass_native_by_ref(self):
1430 return True
1431
1432 def to_dart_conversion(self, value, interface_name=None, attributes=None):
1433 if isinstance(self._item_info, PrimitiveIDLTypeInfo):
1434 return 'DartDOMWrapper::vectorToDart(%s)' % value
1435 return 'DartDOMWrapper::vectorToDart<%s>(%s)' % (
1436 self._item_info.bindings_class(), value)
1437
1438 def return_to_dart_conversion(self,
1439 value,
1440 auto_dart_scope_setup=True,
1441 interface_name=None,
1442 attributes=None):
1443 return 'Dart_SetReturnValue(args, %s)' % self.to_dart_conversion(
1444 value, interface_name, attributes)
1445
1446 def conversion_includes(self):
1447 return self._item_info.conversion_includes()
1448
1449
1450class DOMStringArrayTypeInfo(SequenceIDLTypeInfo):
1451
1452 def __init__(self, data, item_info):
1453 super(DOMStringArrayTypeInfo, self).__init__('DOMString[]', data,
1454 item_info)
1455
1456 def to_native_info(self, idl_node, interface_name, callback_name):
1457 return '%s', 'RefPtr<DOMStringList>', 'DartDOMStringList', 'toNative'
1458
1459 def pass_native_by_ref(self):
1460 return False
1461
1462 def implementation_name(self):
1463 return ""
1464
1465
1466class PrimitiveIDLTypeInfo(IDLTypeInfo):
1467
1468 def __init__(self, idl_type, data):
1469 super(PrimitiveIDLTypeInfo, self).__init__(idl_type, data)
1470
1471 def vector_to_dart_template_parameter(self):
1472 # Ugly hack. Usually IDLs floats are treated as C++ doubles, however
1473 # sequence<float> should map to Vector<float>
1474 if self.idl_type() == 'float': return 'float'
1475 return self.native_type()
1476
1477 def to_native_info(self, idl_node, interface_name, callback_name):
1478 type = self.native_type()
1479 if type == 'SerializedScriptValue':
1480 type = 'RefPtr<%s>' % type
1481 if type == 'String':
1482 type = 'DartStringAdapter'
1483 target_type = self._capitalized_native_type()
1484 if self.idl_type() == 'Date':
1485 target_type = 'Date'
1486 return '%s', type, 'DartUtilities', 'dartTo%s' % target_type
1487
1488 def parameter_type(self):
1489 if self.native_type() == 'String':
1490 return 'const String&'
1491 return self.native_type()
1492
1493 def conversion_includes(self):
1494 return []
1495
1496 def to_dart_conversion(self, value, interface_name=None, attributes=None):
1497 # TODO(antonm): if there are more instances of the case
1498 # when conversion depends on both Dart type and C++ type,
1499 # consider introducing a corresponding argument/class.
1500 if self.idl_type() == 'Date':
1501 function_name = 'date'
1502 else:
1503 function_name = self._capitalized_native_type()
1504 function_name = function_name[0].lower() + function_name[1:]
1505 function_name = 'DartUtilities::%sToDart' % function_name
1506 if attributes and 'TreatReturnedNullStringAs' in attributes:
1507 function_name += 'WithNullCheck'
1508 return '%s(%s)' % (function_name, value)
1509
1510 def return_to_dart_conversion(self,
1511 value,
1512 auto_dart_scope_setup=True,
1513 interface_name=None,
1514 attributes=None):
1515 return 'Dart_SetReturnValue(args, %s)' % self.to_dart_conversion(
1516 value, interface_name, attributes)
1517
1518 def webcore_getter_name(self):
1519 return self._data.webcore_getter_name
1520
1521 def webcore_setter_name(self):
1522 return self._data.webcore_setter_name
1523
1524 def _capitalized_native_type(self):
1525 return re.sub(r'(^| )([a-z])', lambda x: x.group(2).upper(),
1526 self.native_type())
1527
1528
1529class SVGTearOffIDLTypeInfo(InterfaceIDLTypeInfo):
1530
1531 def __init__(self, idl_type, data, interface_name, type_registry):
1532 super(SVGTearOffIDLTypeInfo,
1533 self).__init__(idl_type, data, interface_name, type_registry)
1534
1535 def native_type(self):
1536 if self._data.native_type:
1537 return self._data.native_type
1538 tear_off_type = 'SVGPropertyTearOff'
1539 if self._idl_type.endswith('List'):
1540 tear_off_type = 'SVGListPropertyTearOff'
1541 return '%s<%s>' % (tear_off_type, self._idl_type)
1542
1543 def receiver(self):
1544 return 'receiver->'
1545
1546 def to_conversion_cast(self, value, interface_name, attributes):
1547 svg_primitive_types = [
1548 'SVGLength', 'SVGMatrix', 'SVGNumber', 'SVGPoint', 'SVGRect',
1549 'SVGTransform'
1550 ]
1551
1552 # This is a hack. We either need to figure out the right way to derive this
1553 # information from the IDL or remove this generator.
1554 if self.idl_type() != 'SVGTransformList':
1555 return value
1556
1557 conversion_cast = 'static_cast<%s*>(%s)'
1558 conversion_cast = conversion_cast % (self.native_type(), value)
1559 return '%s' % (conversion_cast)
1560
1561 def to_dart_conversion(self, value, interface_name, attributes):
1562 return 'Dart%s::toDart(%s)' % (self._idl_type,
1563 self.to_conversion_cast(
1564 value, interface_name, attributes))
1565
1566 def return_to_dart_conversion(self, value, auto_dart_scope_setup,
1567 interface_name, attr):
1568 auto_dart_scope = 'true' if auto_dart_scope_setup else 'false'
1569 return 'Dart%s::returnToDart(args, %s, %s)' % (
1570 self._idl_type,
1571 self.to_conversion_cast(
1572 ReturnValueConversionHack(self._idl_type, value,
1573 interface_name), interface_name,
1574 attr), auto_dart_scope)
1575
1576 def argument_expression(self, name, interface_name):
1577 return name
1578
1579
1580class TypedListIDLTypeInfo(InterfaceIDLTypeInfo):
1581
1582 def __init__(self, idl_type, data, interface_name, type_registry):
1583 super(TypedListIDLTypeInfo,
1584 self).__init__(idl_type, data, interface_name, type_registry)
1585
1586 def conversion_includes(self):
1587 return ['"wtf/%s.h"' % self._idl_type]
1588
1589 def to_dart_conversion(self, value, interface_name, attributes):
1590 return 'DartUtilities::arrayBufferViewToDart(%s)' % value
1591
1592 def return_to_dart_conversion(self, value, auto_dart_scope_setup,
1593 interface_name, attributes):
1594 return 'Dart_SetReturnValue(args, %s)' % self.to_dart_conversion(
1595 value, interface_name, attributes)
1596
1597 def to_native_info(self, idl_node, interface_name, callback_name):
1598 return '%s.get()', 'RefPtr<%s>' % self._idl_type, 'DartUtilities', 'dartTo%s' % self._idl_type
1599
1600
1601class BasicTypedListIDLTypeInfo(InterfaceIDLTypeInfo):
1602
1603 def __init__(self, idl_type, data, interface_name, type_registry):
1604 super(BasicTypedListIDLTypeInfo,
1605 self).__init__(idl_type, data, interface_name, type_registry)
1606
1607 def conversion_includes(self):
1608 return []
1609
1610 def to_dart_conversion(self, value, interface_name, attributes):
1611 function_name = 'DartUtilities::%sToDart' % self._idl_type
1612 function_name = function_name[0].lower() + function_name[1:]
1613 return '%s(%s)' % (function_name, value)
1614
1615 def return_to_dart_conversion(self, value, auto_dart_scope_setup,
1616 interface_name, attributes):
1617 return 'Dart_SetReturnValue(args, %s)' % self.to_dart_conversion(
1618 value, interface_name, attributes)
1619
1620 def to_native_info(self, idl_node, interface_name, callback_name):
1621 return '%s.get()', 'RefPtr<%s>' % self._idl_type, 'DartUtilities', 'dartTo%s' % self._idl_type
1622
1623
1624class TypeData(object):
1625
1626 def __init__(self,
1627 clazz,
1628 dart_type=None,
1629 native_type=None,
1630 merged_interface=None,
1631 merged_into=None,
1632 custom_to_dart=False,
1633 custom_to_native=False,
1634 conversion_includes=None,
1635 webcore_getter_name='getAttribute',
1636 webcore_setter_name='setAttribute',
1637 item_type=None,
1638 item_type_nullable=False,
1639 suppress_interface=False):
1640 self.clazz = clazz
1641 self.dart_type = dart_type
1642 self.native_type = native_type
1643 self.merged_interface = merged_interface
1644 self.merged_into = merged_into
1645 self.custom_to_dart = custom_to_dart
1646 self.custom_to_native = custom_to_native
1647 self.conversion_includes = conversion_includes
1648 self.webcore_getter_name = webcore_getter_name
1649 self.webcore_setter_name = webcore_setter_name
1650 self.item_type = item_type
1651 self.item_type_nullable = item_type_nullable
1652 self.suppress_interface = suppress_interface
1653
1654
1655def TypedListTypeData(item_type):
1656 return TypeData(clazz='TypedList', item_type=item_type)
1657
1658
1659_idl_type_registry = monitored.Dict(
1660 'generator._idl_type_registry',
1661 {
1662 'boolean':
1663 TypeData(
1664 clazz='Primitive',
1665 dart_type='bool',
1666 native_type='bool',
1667 webcore_getter_name='hasAttribute',
1668 webcore_setter_name='setBooleanAttribute'),
1669 'byte':
1670 TypeData(clazz='Primitive', dart_type='int', native_type='int'),
1671 'octet':
1672 TypeData(clazz='Primitive', dart_type='int', native_type='int'),
1673 'short':
1674 TypeData(clazz='Primitive', dart_type='int', native_type='int'),
1675 'unsigned short':
1676 TypeData(clazz='Primitive', dart_type='int', native_type='int'),
1677 'int':
1678 TypeData(clazz='Primitive', dart_type='int'),
1679 'long':
1680 TypeData(
1681 clazz='Primitive',
1682 dart_type='int',
1683 native_type='int',
1684 webcore_getter_name='getIntegralAttribute',
1685 webcore_setter_name='setIntegralAttribute'),
1686 'unsigned long':
1687 TypeData(
1688 clazz='Primitive',
1689 dart_type='int',
1690 native_type='unsigned',
1691 webcore_getter_name='getUnsignedIntegralAttribute',
1692 webcore_setter_name='setUnsignedIntegralAttribute'),
1693 'long long':
1694 TypeData(clazz='Primitive', dart_type='int'),
1695 'unsigned long long':
1696 TypeData(clazz='Primitive', dart_type='int'),
1697 'float':
1698 TypeData(clazz='Primitive', dart_type='num', native_type='double'),
1699 'double':
1700 TypeData(clazz='Primitive', dart_type='num'),
1701 'any':
1702 TypeData(
1703 clazz='Primitive', dart_type='Object', native_type='ScriptValue'),
1704 'Array':
1705 TypeData(clazz='Primitive', dart_type='List'),
1706 'custom':
1707 TypeData(clazz='Primitive', dart_type='dynamic'),
1708 'DOMRect':
1709 TypeData(
1710 clazz='Interface', dart_type='Rectangle', suppress_interface=True),
1711 'Date':
1712 TypeData(clazz='Primitive', dart_type='DateTime', native_type='double'),
1713 'Promise':
1714 TypeData(
1715 clazz='Primitive', dart_type='Future', native_type='ScriptPromise'),
1716 'DOMObject':
1717 TypeData(
1718 clazz='Primitive', dart_type='Object', native_type='ScriptValue'),
1719 'DOMString':
1720 TypeData(clazz='Primitive', dart_type='String', native_type='String'),
1721 'ScriptURLString':
1722 TypeData(clazz='Primitive', dart_type='String', native_type='String'),
1723 # TODO(vsm): This won't actually work until we convert the Map to
1724 # a native JS Map for JS DOM.
1725 'Dictionary':
1726 TypeData(clazz='Primitive', dart_type='Map'),
1727 'DOMTimeStamp':
1728 TypeData(
1729 clazz='Primitive',
1730 dart_type='int',
1731 native_type='unsigned long long'),
1732 'object':
1733 TypeData(
1734 clazz='Primitive', dart_type='Object', native_type='ScriptValue'),
1735 'PositionOptions':
1736 TypeData(clazz='Primitive', dart_type='Object'),
1737 # TODO(sra): Come up with some meaningful name so that where this appears in
1738 # the documentation, the user is made aware that only a limited subset of
1739 # serializable types are actually permitted.
1740 'SerializedScriptValue':
1741 TypeData(clazz='Primitive', dart_type='dynamic'),
1742 'sequence':
1743 TypeData(clazz='Primitive', dart_type='List'),
1744 'sequence<any>':
1745 TypeData(clazz='Primitive', dart_type='List'),
1746 'void':
1747 TypeData(clazz='Primitive', dart_type='void'),
1748 'CSSRule':
1749 TypeData(clazz='Interface', conversion_includes=['CSSImportRule']),
1750 'DOMStringMap':
1751 TypeData(clazz='Interface', dart_type='Map<String, String>'),
1752 'Window':
1753 TypeData(clazz='Interface', custom_to_dart=True),
1754 'Element':
1755 TypeData(
1756 clazz='Interface',
1757 merged_interface='HTMLElement',
1758 custom_to_dart=True),
1759 'EventListener':
1760 TypeData(clazz='Interface', custom_to_native=True),
1761 'EventHandler':
1762 TypeData(clazz='Interface', custom_to_native=True),
1763 'EventTarget':
1764 TypeData(clazz='Interface', custom_to_native=True),
1765 'HTMLElement':
1766 TypeData(clazz='Interface', merged_into='Element', custom_to_dart=True),
1767 'IDBAny':
1768 TypeData(clazz='Interface', dart_type='dynamic', custom_to_native=True),
1769 'MutationRecordArray':
1770 TypeData(
1771 clazz='Interface', # C++ pass by pointer.
1772 native_type='MutationRecordArray',
1773 dart_type='List<MutationRecord>'),
1774 'StyleSheet':
1775 TypeData(clazz='Interface', conversion_includes=['CSSStyleSheet']),
1776 'SVGElement':
1777 TypeData(clazz='Interface', custom_to_dart=True),
1778 'CSSRuleList':
1779 TypeData(
1780 clazz='Interface', item_type='CSSRule', suppress_interface=True),
1781 'CSSValueList':
1782 TypeData(
1783 clazz='Interface', item_type='CSSValue', suppress_interface=True),
1784 'MimeTypeArray':
1785 TypeData(clazz='Interface', item_type='MimeType'),
1786 'PluginArray':
1787 TypeData(clazz='Interface', item_type='Plugin'),
1788 'DOMRectList':
1789 TypeData(
1790 clazz='Interface',
1791 item_type='DOMRect',
1792 dart_type='List<Rectangle>',
1793 custom_to_native=True),
1794 'DOMStringList':
1795 TypeData(
1796 clazz='Interface',
1797 item_type='DOMString',
1798 dart_type='List<String>',
1799 custom_to_native=True),
1800 'FileList':
1801 TypeData(clazz='Interface', item_type='File', dart_type='List<File>'),
1802 # Handle new FrozenArray Web IDL builtin
1803 # TODO(terry): Consider automating this mechanism to map the conversion from FrozenArray<xxx>
1804 # to List<xxx>. Some caveats for double, unsigned int and dictionary.
1805 'FrozenArray<BackgroundFetchSettledFetch>':
1806 TypeData(
1807 clazz='Primitive',
1808 item_type='BackgroundFetchSettledFetch',
1809 dart_type='List<BackgroundFetchSettledFetch>'),
1810 'FrozenArray<DOMString>':
1811 TypeData(
1812 clazz='Primitive',
1813 item_type='DOMString',
1814 dart_type='List<String>',
1815 custom_to_native=True),
1816 'FrozenArray<double>':
1817 TypeData(clazz='Primitive', item_type='double', dart_type='List<num>'),
1818 'FrozenArray<Entry>':
1819 TypeData(clazz='Primitive', item_type='Entry', dart_type='List<Entry>'),
1820 'FrozenArray<FillLightMode>':
1821 TypeData(
1822 clazz='Primitive', item_type='FillLightMode', dart_type='List'),
1823 'FrozenArray<FontFace>':
1824 TypeData(
1825 clazz='Primitive', item_type='FontFace',
1826 dart_type='List<FontFace>'),
1827 'FrozenArray<GamepadButton>':
1828 TypeData(
1829 clazz='Primitive',
1830 item_type='GamepadButton',
1831 dart_type='List<GamepadButton>'),
1832 'FrozenArray<Landmark>':
1833 TypeData(clazz='Primitive', item_type='Landmark', dart_type='List'),
1834 'FrozenArray<MediaImage>':
1835 TypeData(clazz='Primitive', item_type='MediaImage', dart_type='List'),
1836 'FrozenArray<MediaStream>':
1837 TypeData(
1838 clazz='Primitive',
1839 item_type='MediaStream',
1840 dart_type='List<MediaStream>'),
1841 'FrozenArray<MessagePort>':
1842 TypeData(
1843 clazz='Primitive',
1844 item_type='MessagePort',
1845 dart_type='List<MessagePort>'),
1846 'FrozenArray<NotificationAction>':
1847 TypeData(
1848 clazz='Primitive', item_type='NotificationAction',
1849 dart_type='List'),
1850 'FrozenArray<PaymentDetailsModifier>':
1851 TypeData(
1852 clazz='Primitive',
1853 item_type='PaymentDetailsModifier',
1854 dart_type='List'),
1855 'FrozenArray<PaymentMethodData>':
1856 TypeData(
1857 clazz='Primitive', item_type='PaymentMethodData', dart_type='List'),
1858 'FrozenArray<PerformanceServerTiming>':
1859 TypeData(
1860 clazz='Primitive',
1861 item_type='PerformanceServerTiming',
1862 dart_type='List<PerformanceServerTiming>'),
1863 'FrozenArray<Point2D>':
1864 TypeData(clazz='Primitive', item_type='Point2D', dart_type='List'),
1865 'FrozenArray<PresentationConnection>':
1866 TypeData(
1867 clazz='Primitive',
1868 item_type='PresentationConnection',
1869 dart_type='List<PresentationConnection>'),
1870 'FrozenArray<TaskAttributionTiming>':
1871 TypeData(
1872 clazz='Primitive',
1873 item_type='TaskAttributionTiming',
1874 dart_type='List<TaskAttributionTiming>'),
1875 'FrozenArray<unsigned long>':
1876 TypeData(
1877 clazz='Primitive', item_type='unsigned long',
1878 dart_type='List<int>'),
1879 'FrozenArray<USBEndpoint>':
1880 TypeData(
1881 clazz='Primitive',
1882 item_type='USBEndpoint',
1883 dart_type='List<USBEndpoint>'),
1884 'FrozenArray<USBInterface>':
1885 TypeData(
1886 clazz='Primitive',
1887 item_type='USBInterface',
1888 dart_type='List<USBInterface>'),
1889 'FrozenArray<USBConfiguration>':
1890 TypeData(
1891 clazz='Primitive',
1892 item_type='USBConfiguration',
1893 dart_type='List<USBConfiguration>'),
1894 'FrozenArray<USBAlternateInterface>':
1895 TypeData(
1896 clazz='Primitive',
1897 item_type='USBAlternateInterface',
1898 dart_type='List<USBAlternateInterface>'),
1899 'FrozenArray<USBIsochronousInTransferPacket>':
1900 TypeData(
1901 clazz='Primitive',
1902 item_type='USBIsochronousInTransferPacket',
1903 dart_type='List<USBIsochronousInTransferPacket>'),
1904 'FrozenArray<USBIsochronousOutTransferPacket>':
1905 TypeData(
1906 clazz='Primitive',
1907 item_type='USBIsochronousOutTransferPacket',
1908 dart_type='List<USBIsochronousOutTransferPacket>'),
1909 'FrozenArray<VRStageBoundsPoint>':
1910 TypeData(
1911 clazz='Primitive',
1912 item_type='VRStageBoundsPoint',
1913 dart_type='List<VRStageBoundsPoint>'),
1914 'Future':
1915 TypeData(clazz='Interface', dart_type='Future'),
1916 'GamepadList':
1917 TypeData(
1918 clazz='Interface',
1919 item_type='Gamepad',
1920 item_type_nullable=True,
1921 suppress_interface=True),
1922 'GLenum':
1923 TypeData(clazz='Primitive', dart_type='int', native_type='unsigned'),
1924 'GLboolean':
1925 TypeData(clazz='Primitive', dart_type='bool', native_type='bool'),
1926 'GLbitfield':
1927 TypeData(clazz='Primitive', dart_type='int', native_type='unsigned'),
1928 'GLshort':
1929 TypeData(clazz='Primitive', dart_type='int', native_type='short'),
1930 'GLint':
1931 TypeData(clazz='Primitive', dart_type='int', native_type='long'),
1932 'GLsizei':
1933 TypeData(clazz='Primitive', dart_type='int', native_type='long'),
1934 'GLintptr':
1935 TypeData(clazz='Primitive', dart_type='int'),
1936 'GLsizeiptr':
1937 TypeData(clazz='Primitive', dart_type='int'),
1938 'GLushort':
1939 TypeData(clazz='Primitive', dart_type='int', native_type='int'),
1940 'GLuint':
1941 TypeData(clazz='Primitive', dart_type='int', native_type='unsigned'),
1942 'GLfloat':
1943 TypeData(clazz='Primitive', dart_type='num', native_type='float'),
1944 'GLclampf':
1945 TypeData(clazz='Primitive', dart_type='num', native_type='float'),
1946 'HTMLCollection':
1947 TypeData(clazz='Interface', item_type='Node', dart_type='List<Node>'),
1948 'NamedNodeMap':
1949 TypeData(clazz='Interface', item_type='Node'),
1950 'NodeList':
1951 TypeData(
1952 clazz='Interface',
1953 item_type='Node',
1954 suppress_interface=False,
1955 dart_type='List<Node>'),
1956 'NotificationAction':
1957 TypedListTypeData(''),
1958 'SVGElementInstanceList':
1959 TypeData(
1960 clazz='Interface',
1961 item_type='SVGElementInstance',
1962 suppress_interface=True),
1963 'SourceBufferList':
1964 TypeData(clazz='Interface', item_type='SourceBuffer'),
1965 'SpeechGrammarList':
1966 TypeData(clazz='Interface', item_type='SpeechGrammar'),
1967 'SpeechInputResultList':
1968 TypeData(
1969 clazz='Interface',
1970 item_type='SpeechInputResult',
1971 suppress_interface=True),
1972 'SpeechRecognitionResultList':
1973 TypeData(
1974 clazz='Interface',
1975 item_type='SpeechRecognitionResult',
1976 suppress_interface=True),
1977 'SQLResultSetRowList':
1978 TypeData(clazz='Interface', item_type='Dictionary'),
1979 'StyleSheetList':
1980 TypeData(
1981 clazz='Interface', item_type='StyleSheet', suppress_interface=True),
1982 'TextTrackCueList':
1983 TypeData(clazz='Interface', item_type='TextTrackCue'),
1984 'TextTrackList':
1985 TypeData(clazz='Interface', item_type='TextTrack'),
1986 'TouchList':
1987 TypeData(clazz='Interface', item_type='Touch'),
1988 'Float32Array':
1989 TypedListTypeData('double'),
1990 'Float64Array':
1991 TypedListTypeData('double'),
1992 'Int8Array':
1993 TypedListTypeData('int'),
1994 'Int16Array':
1995 TypedListTypeData('int'),
1996 'Int32Array':
1997 TypedListTypeData('int'),
1998 'Uint8Array':
1999 TypedListTypeData('int'),
2000 'Uint8ClampedArray':
2001 TypedListTypeData('int'),
2002 'Uint16Array':
2003 TypedListTypeData('int'),
2004 'Uint32Array':
2005 TypedListTypeData('int'),
2006 'ArrayBufferView':
2007 TypeData(clazz='BasicTypedList'),
2008 'ArrayBuffer':
2009 TypeData(clazz='BasicTypedList'),
2010 'SVGAngle':
2011 TypeData(
2012 clazz='SVGTearOff', native_type='SVGPropertyTearOff<SVGAngle>'),
2013 'SVGLength':
2014 TypeData(clazz='SVGTearOff', native_type='SVGLengthTearOff'),
2015 'SVGLengthList':
2016 TypeData(
2017 clazz='SVGTearOff',
2018 item_type='SVGLength',
2019 native_type='SVGLengthListTearOff'),
2020 'SVGMatrix':
2021 TypeData(clazz='SVGTearOff', native_type='SVGMatrixTearOff'),
2022 'SVGNumber':
2023 TypeData(clazz='SVGTearOff', native_type='SVGNumberTearOff'),
2024 'SVGNumberList':
2025 TypeData(
2026 clazz='SVGTearOff',
2027 item_type='SVGNumber',
2028 native_type='SVGNumberListTearOff'),
2029 'SVGPathSegList':
2030 TypeData(
2031 clazz='SVGTearOff',
2032 item_type='SVGPathSeg',
2033 native_type='SVGPathSegListPropertyTearOff'),
2034 'SVGPoint':
2035 TypeData(clazz='SVGTearOff', native_type='SVGPointTearOff'),
2036 'SVGPointList':
2037 TypeData(clazz='SVGTearOff', native_type='SVGPointListTearOff'),
2038 'SVGPreserveAspectRatio':
2039 TypeData(
2040 clazz='SVGTearOff', native_type='SVGPreserveAspectRatioTearOff'),
2041 'SVGRect':
2042 TypeData(clazz='SVGTearOff', native_type='SVGRectTearOff'),
2043 'SVGStringList':
2044 TypeData(
2045 clazz='SVGTearOff',
2046 item_type='DOMString',
2047 native_type='SVGStringListTearOff'),
2048 'SVGTransform':
2049 TypeData(
2050 clazz='SVGTearOff', native_type="SVGPropertyTearOff<SVGTransform>"),
2051 'SVGTransformList':
2052 TypeData(
2053 clazz='SVGTearOff',
2054 item_type='SVGTransform',
2055 native_type='SVGTransformListPropertyTearOff'),
2056
2057 # Add any setlike forEach Callback types here.
2058 'FontFaceSetForEachCallback':
2059 TypeData(clazz='Interface', item_type='FontFaceSetForEachCallback'),
2060 })
2061
2062_svg_supplemental_includes = [
2063 '"core/svg/properties/SVGPropertyTraits.h"',
2064]
2065
2066
2067class TypeRegistry(object):
2068
2069 def __init__(self, database, renamer=None):
2070 self._database = database
2071 self._renamer = renamer
2072 self._cache = {}
2073
2074 def HasInterface(self, type_name):
2075 return self._database.HasInterface(type_name)
2076
2077 def HasTypeDef(self, type_def_name):
2078 return self._database.HasTypeDef(type_def_name)
2079
2080 def TypeInfo(self, type_name):
2081 if not type_name in self._cache:
2082 self._cache[type_name] = self._TypeInfo(type_name)
2083 return self._cache[type_name]
2084
2085 def DartType(self, type_name):
2086 return self.TypeInfo(type_name).dart_type()
2087
2088 def _TypeInfo(self, type_name):
2089 match = re.match(r'(?:sequence<([\w ]+)>|(\w+)\[\])$', type_name)
2090
2091 if match and self._database.HasDictionary(match.group(1)):
2092 interface = self._database.GetDictionary(match.group(1))
2093
2094 # sequence<any> should not be List<Object>
2095 if match and match.group(1) != 'any' and not (
2096 self._database.HasDictionary(match.group(1))):
2097 type_data = TypeData('Sequence')
2098 if self.HasTypeDef(match.group(1) or match.group(2)):
2099 # It's a typedef (union)
2100 item_info = self.TypeInfo('any')
2101 else:
2102 item_info = self.TypeInfo(match.group(1) or match.group(2))
2103 # TODO(vsm): Generalize this code.
2104 if 'SourceInfo' in type_name:
2105 type_data.native_type = 'const Vector<RefPtr<SourceInfo> >& '
2106 return SequenceIDLTypeInfo(type_name, type_data, item_info)
2107
2108 if not type_name in _idl_type_registry:
2109 if self._database.HasEnum(type_name):
2110 return PrimitiveIDLTypeInfo(
2111 type_name,
2112 TypeData(
2113 clazz='Primitive',
2114 dart_type='String',
2115 native_type='String'))
2116 if self._database.HasInterface(type_name):
2117 interface = self._database.GetInterface(type_name)
2118 elif self._database.HasDictionary(type_name):
2119 type_data = _idl_type_registry.get('Dictionary')
2120 class_name = '%sIDLTypeInfo' % type_data.clazz
2121 return globals()[class_name](type_name, type_data)
2122 elif type_name.startswith('sequence<('):
2123 if type_name.find(' or ') != -1:
2124 # Union type of sequence is an any type (no type).
2125 type_data = TypeData('Sequence')
2126 item_info = self.TypeInfo('any')
2127 return SequenceIDLTypeInfo(type_name, type_data, item_info)
2128 elif match and self._database.HasDictionary(match.group(1)):
2129 return SequenceIDLTypeInfo(type_name, TypeData('Sequence'),
2130 self.TypeInfo(match.group(1)))
2131 elif type_name.startswith('sequence<sequence<'):
2132 # TODO(terry): Cleanup up list of list, etc.
2133 type_data = TypeData('Sequence')
2134 item_info = self.TypeInfo('any')
2135 return SequenceIDLTypeInfo(type_name, type_data, item_info)
2136 elif self.HasTypeDef(type_name):
2137 # It's a typedef (implied union)
2138 return self.TypeInfo('any')
2139 else:
2140 print("ERROR: Unexpected interface, or type not found. %s" %
2141 type_name)
2142
2143 if 'Callback' in interface.ext_attrs:
2144 return CallbackIDLTypeInfo(
2145 type_name,
2146 TypeData('Callback',
2147 self._renamer.DartifyTypeName(type_name)))
2148 return InterfaceIDLTypeInfo(
2149 type_name, TypeData('Interface'),
2150 self._renamer.RenameInterface(interface), self)
2151
2152 if (self._database.HasDictionary(type_name)):
2153 type_data = _idl_type_registry.get('Dictionary')
2154 else:
2155 type_data = _idl_type_registry.get(type_name)
2156
2157 if type_data.clazz == 'Interface':
2158 if self._database.HasInterface(type_name):
2159 dart_interface_name = self._renamer.RenameInterface(
2160 self._database.GetInterface(type_name))
2161 else:
2162 dart_interface_name = self._renamer.DartifyTypeName(type_name)
2163 return InterfaceIDLTypeInfo(type_name, type_data,
2164 dart_interface_name, self)
2165
2166 if type_data.clazz == 'SVGTearOff':
2167 dart_interface_name = self._renamer.RenameInterface(
2168 self._database.GetInterface(type_name))
2169 return SVGTearOffIDLTypeInfo(type_name, type_data,
2170 dart_interface_name, self)
2171
2172 if type_data.clazz == 'TypedList':
2173 dart_interface_name = self._renamer.RenameInterfaceId(type_name)
2174 return TypedListIDLTypeInfo(type_name, type_data,
2175 dart_interface_name, self)
2176
2177 if type_data.clazz == 'BasicTypedList':
2178 if type_name == 'ArrayBuffer':
2179 dart_interface_name = 'ByteBuffer'
2180 else:
2181 dart_interface_name = self._renamer.RenameInterfaceId(type_name)
2182 return BasicTypedListIDLTypeInfo(type_name, type_data,
2183 dart_interface_name, self)
2184
2185 class_name = '%sIDLTypeInfo' % type_data.clazz
2186 return globals()[class_name](type_name, type_data)
2187
2188
2189def isList(return_type):
2190 return return_type.startswith('List<') if return_type else False
2191
2192
2193def get_list_type(return_type):
2194 # Get the list type NNNN inside of List<NNNN>
2195 return return_type[5:-1] if isList(return_type) else return_type
2196
2197
2198# TODO(jacobr): remove these obsolete methods as we don't actually
2199# perform any wrapping.
2200def wrap_unwrap_list_blink(return_type, type_registry):
2201 """Return True if the type is the list type is a blink know
2202 type e.g., List<Node>, List<FontFace>, etc."""
2203 if isList(return_type):
2204 list_type = get_list_type(return_type)
2205 if type_registry.HasInterface(list_type):
2206 return True
2207
2208
2209def wrap_unwrap_type_blink(return_type, type_registry):
2210 """Returns True if the type is a blink type that requires wrap_jso or
2211 unwrap_jso"""
2212 if return_type and return_type.startswith('Html'):
2213 return_type = return_type.replace('Html', 'HTML', 1)
2214 return (not (return_type) or return_type == 'Object' or
2215 return_type == 'dynamic')
2216
2217
2218def wrap_type_blink(return_type, type_registry):
2219 """Returns True if the type is a blink type that requires wrap_jso but
2220 NOT unwrap_jso"""
2221 return (return_type == 'Map' or return_type == 'Rectangle')
2222
2223
2224def wrap_return_type_blink(return_type, type_name, type_registry):
2225 """Returns True if we should wrap the returned value. This checks
2226 a number of different variations, calling the more basic functions
2227 above."""
2228 return (wrap_unwrap_type_blink(return_type, type_registry) or
2229 wrap_unwrap_type_blink(type_name, type_registry) or
2230 wrap_type_blink(return_type, type_registry) or
2231 wrap_unwrap_list_blink(return_type, type_registry))
GLenum type
uint32_t uint32_t * format
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not set
Definition: switches.h:76
def print(*args, **kwargs)
Definition: run_tests.py:49
def array_type(data_type)
Definition: systemnative.py:28
SI auto map(std::index_sequence< I... >, Fn &&fn, const Args &... args) -> skvx::Vec< sizeof...(I), decltype(fn(args[0]...))>
Definition: SkVx.h:680
SIT bool any(const Vec< 1, T > &x)
Definition: SkVx.h:530
static SkString join(const CommandLineFlags::StringArray &)
Definition: skpbench.cpp:741