OLD | NEW |
1 # Copyright (C) 2013 Google Inc. All rights reserved. | 1 # Copyright (C) 2013 Google Inc. All rights reserved. |
2 # coding=utf-8 | 2 # coding=utf-8 |
3 # | 3 # |
4 # Redistribution and use in source and binary forms, with or without | 4 # Redistribution and use in source and binary forms, with or without |
5 # modification, are permitted provided that the following conditions are | 5 # modification, are permitted provided that the following conditions are |
6 # met: | 6 # met: |
7 # | 7 # |
8 # * Redistributions of source code must retain the above copyright | 8 # * Redistributions of source code must retain the above copyright |
9 # notice, this list of conditions and the following disclaimer. | 9 # notice, this list of conditions and the following disclaimer. |
10 # * Redistributions in binary form must reproduce the above | 10 # * Redistributions in binary form must reproduce the above |
(...skipping 19 matching lines...) Expand all Loading... |
30 """Generate template values for an interface. | 30 """Generate template values for an interface. |
31 | 31 |
32 Design doc: http://www.chromium.org/developers/design-documents/idl-compiler | 32 Design doc: http://www.chromium.org/developers/design-documents/idl-compiler |
33 """ | 33 """ |
34 | 34 |
35 from collections import defaultdict | 35 from collections import defaultdict |
36 import itertools | 36 import itertools |
37 from operator import itemgetter | 37 from operator import itemgetter |
38 | 38 |
39 import idl_definitions | 39 import idl_definitions |
40 from idl_definitions import IdlOperation | 40 from idl_definitions import IdlOperation, IdlArgument |
41 import idl_types | 41 import idl_types |
42 from idl_types import IdlType, inherits_interface | 42 from idl_types import IdlType, inherits_interface |
43 import v8_attributes | 43 import v8_attributes |
44 from v8_globals import includes | 44 from v8_globals import includes |
45 import v8_methods | 45 import v8_methods |
46 import v8_types | 46 import v8_types |
47 from v8_types import cpp_ptr_type, cpp_template_type | 47 from v8_types import cpp_ptr_type, cpp_template_type |
48 import v8_utilities | 48 import v8_utilities |
49 from v8_utilities import (capitalize, conditional_string, cpp_name, gc_type, | 49 from v8_utilities import (cpp_name_or_partial, capitalize, conditional_string, c
pp_name, gc_type, |
50 has_extended_attribute_value, runtime_enabled_function
_name, | 50 has_extended_attribute_value, runtime_enabled_function
_name, |
51 extended_attribute_value_as_list) | 51 extended_attribute_value_as_list, is_legacy_interface_
type_checking) |
52 | 52 |
53 | 53 |
54 INTERFACE_H_INCLUDES = frozenset([ | 54 INTERFACE_H_INCLUDES = frozenset([ |
55 'bindings/common/ScriptWrappable.h', | 55 'bindings/core/v8/ScriptWrappable.h', |
| 56 'bindings/core/v8/ToV8.h', |
56 'bindings/core/v8/V8Binding.h', | 57 'bindings/core/v8/V8Binding.h', |
57 'bindings/core/v8/V8DOMWrapper.h', | 58 'bindings/core/v8/V8DOMWrapper.h', |
58 'bindings/core/v8/WrapperTypeInfo.h', | 59 'bindings/core/v8/WrapperTypeInfo.h', |
59 'platform/heap/Handle.h', | 60 'platform/heap/Handle.h', |
60 ]) | 61 ]) |
61 INTERFACE_CPP_INCLUDES = frozenset([ | 62 INTERFACE_CPP_INCLUDES = frozenset([ |
62 'bindings/core/v8/V8ExceptionState.h', | 63 'bindings/core/v8/ExceptionState.h', |
63 'bindings/core/v8/V8DOMConfiguration.h', | 64 'bindings/core/v8/V8DOMConfiguration.h', |
64 'bindings/core/v8/V8HiddenValue.h', | |
65 'bindings/core/v8/V8ObjectConstructor.h', | 65 'bindings/core/v8/V8ObjectConstructor.h', |
66 'core/dom/ContextFeatures.h', | 66 'core/dom/ContextFeatures.h', |
67 'core/dom/Document.h', | 67 'core/dom/Document.h', |
68 'platform/RuntimeEnabledFeatures.h', | 68 'platform/RuntimeEnabledFeatures.h', |
69 'platform/TraceEvent.h', | 69 'platform/TraceEvent.h', |
70 'wtf/GetPtr.h', | 70 'wtf/GetPtr.h', |
71 'wtf/RefPtr.h', | 71 'wtf/RefPtr.h', |
72 ]) | 72 ]) |
73 | 73 |
74 | 74 |
75 def interface_context(interface): | 75 def interface_context(interface): |
76 includes.clear() | 76 includes.clear() |
77 includes.update(INTERFACE_CPP_INCLUDES) | 77 includes.update(INTERFACE_CPP_INCLUDES) |
78 header_includes = set(INTERFACE_H_INCLUDES) | 78 header_includes = set(INTERFACE_H_INCLUDES) |
79 | 79 |
80 parent_interface = interface.parent | 80 if interface.is_partial: |
81 if parent_interface: | 81 # A partial interface definition cannot specify that the interface |
82 header_includes.update(v8_types.includes_for_interface(parent_interface)
) | 82 # inherits from another interface. Inheritance must be specified on |
| 83 # the original interface definition. |
| 84 parent_interface = None |
| 85 is_event_target = False |
| 86 # partial interface needs the definition of its original interface. |
| 87 includes.add('bindings/core/v8/V8%s.h' % interface.name) |
| 88 else: |
| 89 parent_interface = interface.parent |
| 90 if parent_interface: |
| 91 header_includes.update(v8_types.includes_for_interface(parent_interf
ace)) |
| 92 is_event_target = inherits_interface(interface.name, 'EventTarget') |
| 93 |
83 extended_attributes = interface.extended_attributes | 94 extended_attributes = interface.extended_attributes |
84 | 95 |
85 is_audio_buffer = inherits_interface(interface.name, 'AudioBuffer') | 96 is_array_buffer_or_view = interface.idl_type.is_array_buffer_or_view |
86 if is_audio_buffer: | 97 is_typed_array_type = interface.idl_type.is_typed_array |
87 includes.add('modules/webaudio/AudioBuffer.h') | 98 if is_array_buffer_or_view: |
88 | 99 includes.add('bindings/core/v8/V8ArrayBuffer.h') |
89 is_document = inherits_interface(interface.name, 'Document') | 100 if interface.name == 'ArrayBufferView': |
90 if is_document: | 101 includes.update(( |
91 includes.update(['bindings/core/v8/ScriptController.h', | 102 'bindings/core/v8/V8Int8Array.h', |
92 'bindings/core/v8/WindowProxy.h', | 103 'bindings/core/v8/V8Int16Array.h', |
93 'core/frame/LocalFrame.h']) | 104 'bindings/core/v8/V8Int32Array.h', |
| 105 'bindings/core/v8/V8Uint8Array.h', |
| 106 'bindings/core/v8/V8Uint8ClampedArray.h', |
| 107 'bindings/core/v8/V8Uint16Array.h', |
| 108 'bindings/core/v8/V8Uint32Array.h', |
| 109 'bindings/core/v8/V8Float32Array.h', |
| 110 'bindings/core/v8/V8Float64Array.h', |
| 111 'bindings/core/v8/V8DataView.h')) |
94 | 112 |
95 # [ActiveDOMObject] | 113 # [ActiveDOMObject] |
96 is_active_dom_object = 'ActiveDOMObject' in extended_attributes | 114 is_active_dom_object = 'ActiveDOMObject' in extended_attributes |
97 | 115 |
98 # [CheckSecurity] | 116 # [CheckSecurity] |
99 is_check_security = 'CheckSecurity' in extended_attributes | 117 is_check_security = 'CheckSecurity' in extended_attributes |
100 if is_check_security: | 118 if is_check_security: |
101 includes.add('bindings/common/BindingSecurity.h') | 119 includes.add('bindings/core/v8/BindingSecurity.h') |
102 | 120 |
103 # [DependentLifetime] | 121 # [DependentLifetime] |
104 is_dependent_lifetime = 'DependentLifetime' in extended_attributes | 122 is_dependent_lifetime = 'DependentLifetime' in extended_attributes |
105 | 123 |
106 # [Iterable] | |
107 iterator_method = None | |
108 if 'Iterable' in extended_attributes: | |
109 iterator_operation = IdlOperation(interface.idl_name) | |
110 iterator_operation.name = 'iterator' | |
111 iterator_operation.idl_type = IdlType('Iterator') | |
112 iterator_operation.extended_attributes['RaisesException'] = None | |
113 iterator_operation.extended_attributes['CallWith'] = 'ScriptState' | |
114 iterator_method = v8_methods.method_context(interface, | |
115 iterator_operation) | |
116 | |
117 # [MeasureAs] | 124 # [MeasureAs] |
118 is_measure_as = 'MeasureAs' in extended_attributes | 125 is_measure_as = 'MeasureAs' in extended_attributes |
119 if is_measure_as: | 126 if is_measure_as: |
120 includes.add('core/frame/UseCounter.h') | 127 includes.add('core/frame/UseCounter.h') |
121 | 128 |
122 # [SetWrapperReferenceFrom] | 129 # [SetWrapperReferenceFrom] |
123 reachable_node_function = extended_attributes.get('SetWrapperReferenceFrom') | 130 set_wrapper_reference_from = extended_attributes.get('SetWrapperReferenceFro
m') |
124 if reachable_node_function: | 131 if set_wrapper_reference_from: |
125 includes.update(['bindings/core/v8/V8GCController.h', | 132 includes.update(['bindings/core/v8/V8GCController.h', |
126 'core/dom/Element.h']) | 133 'core/dom/Element.h']) |
127 | 134 |
128 # [SetWrapperReferenceTo] | 135 # [SetWrapperReferenceTo] |
129 set_wrapper_reference_to_list = [{ | 136 set_wrapper_reference_to_argument = extended_attributes.get('SetWrapperRefer
enceTo') |
130 'name': argument.name, | 137 set_wrapper_reference_to = None |
131 # FIXME: properly should be: | 138 if set_wrapper_reference_to_argument: |
132 # 'cpp_type': argument.idl_type.cpp_type_args(raw_type=True), | 139 set_wrapper_reference_to = { |
133 # (if type is non-wrapper type like NodeFilter, normally RefPtr) | 140 'name': set_wrapper_reference_to_argument.name, |
134 # Raw pointers faster though, and NodeFilter hacky anyway. | 141 # FIXME: properly should be: |
135 'cpp_type': argument.idl_type.implemented_as + '*', | 142 # 'cpp_type': set_wrapper_reference_to_argument.idl_type.cpp_type_ar
gs(raw_type=True), |
136 'idl_type': argument.idl_type, | 143 # (if type is non-wrapper type like NodeFilter, normally RefPtr) |
137 'v8_type': v8_types.v8_type(argument.idl_type.name), | 144 # Raw pointers faster though, and NodeFilter hacky anyway. |
138 } for argument in extended_attributes.get('SetWrapperReferenceTo', [])] | 145 'cpp_type': set_wrapper_reference_to_argument.idl_type.implemented_a
s + '*', |
139 for set_wrapper_reference_to in set_wrapper_reference_to_list: | 146 'idl_type': set_wrapper_reference_to_argument.idl_type, |
| 147 'v8_type': v8_types.v8_type(set_wrapper_reference_to_argument.idl_ty
pe.name), |
| 148 } |
140 set_wrapper_reference_to['idl_type'].add_includes_for_type() | 149 set_wrapper_reference_to['idl_type'].add_includes_for_type() |
141 | 150 |
142 # [NotScriptWrappable] | 151 # [SetWrapperReferenceFrom] |
143 is_script_wrappable = 'NotScriptWrappable' not in extended_attributes | |
144 | |
145 # [SpecialWrapFor] | |
146 if 'SpecialWrapFor' in extended_attributes: | |
147 special_wrap_for = extended_attribute_value_as_list(interface, 'SpecialW
rapFor') | |
148 else: | |
149 special_wrap_for = [] | |
150 for special_wrap_interface in special_wrap_for: | |
151 v8_types.add_includes_for_interface(special_wrap_interface) | |
152 | |
153 # [Custom=Wrap], [SetWrapperReferenceFrom] | |
154 has_visit_dom_wrapper = ( | 152 has_visit_dom_wrapper = ( |
155 has_extended_attribute_value(interface, 'Custom', 'VisitDOMWrapper') or | 153 has_extended_attribute_value(interface, 'Custom', 'VisitDOMWrapper') or |
156 reachable_node_function or | 154 set_wrapper_reference_from or set_wrapper_reference_to) |
157 set_wrapper_reference_to_list) | |
158 | 155 |
159 this_gc_type = gc_type(interface) | 156 this_gc_type = gc_type(interface) |
160 | 157 |
161 wrapper_class_id = ('NodeClassId' if inherits_interface(interface.name, 'Nod
e') else 'ObjectClassId') | 158 wrapper_class_id = ('NodeClassId' if inherits_interface(interface.name, 'Nod
e') else 'ObjectClassId') |
162 | 159 |
| 160 v8_class_name = v8_utilities.v8_class_name(interface) |
| 161 cpp_class_name = cpp_name(interface) |
| 162 cpp_class_name_or_partial = cpp_name_or_partial(interface) |
| 163 v8_class_name_or_partial = v8_utilities.v8_class_name_or_partial(interface) |
| 164 |
163 context = { | 165 context = { |
164 'conditional_string': conditional_string(interface), # [Conditional] | 166 'conditional_string': conditional_string(interface), # [Conditional] |
165 'cpp_class': cpp_name(interface), | 167 'cpp_class': cpp_class_name, |
| 168 'cpp_class_or_partial': cpp_class_name_or_partial, |
| 169 'event_target_inheritance': 'InheritFromEventTarget' if is_event_target
else 'NotInheritFromEventTarget', |
166 'gc_type': this_gc_type, | 170 'gc_type': this_gc_type, |
167 # FIXME: Remove 'EventTarget' special handling, http://crbug.com/383699 | 171 # FIXME: Remove 'EventTarget' special handling, http://crbug.com/383699 |
168 'has_access_check_callbacks': (is_check_security and | 172 'has_access_check_callbacks': (is_check_security and |
169 interface.name != 'Window' and | 173 interface.name != 'Window' and |
170 interface.name != 'EventTarget'), | 174 interface.name != 'EventTarget'), |
171 'has_custom_legacy_call_as_function': has_extended_attribute_value(inter
face, 'Custom', 'LegacyCallAsFunction'), # [Custom=LegacyCallAsFunction] | 175 'has_custom_legacy_call_as_function': has_extended_attribute_value(inter
face, 'Custom', 'LegacyCallAsFunction'), # [Custom=LegacyCallAsFunction] |
172 'has_custom_to_v8': has_extended_attribute_value(interface, 'Custom', 'T
oV8'), # [Custom=ToV8] | 176 'has_partial_interface': len(interface.partial_interfaces) > 0, |
173 'has_custom_wrap': has_extended_attribute_value(interface, 'Custom', 'Wr
ap'), # [Custom=Wrap] | |
174 'has_visit_dom_wrapper': has_visit_dom_wrapper, | 177 'has_visit_dom_wrapper': has_visit_dom_wrapper, |
175 'header_includes': header_includes, | 178 'header_includes': header_includes, |
176 'interface_name': interface.name, | 179 'interface_name': interface.name, |
177 'is_active_dom_object': is_active_dom_object, | 180 'is_active_dom_object': is_active_dom_object, |
178 'is_audio_buffer': is_audio_buffer, | 181 'is_array_buffer_or_view': is_array_buffer_or_view, |
179 'is_check_security': is_check_security, | 182 'is_check_security': is_check_security, |
180 'is_dependent_lifetime': is_dependent_lifetime, | 183 'is_event_target': is_event_target, |
181 'is_document': is_document, | |
182 'is_event_target': inherits_interface(interface.name, 'EventTarget'), | |
183 'is_exception': interface.is_exception, | 184 'is_exception': interface.is_exception, |
184 'is_node': inherits_interface(interface.name, 'Node'), | 185 'is_node': inherits_interface(interface.name, 'Node'), |
185 'is_script_wrappable': is_script_wrappable, | 186 'is_partial': interface.is_partial, |
186 'iterator_method': iterator_method, | 187 'is_typed_array_type': is_typed_array_type, |
187 'lifetime': 'Dependent' | 188 'lifetime': 'Dependent' |
188 if (has_visit_dom_wrapper or | 189 if (has_visit_dom_wrapper or |
189 is_active_dom_object or | 190 is_active_dom_object or |
190 is_dependent_lifetime) | 191 is_dependent_lifetime) |
191 else 'Independent', | 192 else 'Independent', |
192 'measure_as': v8_utilities.measure_as(interface), # [MeasureAs] | 193 'measure_as': v8_utilities.measure_as(interface, None), # [MeasureAs] |
193 'parent_interface': parent_interface, | 194 'parent_interface': parent_interface, |
194 'pass_cpp_type': cpp_template_type( | 195 'pass_cpp_type': cpp_template_type( |
195 cpp_ptr_type('PassRefPtr', 'RawPtr', this_gc_type), | 196 cpp_ptr_type('PassRefPtr', 'RawPtr', this_gc_type), |
196 cpp_name(interface)), | 197 cpp_name(interface)), |
197 'reachable_node_function': reachable_node_function, | |
198 'runtime_enabled_function': runtime_enabled_function_name(interface), #
[RuntimeEnabled] | 198 'runtime_enabled_function': runtime_enabled_function_name(interface), #
[RuntimeEnabled] |
199 'set_wrapper_reference_to_list': set_wrapper_reference_to_list, | 199 'set_wrapper_reference_from': set_wrapper_reference_from, |
200 'special_wrap_for': special_wrap_for, | 200 'set_wrapper_reference_to': set_wrapper_reference_to, |
201 'v8_class': v8_utilities.v8_class_name(interface), | 201 'v8_class': v8_class_name, |
| 202 'v8_class_or_partial': v8_class_name_or_partial, |
202 'wrapper_class_id': wrapper_class_id, | 203 'wrapper_class_id': wrapper_class_id, |
203 } | 204 } |
204 | 205 |
205 # Constructors | 206 # Constructors |
206 constructors = [constructor_context(interface, constructor) | 207 constructors = [constructor_context(interface, constructor) |
207 for constructor in interface.constructors | 208 for constructor in interface.constructors |
208 # FIXME: shouldn't put named constructors with constructors | 209 # FIXME: shouldn't put named constructors with constructors |
209 # (currently needed for Perl compatibility) | 210 # (currently needed for Perl compatibility) |
210 # Handle named constructors separately | 211 # Handle named constructors separately |
211 if constructor.name == 'Constructor'] | 212 if constructor.name == 'Constructor'] |
212 if len(constructors) > 1: | 213 if len(constructors) > 1: |
213 context['constructor_overloads'] = overloads_context(constructors) | 214 context['constructor_overloads'] = overloads_context(interface, construc
tors) |
214 | 215 |
215 # [CustomConstructor] | 216 # [CustomConstructor] |
216 custom_constructors = [{ # Only needed for computing interface length | 217 custom_constructors = [{ # Only needed for computing interface length |
217 'number_of_required_arguments': | 218 'number_of_required_arguments': |
218 number_of_required_arguments(constructor), | 219 number_of_required_arguments(constructor), |
219 } for constructor in interface.custom_constructors] | 220 } for constructor in interface.custom_constructors] |
220 | 221 |
221 # [EventConstructor] | |
222 has_event_constructor = 'EventConstructor' in extended_attributes | |
223 any_type_attributes = [attribute for attribute in interface.attributes | |
224 if attribute.idl_type.name == 'Any'] | |
225 if has_event_constructor: | |
226 includes.add('bindings/core/v8/Dictionary.h') | |
227 if any_type_attributes: | |
228 includes.add('bindings/core/v8/SerializedScriptValue.h') | |
229 | |
230 # [NamedConstructor] | 222 # [NamedConstructor] |
231 named_constructor = named_constructor_context(interface) | 223 named_constructor = named_constructor_context(interface) |
232 | 224 |
233 if (constructors or custom_constructors or has_event_constructor or | 225 if constructors or custom_constructors or named_constructor: |
234 named_constructor): | 226 if interface.is_partial: |
| 227 raise Exception('[Constructor] and [NamedConstructor] MUST NOT be' |
| 228 ' specified on partial interface definitions:' |
| 229 '%s' % interface.name) |
| 230 |
235 includes.add('bindings/core/v8/V8ObjectConstructor.h') | 231 includes.add('bindings/core/v8/V8ObjectConstructor.h') |
236 includes.add('core/frame/LocalDOMWindow.h') | 232 includes.add('core/frame/LocalDOMWindow.h') |
237 | 233 |
| 234 # [Unscopeable] attributes and methods |
| 235 unscopeables = [] |
| 236 for attribute in interface.attributes: |
| 237 if 'Unscopeable' in attribute.extended_attributes: |
| 238 unscopeables.append((attribute.name, v8_utilities.runtime_enabled_fu
nction_name(attribute))) |
| 239 for method in interface.operations: |
| 240 if 'Unscopeable' in method.extended_attributes: |
| 241 unscopeables.append((method.name, v8_utilities.runtime_enabled_funct
ion_name(method))) |
| 242 |
238 context.update({ | 243 context.update({ |
239 'any_type_attributes': any_type_attributes, | |
240 'constructors': constructors, | 244 'constructors': constructors, |
241 'has_custom_constructor': bool(custom_constructors), | 245 'has_custom_constructor': bool(custom_constructors), |
242 'has_event_constructor': has_event_constructor, | |
243 'interface_length': | 246 'interface_length': |
244 interface_length(interface, constructors + custom_constructors), | 247 interface_length(interface, constructors + custom_constructors), |
245 'is_constructor_raises_exception': extended_attributes.get('RaisesExcept
ion') == 'Constructor', # [RaisesException=Constructor] | 248 'is_constructor_raises_exception': extended_attributes.get('RaisesExcept
ion') == 'Constructor', # [RaisesException=Constructor] |
246 'named_constructor': named_constructor, | 249 'named_constructor': named_constructor, |
| 250 'unscopeables': sorted(unscopeables), |
247 }) | 251 }) |
248 | 252 |
249 constants = [constant_context(constant) for constant in interface.constants] | 253 constants = [constant_context(constant, interface) for constant in interface
.constants] |
250 | 254 |
251 special_getter_constants = [] | 255 special_getter_constants = [] |
252 runtime_enabled_constants = [] | 256 runtime_enabled_constants = [] |
253 constant_configuration_constants = [] | 257 constant_configuration_constants = [] |
254 | 258 |
255 for constant in constants: | 259 for constant in constants: |
256 if constant['measure_as'] or constant['deprecate_as']: | 260 if constant['measure_as'] or constant['deprecate_as']: |
257 special_getter_constants.append(constant) | 261 special_getter_constants.append(constant) |
258 continue | 262 continue |
259 if constant['runtime_enabled_function']: | 263 if constant['runtime_enabled_function']: |
260 runtime_enabled_constants.append(constant) | 264 runtime_enabled_constants.append(constant) |
261 continue | 265 continue |
262 constant_configuration_constants.append(constant) | 266 constant_configuration_constants.append(constant) |
263 | 267 |
264 # Constants | 268 # Constants |
265 context.update({ | 269 context.update({ |
266 'constant_configuration_constants': constant_configuration_constants, | 270 'constant_configuration_constants': constant_configuration_constants, |
267 'constants': constants, | 271 'constants': constants, |
268 'do_not_check_constants': 'DoNotCheckConstants' in extended_attributes, | 272 'do_not_check_constants': 'DoNotCheckConstants' in extended_attributes, |
269 'has_constant_configuration': any( | 273 'has_constant_configuration': any( |
270 not constant['runtime_enabled_function'] | 274 not constant['runtime_enabled_function'] |
271 for constant in constants), | 275 for constant in constants), |
272 'runtime_enabled_constants': runtime_enabled_constants, | 276 'runtime_enabled_constants': runtime_enabled_constants, |
273 'special_getter_constants': special_getter_constants, | 277 'special_getter_constants': special_getter_constants, |
274 }) | 278 }) |
275 | 279 |
276 # Attributes | 280 # Attributes |
277 attributes = [v8_attributes.attribute_context(interface, attribute) | 281 attributes = [v8_attributes.attribute_context(interface, attribute) |
278 for attribute in interface.attributes | 282 for attribute in interface.attributes] |
279 if not v8_utilities.dart_custom_method(attribute.extended_attr
ibutes)] | 283 |
| 284 has_conditional_attributes = any(attribute['exposed_test'] for attribute in
attributes) |
| 285 if has_conditional_attributes and interface.is_partial: |
| 286 raise Exception('Conditional attributes between partial interfaces in mo
dules and the original interfaces(%s) in core are not allowed.' % interface.name
) |
| 287 |
280 context.update({ | 288 context.update({ |
281 'attributes': attributes, | 289 'attributes': attributes, |
282 'has_accessors': any(attribute['is_expose_js_accessors'] and attribute['
should_be_exposed_to_script'] for attribute in attributes), | 290 'has_accessor_configuration': any( |
| 291 attribute['is_expose_js_accessors'] and |
| 292 not (attribute['is_static'] or |
| 293 attribute['runtime_enabled_function']) and |
| 294 attribute['should_be_exposed_to_script'] |
| 295 for attribute in attributes), |
283 'has_attribute_configuration': any( | 296 'has_attribute_configuration': any( |
284 not (attribute['is_expose_js_accessors'] or | 297 not (attribute['is_expose_js_accessors'] or |
285 attribute['is_static'] or | 298 attribute['is_static'] or |
286 attribute['runtime_enabled_function'] or | 299 attribute['runtime_enabled_function']) |
287 attribute['per_context_enabled_function']) | |
288 and attribute['should_be_exposed_to_script'] | 300 and attribute['should_be_exposed_to_script'] |
289 for attribute in attributes), | 301 for attribute in attributes), |
290 'has_conditional_attributes': any(attribute['per_context_enabled_functio
n'] or attribute['exposed_test'] for attribute in attributes), | |
291 'has_constructor_attributes': any(attribute['constructor_type'] for attr
ibute in attributes), | 302 'has_constructor_attributes': any(attribute['constructor_type'] for attr
ibute in attributes), |
292 'has_replaceable_attributes': any(attribute['is_replaceable'] for attrib
ute in attributes), | 303 'has_replaceable_attributes': any(attribute['is_replaceable'] for attrib
ute in attributes), |
293 }) | 304 }) |
294 | 305 |
295 # Methods | 306 # Methods |
296 methods = [v8_methods.method_context(interface, method) | 307 methods = [] |
297 for method in interface.operations | 308 if interface.original_interface: |
298 if (method.name and # Skip anonymous special operations (methods
) | 309 methods.extend([v8_methods.method_context(interface, operation, is_visib
le=False) |
299 not v8_utilities.dart_custom_method(method.extended_attribute
s))] | 310 for operation in interface.original_interface.operations |
300 compute_method_overloads_context(methods) | 311 if operation.name]) |
| 312 methods.extend([v8_methods.method_context(interface, method) |
| 313 for method in interface.operations |
| 314 if method.name]) # Skip anonymous special operations (metho
ds) |
| 315 if interface.partial_interfaces: |
| 316 assert len(interface.partial_interfaces) == len(set(interface.partial_in
terfaces)) |
| 317 for partial_interface in interface.partial_interfaces: |
| 318 methods.extend([v8_methods.method_context(interface, operation, is_v
isible=False) |
| 319 for operation in partial_interface.operations |
| 320 if operation.name]) |
| 321 compute_method_overloads_context(interface, methods) |
| 322 |
| 323 def generated_method(return_type, name, arguments=None, extended_attributes=
None, implemented_as=None): |
| 324 operation = IdlOperation(interface.idl_name) |
| 325 operation.idl_type = return_type |
| 326 operation.name = name |
| 327 if arguments: |
| 328 operation.arguments = arguments |
| 329 if extended_attributes: |
| 330 operation.extended_attributes.update(extended_attributes) |
| 331 if implemented_as is None: |
| 332 implemented_as = name + 'ForBinding' |
| 333 operation.extended_attributes['ImplementedAs'] = implemented_as |
| 334 return v8_methods.method_context(interface, operation) |
| 335 |
| 336 def generated_argument(idl_type, name, is_optional=False, extended_attribute
s=None): |
| 337 argument = IdlArgument(interface.idl_name) |
| 338 argument.idl_type = idl_type |
| 339 argument.name = name |
| 340 argument.is_optional = is_optional |
| 341 if extended_attributes: |
| 342 argument.extended_attributes.update(extended_attributes) |
| 343 return argument |
| 344 |
| 345 # [Iterable], iterable<>, maplike<> and setlike<> |
| 346 iterator_method = None |
| 347 # FIXME: support Iterable in partial interfaces. However, we don't |
| 348 # need to support iterator overloads between interface and |
| 349 # partial interface definitions. |
| 350 # http://heycam.github.io/webidl/#idl-overloading |
| 351 if (not interface.is_partial |
| 352 and (interface.iterable or interface.maplike or interface.setlike |
| 353 or 'Iterable' in extended_attributes)): |
| 354 |
| 355 used_extended_attributes = {} |
| 356 |
| 357 if interface.iterable: |
| 358 used_extended_attributes.update(interface.iterable.extended_attribut
es) |
| 359 elif interface.maplike: |
| 360 used_extended_attributes.update(interface.maplike.extended_attribute
s) |
| 361 elif interface.setlike: |
| 362 used_extended_attributes.update(interface.setlike.extended_attribute
s) |
| 363 |
| 364 if 'RaisesException' in used_extended_attributes: |
| 365 raise ValueError('[RaisesException] is implied for iterable<>/maplik
e<>/setlike<>') |
| 366 if 'CallWith' in used_extended_attributes: |
| 367 raise ValueError('[CallWith=ScriptState] is implied for iterable<>/m
aplike<>/setlike<>') |
| 368 |
| 369 used_extended_attributes.update({ |
| 370 'RaisesException': None, |
| 371 'CallWith': 'ScriptState', |
| 372 }) |
| 373 |
| 374 forEach_extended_attributes = used_extended_attributes.copy() |
| 375 forEach_extended_attributes.update({ |
| 376 'CallWith': ['ScriptState', 'ThisValue'], |
| 377 }) |
| 378 |
| 379 def generated_iterator_method(name, implemented_as=None): |
| 380 return generated_method( |
| 381 return_type=IdlType('Iterator'), |
| 382 name=name, |
| 383 extended_attributes=used_extended_attributes, |
| 384 implemented_as=implemented_as) |
| 385 |
| 386 iterator_method = generated_iterator_method('iterator', implemented_as='
iterator') |
| 387 |
| 388 if interface.iterable or interface.maplike or interface.setlike: |
| 389 implicit_methods = [ |
| 390 generated_iterator_method('keys'), |
| 391 generated_iterator_method('values'), |
| 392 generated_iterator_method('entries'), |
| 393 |
| 394 # void forEach(Function callback, [Default=Undefined] optional a
ny thisArg) |
| 395 generated_method(IdlType('void'), 'forEach', |
| 396 arguments=[generated_argument(IdlType('Function
'), 'callback'), |
| 397 generated_argument(IdlType('any'), '
thisArg', |
| 398 is_optional=True, |
| 399 extended_attribut
es={'Default': 'Undefined'})], |
| 400 extended_attributes=forEach_extended_attributes
), |
| 401 ] |
| 402 |
| 403 if interface.maplike: |
| 404 key_argument = generated_argument(interface.maplike.key_type, 'k
ey') |
| 405 value_argument = generated_argument(interface.maplike.value_type
, 'value') |
| 406 |
| 407 implicit_methods.extend([ |
| 408 generated_method(IdlType('boolean'), 'has', |
| 409 arguments=[key_argument], |
| 410 extended_attributes=used_extended_attribute
s), |
| 411 generated_method(IdlType('any'), 'get', |
| 412 arguments=[key_argument], |
| 413 extended_attributes=used_extended_attribute
s), |
| 414 ]) |
| 415 |
| 416 if not interface.maplike.is_read_only: |
| 417 implicit_methods.extend([ |
| 418 generated_method(IdlType('void'), 'clear', |
| 419 extended_attributes=used_extended_attri
butes), |
| 420 generated_method(IdlType('boolean'), 'delete', |
| 421 arguments=[key_argument], |
| 422 extended_attributes=used_extended_attri
butes), |
| 423 generated_method(IdlType(interface.name), 'set', |
| 424 arguments=[key_argument, value_argument
], |
| 425 extended_attributes=used_extended_attri
butes), |
| 426 ]) |
| 427 |
| 428 if interface.setlike: |
| 429 value_argument = generated_argument(interface.setlike.value_type
, 'value') |
| 430 |
| 431 implicit_methods.extend([ |
| 432 generated_method(IdlType('boolean'), 'has', |
| 433 arguments=[value_argument], |
| 434 extended_attributes=used_extended_attribute
s), |
| 435 ]) |
| 436 |
| 437 if not interface.setlike.is_read_only: |
| 438 implicit_methods.extend([ |
| 439 generated_method(IdlType(interface.name), 'add', |
| 440 arguments=[value_argument], |
| 441 extended_attributes=used_extended_attri
butes), |
| 442 generated_method(IdlType('void'), 'clear', |
| 443 extended_attributes=used_extended_attri
butes), |
| 444 generated_method(IdlType('boolean'), 'delete', |
| 445 arguments=[value_argument], |
| 446 extended_attributes=used_extended_attri
butes), |
| 447 ]) |
| 448 |
| 449 methods_by_name = {} |
| 450 for method in methods: |
| 451 methods_by_name.setdefault(method['name'], []).append(method) |
| 452 |
| 453 for implicit_method in implicit_methods: |
| 454 if implicit_method['name'] in methods_by_name: |
| 455 # FIXME: Check that the existing method is compatible. |
| 456 continue |
| 457 methods.append(implicit_method) |
| 458 |
| 459 # FIXME: maplike<> and setlike<> should also imply the presence of a |
| 460 # 'size' attribute. |
| 461 |
| 462 # Serializer |
| 463 if interface.serializer: |
| 464 serializer = interface.serializer |
| 465 serializer_ext_attrs = serializer.extended_attributes.copy() |
| 466 if serializer.operation: |
| 467 return_type = serializer.operation.idl_type |
| 468 implemented_as = serializer.operation.name |
| 469 else: |
| 470 return_type = IdlType('any') |
| 471 implemented_as = None |
| 472 if 'CallWith' not in serializer_ext_attrs: |
| 473 serializer_ext_attrs['CallWith'] = 'ScriptState' |
| 474 methods.append(generated_method( |
| 475 return_type=return_type, |
| 476 name='toJSON', |
| 477 extended_attributes=serializer_ext_attrs, |
| 478 implemented_as=implemented_as)) |
301 | 479 |
302 # Stringifier | 480 # Stringifier |
303 if interface.stringifier: | 481 if interface.stringifier: |
304 stringifier = interface.stringifier | 482 stringifier = interface.stringifier |
305 method = IdlOperation(interface.idl_name) | 483 stringifier_ext_attrs = stringifier.extended_attributes.copy() |
306 method.name = 'toString' | |
307 method.idl_type = IdlType('DOMString') | |
308 method.extended_attributes.update(stringifier.extended_attributes) | |
309 if stringifier.attribute: | 484 if stringifier.attribute: |
310 method.extended_attributes['ImplementedAs'] = stringifier.attribute.
name | 485 implemented_as = stringifier.attribute.name |
311 elif stringifier.operation: | 486 elif stringifier.operation: |
312 method.extended_attributes['ImplementedAs'] = stringifier.operation.
name | 487 implemented_as = stringifier.operation.name |
313 methods.append(v8_methods.method_context(interface, method)) | 488 else: |
| 489 implemented_as = 'toString' |
| 490 methods.append(generated_method( |
| 491 return_type=IdlType('DOMString'), |
| 492 name='toString', |
| 493 extended_attributes=stringifier_ext_attrs, |
| 494 implemented_as=implemented_as)) |
314 | 495 |
315 conditionally_enabled_methods = [] | 496 conditionally_enabled_methods = [] |
316 custom_registration_methods = [] | 497 custom_registration_methods = [] |
317 method_configuration_methods = [] | 498 method_configuration_methods = [] |
318 | 499 |
319 for method in methods: | 500 for method in methods: |
320 # Skip all but one method in each set of overloaded methods. | 501 # Skip all but one method in each set of overloaded methods. |
321 if 'overload_index' in method and 'overloads' not in method: | 502 if 'overload_index' in method and 'overloads' not in method: |
322 continue | 503 continue |
323 | 504 |
324 if 'overloads' in method: | 505 if 'overloads' in method: |
325 overloads = method['overloads'] | 506 overloads = method['overloads'] |
326 per_context_enabled_function = overloads['per_context_enabled_functi
on_all'] | 507 if not overloads['visible']: |
| 508 continue |
| 509 # original interface will register instead of partial interface. |
| 510 if overloads['has_partial_overloads'] and interface.is_partial: |
| 511 continue |
327 conditionally_exposed_function = overloads['exposed_test_all'] | 512 conditionally_exposed_function = overloads['exposed_test_all'] |
328 runtime_enabled_function = overloads['runtime_enabled_function_all'] | 513 runtime_enabled_function = overloads['runtime_enabled_function_all'] |
329 has_custom_registration = overloads['has_custom_registration_all'] | 514 has_custom_registration = (overloads['has_custom_registration_all']
or |
| 515 overloads['runtime_determined_lengths']) |
330 else: | 516 else: |
331 per_context_enabled_function = method['per_context_enabled_function'
] | 517 if not method['visible']: |
| 518 continue |
332 conditionally_exposed_function = method['exposed_test'] | 519 conditionally_exposed_function = method['exposed_test'] |
333 runtime_enabled_function = method['runtime_enabled_function'] | 520 runtime_enabled_function = method['runtime_enabled_function'] |
334 has_custom_registration = method['has_custom_registration'] | 521 has_custom_registration = method['has_custom_registration'] |
335 | 522 |
336 if per_context_enabled_function or conditionally_exposed_function: | 523 if has_custom_registration: |
| 524 custom_registration_methods.append(method) |
| 525 continue |
| 526 if conditionally_exposed_function: |
337 conditionally_enabled_methods.append(method) | 527 conditionally_enabled_methods.append(method) |
338 continue | 528 continue |
339 if runtime_enabled_function or has_custom_registration: | 529 if runtime_enabled_function: |
340 custom_registration_methods.append(method) | 530 custom_registration_methods.append(method) |
341 continue | 531 continue |
342 if method['should_be_exposed_to_script']: | 532 if method['should_be_exposed_to_script']: |
343 method_configuration_methods.append(method) | 533 method_configuration_methods.append(method) |
344 | 534 |
345 for method in methods: | 535 for method in methods: |
346 # The value of the Function object’s “length” property is a Number | 536 # The value of the Function object’s “length” property is a Number |
347 # determined as follows: | 537 # determined as follows: |
348 # 1. Let S be the effective overload set for regular operations (if the | 538 # 1. Let S be the effective overload set for regular operations (if the |
349 # operation is a regular operation) or for static operations (if the | 539 # operation is a regular operation) or for static operations (if the |
350 # operation is a static operation) with identifier id on interface I and | 540 # operation is a static operation) with identifier id on interface I and |
351 # with argument count 0. | 541 # with argument count 0. |
352 # 2. Return the length of the shortest argument list of the entries in S
. | 542 # 2. Return the length of the shortest argument list of the entries in S
. |
353 # FIXME: This calculation doesn't take into account whether runtime | 543 # FIXME: This calculation doesn't take into account whether runtime |
354 # enabled overloads are actually enabled, so length may be incorrect. | 544 # enabled overloads are actually enabled, so length may be incorrect. |
355 # E.g., [RuntimeEnabled=Foo] void f(); void f(long x); | 545 # E.g., [RuntimeEnabled=Foo] void f(); void f(long x); |
356 # should have length 1 if Foo is not enabled, but length 0 if it is. | 546 # should have length 1 if Foo is not enabled, but length 0 if it is. |
357 method['length'] = (method['overloads']['minarg'] if 'overloads' in meth
od else | 547 method['length'] = (method['overloads']['length'] if 'overloads' in meth
od else |
358 method['number_of_required_arguments']) | 548 method['number_of_required_arguments']) |
359 | 549 |
360 context.update({ | 550 context.update({ |
361 'conditionally_enabled_methods': conditionally_enabled_methods, | 551 'conditionally_enabled_methods': conditionally_enabled_methods, |
362 'custom_registration_methods': custom_registration_methods, | 552 'custom_registration_methods': custom_registration_methods, |
363 'has_origin_safe_method_setter': any( | 553 'has_origin_safe_method_setter': any( |
364 method['is_check_security_for_frame'] and not method['is_read_only'] | 554 method['is_check_security_for_frame'] and not method['is_read_only'] |
365 for method in methods), | 555 for method in methods), |
366 'has_private_script': any(attribute['is_implemented_in_private_script']
for attribute in attributes) or | 556 'has_private_script': any(attribute['is_implemented_in_private_script']
for attribute in attributes) or |
367 any(method['is_implemented_in_private_script'] for method in methods
), | 557 any(method['is_implemented_in_private_script'] for method in methods
), |
| 558 'iterator_method': iterator_method, |
368 'method_configuration_methods': method_configuration_methods, | 559 'method_configuration_methods': method_configuration_methods, |
369 'methods': methods, | 560 'methods': methods, |
370 }) | 561 }) |
371 | 562 |
| 563 # Conditionally enabled members |
| 564 has_conditional_attributes_on_instance = any( |
| 565 attribute['exposed_test'] and attribute['on_instance'] |
| 566 for attribute in attributes) |
| 567 has_conditional_attributes_on_prototype = any( |
| 568 attribute['exposed_test'] and attribute['on_prototype'] |
| 569 for attribute in attributes) |
372 context.update({ | 570 context.update({ |
373 'indexed_property_getter': indexed_property_getter(interface), | 571 'has_conditional_attributes_on_instance': |
374 'indexed_property_setter': indexed_property_setter(interface), | 572 has_conditional_attributes_on_instance, |
375 'indexed_property_deleter': indexed_property_deleter(interface), | 573 'has_conditional_attributes_on_prototype': |
| 574 has_conditional_attributes_on_prototype, |
| 575 }) |
| 576 |
| 577 context.update({ |
| 578 'indexed_property_getter': property_getter(interface.indexed_property_ge
tter, ['index']), |
| 579 'indexed_property_setter': property_setter(interface.indexed_property_se
tter, interface), |
| 580 'indexed_property_deleter': property_deleter(interface.indexed_property_
deleter), |
376 'is_override_builtins': 'OverrideBuiltins' in extended_attributes, | 581 'is_override_builtins': 'OverrideBuiltins' in extended_attributes, |
377 'named_property_getter': named_property_getter(interface), | 582 'named_property_getter': property_getter(interface.named_property_getter
, ['propertyName']), |
378 'named_property_setter': named_property_setter(interface), | 583 'named_property_setter': property_setter(interface.named_property_setter
, interface), |
379 'named_property_deleter': named_property_deleter(interface), | 584 'named_property_deleter': property_deleter(interface.named_property_dele
ter), |
380 }) | 585 }) |
381 | 586 |
382 return context | 587 return context |
383 | 588 |
384 | 589 |
385 # [DeprecateAs], [Reflect], [RuntimeEnabled] | 590 # [DeprecateAs], [Reflect], [RuntimeEnabled] |
386 def constant_context(constant): | 591 def constant_context(constant, interface): |
387 extended_attributes = constant.extended_attributes | 592 extended_attributes = constant.extended_attributes |
388 return { | 593 return { |
389 'cpp_class': extended_attributes.get('PartialInterfaceImplementedAs'), | 594 'cpp_class': extended_attributes.get('PartialInterfaceImplementedAs'), |
390 'deprecate_as': v8_utilities.deprecate_as(constant), # [DeprecateAs] | 595 'deprecate_as': v8_utilities.deprecate_as(constant), # [DeprecateAs] |
391 'idl_type': constant.idl_type.name, | 596 'idl_type': constant.idl_type.name, |
392 'measure_as': v8_utilities.measure_as(constant), # [MeasureAs] | 597 'measure_as': v8_utilities.measure_as(constant, interface), # [MeasureA
s] |
393 'name': constant.name, | 598 'name': constant.name, |
394 # FIXME: use 'reflected_name' as correct 'name' | 599 # FIXME: use 'reflected_name' as correct 'name' |
395 'reflected_name': extended_attributes.get('Reflect', constant.name), | 600 'reflected_name': extended_attributes.get('Reflect', constant.name), |
396 'runtime_enabled_function': runtime_enabled_function_name(constant), | 601 'runtime_enabled_function': runtime_enabled_function_name(constant), |
397 'value': constant.value, | 602 'value': constant.value, |
398 } | 603 } |
399 | 604 |
400 | 605 |
401 ################################################################################ | 606 ################################################################################ |
402 # Overloads | 607 # Overloads |
403 ################################################################################ | 608 ################################################################################ |
404 | 609 |
405 def compute_method_overloads_context(methods): | 610 def compute_method_overloads_context(interface, methods): |
406 # Regular methods | 611 # Regular methods |
407 compute_method_overloads_context_by_type([method for method in methods | 612 compute_method_overloads_context_by_type( |
408 if not method['is_static']]) | 613 interface, [method for method in methods if not method['is_static']]) |
409 # Static methods | 614 # Static methods |
410 compute_method_overloads_context_by_type([method for method in methods | 615 compute_method_overloads_context_by_type( |
411 if method['is_static']]) | 616 interface, [method for method in methods if method['is_static']]) |
412 | 617 |
413 | 618 |
414 def compute_method_overloads_context_by_type(methods): | 619 def compute_method_overloads_context_by_type(interface, methods): |
415 """Computes |method.overload*| template values. | 620 """Computes |method.overload*| template values. |
416 | 621 |
417 Called separately for static and non-static (regular) methods, | 622 Called separately for static and non-static (regular) methods, |
418 as these are overloaded separately. | 623 as these are overloaded separately. |
419 Modifies |method| in place for |method| in |methods|. | 624 Modifies |method| in place for |method| in |methods|. |
420 Doesn't change the |methods| list itself (only the values, i.e. individual | 625 Doesn't change the |methods| list itself (only the values, i.e. individual |
421 methods), so ok to treat these separately. | 626 methods), so ok to treat these separately. |
422 """ | 627 """ |
423 # Add overload information only to overloaded methods, so template code can | 628 # Add overload information only to overloaded methods, so template code can |
424 # easily verify if a function is overloaded | 629 # easily verify if a function is overloaded |
425 for name, overloads in method_overloads_by_name(methods): | 630 for name, overloads in method_overloads_by_name(methods): |
426 # Resolution function is generated after last overloaded function; | 631 # Resolution function is generated after last overloaded function; |
427 # package necessary information into |method.overloads| for that method. | 632 # package necessary information into |method.overloads| for that method. |
428 overloads[-1]['overloads'] = overloads_context(overloads) | 633 overloads[-1]['overloads'] = overloads_context(interface, overloads) |
429 overloads[-1]['overloads']['name'] = name | 634 overloads[-1]['overloads']['name'] = name |
430 | 635 |
431 | 636 |
432 def method_overloads_by_name(methods): | 637 def method_overloads_by_name(methods): |
433 """Returns generator of overloaded methods by name: [name, [method]]""" | 638 """Returns generator of overloaded methods by name: [name, [method]]""" |
434 # Filter to only methods that are actually overloaded | 639 # Filter to only methods that are actually overloaded |
435 method_counts = Counter(method['name'] for method in methods) | 640 method_counts = Counter(method['name'] for method in methods) |
436 overloaded_method_names = set(name | 641 overloaded_method_names = set(name |
437 for name, count in method_counts.iteritems() | 642 for name, count in method_counts.iteritems() |
438 if count > 1) | 643 if count > 1) |
439 overloaded_methods = [method for method in methods | 644 overloaded_methods = [method for method in methods |
440 if method['name'] in overloaded_method_names] | 645 if method['name'] in overloaded_method_names] |
441 | 646 |
442 # Group by name (generally will be defined together, but not necessarily) | 647 # Group by name (generally will be defined together, but not necessarily) |
443 return sort_and_groupby(overloaded_methods, itemgetter('name')) | 648 return sort_and_groupby(overloaded_methods, itemgetter('name')) |
444 | 649 |
445 | 650 |
446 def overloads_context(overloads): | 651 def overloads_context(interface, overloads): |
447 """Returns |overloads| template values for a single name. | 652 """Returns |overloads| template values for a single name. |
448 | 653 |
449 Sets |method.overload_index| in place for |method| in |overloads| | 654 Sets |method.overload_index| in place for |method| in |overloads| |
450 and returns dict of overall overload template values. | 655 and returns dict of overall overload template values. |
451 """ | 656 """ |
452 assert len(overloads) > 1 # only apply to overloaded names | 657 assert len(overloads) > 1 # only apply to overloaded names |
453 for index, method in enumerate(overloads, 1): | 658 for index, method in enumerate(overloads, 1): |
454 method['overload_index'] = index | 659 method['overload_index'] = index |
455 | 660 |
456 effective_overloads_by_length = effective_overload_set_by_length(overloads) | 661 effective_overloads_by_length = effective_overload_set_by_length(overloads) |
457 lengths = [length for length, _ in effective_overloads_by_length] | 662 lengths = [length for length, _ in effective_overloads_by_length] |
458 name = overloads[0].get('name', '<constructor>') | 663 name = overloads[0].get('name', '<constructor>') |
459 | 664 |
460 # Check and fail if all overloads with the shortest acceptable arguments | 665 runtime_determined_lengths = None |
461 # list are runtime enabled, since we would otherwise set 'length' on the | 666 function_length = lengths[0] |
462 # function object to an incorrect value when none of those overloads were | 667 runtime_determined_maxargs = None |
463 # actually enabled at runtime. The exception is if all overloads are | 668 maxarg = lengths[-1] |
464 # controlled by the same runtime enabled feature, in which case there would | 669 |
465 # be no function object at all if it is not enabled. | 670 # The special case handling below is not needed if all overloads are |
466 shortest_overloads = effective_overloads_by_length[0][1] | 671 # runtime enabled by the same feature. |
467 if (all(method.get('runtime_enabled_function') | 672 if not common_value(overloads, 'runtime_enabled_function'): |
468 for method, _, _ in shortest_overloads) and | 673 # Check if all overloads with the shortest acceptable arguments list are |
469 not common_value(overloads, 'runtime_enabled_function')): | 674 # runtime enabled, in which case we need to have a runtime determined |
470 raise ValueError('Function.length of %s depends on runtime enabled featu
res' % name) | 675 # Function.length. |
| 676 shortest_overloads = effective_overloads_by_length[0][1] |
| 677 if (all(method.get('runtime_enabled_function') |
| 678 for method, _, _ in shortest_overloads)): |
| 679 # Generate a list of (length, runtime_enabled_functions) tuples. |
| 680 runtime_determined_lengths = [] |
| 681 for length, effective_overloads in effective_overloads_by_length: |
| 682 runtime_enabled_functions = set( |
| 683 method['runtime_enabled_function'] |
| 684 for method, _, _ in effective_overloads |
| 685 if method.get('runtime_enabled_function')) |
| 686 if not runtime_enabled_functions: |
| 687 # This "length" is unconditionally enabled, so stop here. |
| 688 runtime_determined_lengths.append((length, [None])) |
| 689 break |
| 690 runtime_determined_lengths.append( |
| 691 (length, sorted(runtime_enabled_functions))) |
| 692 function_length = ('%sV8Internal::%sMethodLength()' |
| 693 % (cpp_name_or_partial(interface), name)) |
| 694 |
| 695 # Check if all overloads with the longest required arguments list are |
| 696 # runtime enabled, in which case we need to have a runtime determined |
| 697 # maximum distinguishing argument index. |
| 698 longest_overloads = effective_overloads_by_length[-1][1] |
| 699 if (not common_value(overloads, 'runtime_enabled_function') and |
| 700 all(method.get('runtime_enabled_function') |
| 701 for method, _, _ in longest_overloads)): |
| 702 # Generate a list of (length, runtime_enabled_functions) tuples. |
| 703 runtime_determined_maxargs = [] |
| 704 for length, effective_overloads in reversed(effective_overloads_by_l
ength): |
| 705 runtime_enabled_functions = set( |
| 706 method['runtime_enabled_function'] |
| 707 for method, _, _ in effective_overloads |
| 708 if method.get('runtime_enabled_function')) |
| 709 if not runtime_enabled_functions: |
| 710 # This "length" is unconditionally enabled, so stop here. |
| 711 runtime_determined_maxargs.append((length, [None])) |
| 712 break |
| 713 runtime_determined_maxargs.append( |
| 714 (length, sorted(runtime_enabled_functions))) |
| 715 maxarg = ('%sV8Internal::%sMethodMaxArg()' |
| 716 % (cpp_name_or_partial(interface), name)) |
471 | 717 |
472 # Check and fail if overloads disagree on any of the extended attributes | 718 # Check and fail if overloads disagree on any of the extended attributes |
473 # that affect how the method should be registered. | 719 # that affect how the method should be registered. |
474 # Skip the check for overloaded constructors, since they don't support any | 720 # Skip the check for overloaded constructors, since they don't support any |
475 # of the extended attributes in question. | 721 # of the extended attributes in question. |
476 if not overloads[0].get('is_constructor'): | 722 if not overloads[0].get('is_constructor'): |
477 overload_extended_attributes = [ | 723 overload_extended_attributes = [ |
478 method['custom_registration_extended_attributes'] | 724 method['custom_registration_extended_attributes'] |
479 for method in overloads] | 725 for method in overloads] |
480 for extended_attribute in v8_methods.CUSTOM_REGISTRATION_EXTENDED_ATTRIB
UTES: | 726 for extended_attribute in v8_methods.CUSTOM_REGISTRATION_EXTENDED_ATTRIB
UTES: |
481 if common_key(overload_extended_attributes, extended_attribute) is N
one: | 727 if common_key(overload_extended_attributes, extended_attribute) is N
one: |
482 raise ValueError('Overloads of %s have conflicting extended attr
ibute %s' | 728 raise ValueError('Overloads of %s have conflicting extended attr
ibute %s' |
483 % (name, extended_attribute)) | 729 % (name, extended_attribute)) |
484 | 730 |
485 # Check and fail if overloads disagree about whether the return type | 731 # Check and fail if overloads disagree about whether the return type |
486 # is a Promise or not. | 732 # is a Promise or not. |
487 promise_overload_count = sum(1 for method in overloads if method.get('idl_ty
pe') == 'Promise') | 733 promise_overload_count = sum(1 for method in overloads if method.get('return
s_promise')) |
488 if promise_overload_count not in (0, len(overloads)): | 734 if promise_overload_count not in (0, len(overloads)): |
489 raise ValueError('Overloads of %s have conflicting Promise/non-Promise t
ypes' | 735 raise ValueError('Overloads of %s have conflicting Promise/non-Promise t
ypes' |
490 % (name)) | 736 % (name)) |
491 | 737 |
| 738 has_overload_visible = False |
| 739 has_overload_not_visible = False |
| 740 for overload in overloads: |
| 741 if overload.get('visible', True): |
| 742 # If there exists an overload which is visible, need to generate |
| 743 # overload_resolution, i.e. overlods_visible should be True. |
| 744 has_overload_visible = True |
| 745 else: |
| 746 has_overload_not_visible = True |
| 747 |
| 748 # If some overloads are not visible and others are visible, |
| 749 # the method is overloaded between core and modules. |
| 750 has_partial_overloads = has_overload_visible and has_overload_not_visible |
| 751 |
492 return { | 752 return { |
493 'deprecate_all_as': common_value(overloads, 'deprecate_as'), # [Depreca
teAs] | 753 'deprecate_all_as': common_value(overloads, 'deprecate_as'), # [Depreca
teAs] |
494 'exposed_test_all': common_value(overloads, 'exposed_test'), # [Exposed
] | 754 'exposed_test_all': common_value(overloads, 'exposed_test'), # [Exposed
] |
495 'has_custom_registration_all': common_value(overloads, 'has_custom_regis
tration'), | 755 'has_custom_registration_all': common_value(overloads, 'has_custom_regis
tration'), |
| 756 'length': function_length, |
496 'length_tests_methods': length_tests_methods(effective_overloads_by_leng
th), | 757 'length_tests_methods': length_tests_methods(effective_overloads_by_leng
th), |
497 # 1. Let maxarg be the length of the longest type list of the | 758 # 1. Let maxarg be the length of the longest type list of the |
498 # entries in S. | 759 # entries in S. |
499 'maxarg': lengths[-1], | 760 'maxarg': maxarg, |
500 'measure_all_as': common_value(overloads, 'measure_as'), # [MeasureAs] | 761 'measure_all_as': common_value(overloads, 'measure_as'), # [MeasureAs] |
501 'minarg': lengths[0], | 762 'returns_promise_all': promise_overload_count > 0, |
502 'per_context_enabled_function_all': common_value(overloads, 'per_context
_enabled_function'), # [PerContextEnabled] | 763 'runtime_determined_lengths': runtime_determined_lengths, |
| 764 'runtime_determined_maxargs': runtime_determined_maxargs, |
503 'runtime_enabled_function_all': common_value(overloads, 'runtime_enabled
_function'), # [RuntimeEnabled] | 765 'runtime_enabled_function_all': common_value(overloads, 'runtime_enabled
_function'), # [RuntimeEnabled] |
504 'valid_arities': lengths | 766 'valid_arities': lengths |
505 # Only need to report valid arities if there is a gap in the | 767 # Only need to report valid arities if there is a gap in the |
506 # sequence of possible lengths, otherwise invalid length means | 768 # sequence of possible lengths, otherwise invalid length means |
507 # "not enough arguments". | 769 # "not enough arguments". |
508 if lengths[-1] - lengths[0] != len(lengths) - 1 else None, | 770 if lengths[-1] - lengths[0] != len(lengths) - 1 else None, |
| 771 'visible': has_overload_visible, |
| 772 'has_partial_overloads': has_partial_overloads, |
509 } | 773 } |
510 | 774 |
511 | 775 |
512 def effective_overload_set(F): | 776 def effective_overload_set(F): |
513 """Returns the effective overload set of an overloaded function. | 777 """Returns the effective overload set of an overloaded function. |
514 | 778 |
515 An effective overload set is the set of overloaded functions + signatures | 779 An effective overload set is the set of overloaded functions + signatures |
516 (type list of arguments, with optional and variadic arguments included or | 780 (type list of arguments, with optional and variadic arguments included or |
517 not), and is used in the overload resolution algorithm. | 781 not), and is used in the overload resolution algorithm. |
518 | 782 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
563 # 1. Let n be the number of arguments X is declared to take. | 827 # 1. Let n be the number of arguments X is declared to take. |
564 n = len(arguments) | 828 n = len(arguments) |
565 # 2. Let t0..n−1 be a list of types, where ti is the type of X’s | 829 # 2. Let t0..n−1 be a list of types, where ti is the type of X’s |
566 # argument at index i. | 830 # argument at index i. |
567 # (“type list”) | 831 # (“type list”) |
568 t = tuple(argument['idl_type_object'] for argument in arguments) | 832 t = tuple(argument['idl_type_object'] for argument in arguments) |
569 # 3. Let o0..n−1 be a list of optionality values, where oi is “variadic” | 833 # 3. Let o0..n−1 be a list of optionality values, where oi is “variadic” |
570 # if X’s argument at index i is a final, variadic argument, “optional” | 834 # if X’s argument at index i is a final, variadic argument, “optional” |
571 # if the argument is optional, and “required” otherwise. | 835 # if the argument is optional, and “required” otherwise. |
572 # (“optionality list”) | 836 # (“optionality list”) |
573 # (We’re just using a boolean for optional vs. required.) | 837 # (We’re just using a boolean for optional/variadic vs. required.) |
574 o = tuple(argument['is_optional'] for argument in arguments) | 838 o = tuple(argument['is_optional'] or argument['is_variadic'] |
| 839 for argument in arguments) |
575 # 4. Add to S the tuple <X, t0..n−1, o0..n−1>. | 840 # 4. Add to S the tuple <X, t0..n−1, o0..n−1>. |
576 S.append((X, t, o)) | 841 S.append((X, t, o)) |
577 # 5. If X is declared to be variadic, then: | 842 # 5. If X is declared to be variadic, then: |
578 # (Not used, so not implemented.) | 843 # (Not used, so not implemented.) |
579 # 6. Initialize i to n−1. | 844 # 6. Initialize i to n−1. |
580 i = n - 1 | 845 i = n - 1 |
581 # 7. While i ≥ 0: | 846 # 7. While i ≥ 0: |
582 # Spec bug (fencepost error); should be “While i > 0:” | 847 # Spec bug (fencepost error); should be “While i > 0:” |
583 # https://www.w3.org/Bugs/Public/show_bug.cgi?id=25590 | 848 # https://www.w3.org/Bugs/Public/show_bug.cgi?id=25590 |
584 while i > 0: | 849 while i > 0: |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
769 # • an interface type that V implements | 1034 # • an interface type that V implements |
770 # (Unlike most of these tests, this can return multiple methods, since we | 1035 # (Unlike most of these tests, this can return multiple methods, since we |
771 # test if it implements an interface. Thus we need a for loop, not a next.) | 1036 # test if it implements an interface. Thus we need a for loop, not a next.) |
772 # (We distinguish wrapper types from built-in interface types.) | 1037 # (We distinguish wrapper types from built-in interface types.) |
773 for idl_type, method in ((idl_type, method) | 1038 for idl_type, method in ((idl_type, method) |
774 for idl_type, method in idl_types_methods | 1039 for idl_type, method in idl_types_methods |
775 if idl_type.is_wrapper_type): | 1040 if idl_type.is_wrapper_type): |
776 test = 'V8{idl_type}::hasInstance({cpp_value}, info.GetIsolate())'.forma
t(idl_type=idl_type.base_type, cpp_value=cpp_value) | 1041 test = 'V8{idl_type}::hasInstance({cpp_value}, info.GetIsolate())'.forma
t(idl_type=idl_type.base_type, cpp_value=cpp_value) |
777 yield test, method | 1042 yield test, method |
778 | 1043 |
779 # 8. Otherwise: if V is any kind of object except for a native Date object, | 1044 # 13. Otherwise: if IsCallable(V) is true, and there is an entry in S that |
| 1045 # has one of the following types at position i of its type list, |
| 1046 # • a callback function type |
| 1047 # ... |
| 1048 # |
| 1049 # FIXME: |
| 1050 # We test for functions rather than callability, which isn't strictly the |
| 1051 # same thing. |
| 1052 try: |
| 1053 method = next(method for idl_type, method in idl_types_methods |
| 1054 if idl_type.is_callback_function) |
| 1055 test = '%s->IsFunction()' % cpp_value |
| 1056 yield test, method |
| 1057 except StopIteration: |
| 1058 pass |
| 1059 |
| 1060 # 14. Otherwise: if V is any kind of object except for a native Date object, |
| 1061 # a native RegExp object, and there is an entry in S that has one of the |
| 1062 # following types at position i of its type list, |
| 1063 # • a sequence type |
| 1064 # ... |
| 1065 # |
| 1066 # 15. Otherwise: if V is any kind of object except for a native Date object, |
780 # a native RegExp object, and there is an entry in S that has one of the | 1067 # a native RegExp object, and there is an entry in S that has one of the |
781 # following types at position i of its type list, | 1068 # following types at position i of its type list, |
782 # • an array type | 1069 # • an array type |
783 # • a sequence type | |
784 # ... | 1070 # ... |
785 # • a dictionary | 1071 # • a dictionary |
786 # | 1072 # |
787 # FIXME: | 1073 # FIXME: |
788 # We don't strictly follow the algorithm here. The algorithm says "remove | 1074 # We don't strictly follow the algorithm here. The algorithm says "remove |
789 # all other entries" if there is "one entry" matching, but we yield all | 1075 # all other entries" if there is "one entry" matching, but we yield all |
790 # entries to support following constructors: | 1076 # entries to support following constructors: |
791 # [constructor(sequence<DOMString> arg), constructor(Dictionary arg)] | 1077 # [constructor(sequence<DOMString> arg), constructor(Dictionary arg)] |
792 # interface I { ... } | 1078 # interface I { ... } |
793 # (Need to check array types before objects because an array is an object) | 1079 # (Need to check array types before objects because an array is an object) |
(...skipping 30 matching lines...) Expand all Loading... |
824 | 1110 |
825 # (Perform automatic type conversion, in order. If any of these match, | 1111 # (Perform automatic type conversion, in order. If any of these match, |
826 # that’s the end, and no other tests are needed.) To keep this code simple, | 1112 # that’s the end, and no other tests are needed.) To keep this code simple, |
827 # we rely on the C++ compiler's dead code elimination to deal with the | 1113 # we rely on the C++ compiler's dead code elimination to deal with the |
828 # redundancy if both cases below trigger. | 1114 # redundancy if both cases below trigger. |
829 | 1115 |
830 # 11. Otherwise: if there is an entry in S that has one of the following | 1116 # 11. Otherwise: if there is an entry in S that has one of the following |
831 # types at position i of its type list, | 1117 # types at position i of its type list, |
832 # • DOMString | 1118 # • DOMString |
833 # • ByteString | 1119 # • ByteString |
834 # • ScalarValueString [a DOMString typedef, per definition.] | 1120 # • USVString |
835 # • an enumeration type | 1121 # • an enumeration type |
836 try: | 1122 try: |
837 method = next(method for idl_type, method in idl_types_methods | 1123 method = next(method for idl_type, method in idl_types_methods |
838 if idl_type.is_string_type or idl_type.is_enum) | 1124 if idl_type.is_string_type or idl_type.is_enum) |
839 yield 'true', method | 1125 yield 'true', method |
840 except StopIteration: | 1126 except StopIteration: |
841 pass | 1127 pass |
842 | 1128 |
843 # 12. Otherwise: if there is an entry in S that has one of the following | 1129 # 12. Otherwise: if there is an entry in S that has one of the following |
844 # types at position i of its type list, | 1130 # types at position i of its type list, |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
923 if argument.idl_type.name == 'SerializedScriptValue' or | 1209 if argument.idl_type.name == 'SerializedScriptValue' or |
924 argument.idl_type.v8_conversion_needs_exception_state), | 1210 argument.idl_type.v8_conversion_needs_exception_state), |
925 'is_call_with_document': | 1211 'is_call_with_document': |
926 # [ConstructorCallWith=Document] | 1212 # [ConstructorCallWith=Document] |
927 has_extended_attribute_value(interface, | 1213 has_extended_attribute_value(interface, |
928 'ConstructorCallWith', 'Document'), | 1214 'ConstructorCallWith', 'Document'), |
929 'is_call_with_execution_context': | 1215 'is_call_with_execution_context': |
930 # [ConstructorCallWith=ExecutionContext] | 1216 # [ConstructorCallWith=ExecutionContext] |
931 has_extended_attribute_value(interface, | 1217 has_extended_attribute_value(interface, |
932 'ConstructorCallWith', 'ExecutionContext'), | 1218 'ConstructorCallWith', 'ExecutionContext'), |
| 1219 'is_call_with_script_state': |
| 1220 # [ConstructorCallWith=ScriptState] |
| 1221 has_extended_attribute_value( |
| 1222 interface, 'ConstructorCallWith', 'ScriptState'), |
933 'is_constructor': True, | 1223 'is_constructor': True, |
934 'is_named_constructor': False, | 1224 'is_named_constructor': False, |
935 'is_raises_exception': is_constructor_raises_exception, | 1225 'is_raises_exception': is_constructor_raises_exception, |
936 'number_of_required_arguments': | 1226 'number_of_required_arguments': |
937 number_of_required_arguments(constructor), | 1227 number_of_required_arguments(constructor), |
938 } | 1228 } |
939 | 1229 |
940 | 1230 |
941 # [NamedConstructor] | 1231 # [NamedConstructor] |
942 def named_constructor_context(interface): | 1232 def named_constructor_context(interface): |
(...skipping 13 matching lines...) Expand all Loading... |
956 return context | 1246 return context |
957 | 1247 |
958 | 1248 |
959 def number_of_required_arguments(constructor): | 1249 def number_of_required_arguments(constructor): |
960 return len([argument for argument in constructor.arguments | 1250 return len([argument for argument in constructor.arguments |
961 if not argument.is_optional]) | 1251 if not argument.is_optional]) |
962 | 1252 |
963 | 1253 |
964 def interface_length(interface, constructors): | 1254 def interface_length(interface, constructors): |
965 # Docs: http://heycam.github.io/webidl/#es-interface-call | 1255 # Docs: http://heycam.github.io/webidl/#es-interface-call |
966 if 'EventConstructor' in interface.extended_attributes: | |
967 return 1 | |
968 if not constructors: | 1256 if not constructors: |
969 return 0 | 1257 return 0 |
970 return min(constructor['number_of_required_arguments'] | 1258 return min(constructor['number_of_required_arguments'] |
971 for constructor in constructors) | 1259 for constructor in constructors) |
972 | 1260 |
973 | 1261 |
974 ################################################################################ | 1262 ################################################################################ |
975 # Special operations (methods) | 1263 # Special operations (methods) |
976 # http://heycam.github.io/webidl/#idl-special-operations | 1264 # http://heycam.github.io/webidl/#idl-special-operations |
977 ################################################################################ | 1265 ################################################################################ |
978 | 1266 |
979 def property_getter(getter, cpp_arguments): | 1267 def property_getter(getter, cpp_arguments): |
| 1268 if not getter: |
| 1269 return None |
| 1270 |
980 def is_null_expression(idl_type): | 1271 def is_null_expression(idl_type): |
981 if idl_type.is_union_type: | 1272 if idl_type.use_output_parameter_for_result: |
982 notnull = ' || '.join([ | 1273 return 'result.isNull()' |
983 member_argument['null_check_value'] | 1274 if idl_type.is_string_type: |
984 for member_argument in idl_type.union_arguments]) | |
985 return '!(%s)' % notnull | |
986 if idl_type.name == 'String': | |
987 return 'result.isNull()' | 1275 return 'result.isNull()' |
988 if idl_type.is_interface_type: | 1276 if idl_type.is_interface_type: |
989 return '!result' | 1277 return '!result' |
| 1278 if idl_type.base_type in ('any', 'object'): |
| 1279 return 'result.isEmpty()' |
990 return '' | 1280 return '' |
991 | 1281 |
| 1282 extended_attributes = getter.extended_attributes |
992 idl_type = getter.idl_type | 1283 idl_type = getter.idl_type |
993 extended_attributes = getter.extended_attributes | 1284 idl_type.add_includes_for_type(extended_attributes) |
| 1285 is_call_with_script_state = v8_utilities.has_extended_attribute_value(getter
, 'CallWith', 'ScriptState') |
994 is_raises_exception = 'RaisesException' in extended_attributes | 1286 is_raises_exception = 'RaisesException' in extended_attributes |
| 1287 use_output_parameter_for_result = idl_type.use_output_parameter_for_result |
995 | 1288 |
996 # FIXME: make more generic, so can use v8_methods.cpp_value | 1289 # FIXME: make more generic, so can use v8_methods.cpp_value |
997 cpp_method_name = 'impl->%s' % cpp_name(getter) | 1290 cpp_method_name = 'impl->%s' % cpp_name(getter) |
998 | 1291 |
| 1292 if is_call_with_script_state: |
| 1293 cpp_arguments.insert(0, 'scriptState') |
999 if is_raises_exception: | 1294 if is_raises_exception: |
1000 cpp_arguments.append('exceptionState') | 1295 cpp_arguments.append('exceptionState') |
1001 union_arguments = idl_type.union_arguments | 1296 if use_output_parameter_for_result: |
1002 if union_arguments: | 1297 cpp_arguments.append('result') |
1003 cpp_arguments.extend([member_argument['cpp_value'] | |
1004 for member_argument in union_arguments]) | |
1005 | 1298 |
1006 cpp_value = '%s(%s)' % (cpp_method_name, ', '.join(cpp_arguments)) | 1299 cpp_value = '%s(%s)' % (cpp_method_name, ', '.join(cpp_arguments)) |
1007 | 1300 |
1008 return { | 1301 return { |
1009 'cpp_type': idl_type.cpp_type, | 1302 'cpp_type': idl_type.cpp_type, |
1010 'cpp_value': cpp_value, | 1303 'cpp_value': cpp_value, |
| 1304 'do_not_check_security': 'DoNotCheckSecurity' in extended_attributes, |
| 1305 'is_call_with_script_state': is_call_with_script_state, |
1011 'is_custom': | 1306 'is_custom': |
1012 'Custom' in extended_attributes and | 1307 'Custom' in extended_attributes and |
1013 (not extended_attributes['Custom'] or | 1308 (not extended_attributes['Custom'] or |
1014 has_extended_attribute_value(getter, 'Custom', 'PropertyGetter')), | 1309 has_extended_attribute_value(getter, 'Custom', 'PropertyGetter')), |
1015 'is_custom_property_enumerator': has_extended_attribute_value( | 1310 'is_custom_property_enumerator': has_extended_attribute_value( |
1016 getter, 'Custom', 'PropertyEnumerator'), | 1311 getter, 'Custom', 'PropertyEnumerator'), |
1017 'is_custom_property_query': has_extended_attribute_value( | 1312 'is_custom_property_query': has_extended_attribute_value( |
1018 getter, 'Custom', 'PropertyQuery'), | 1313 getter, 'Custom', 'PropertyQuery'), |
1019 'is_enumerable': 'NotEnumerable' not in extended_attributes, | 1314 'is_enumerable': 'NotEnumerable' not in extended_attributes, |
1020 'is_null_expression': is_null_expression(idl_type), | 1315 'is_null_expression': is_null_expression(idl_type), |
1021 'is_raises_exception': is_raises_exception, | 1316 'is_raises_exception': is_raises_exception, |
1022 'name': cpp_name(getter), | 1317 'name': cpp_name(getter), |
1023 'union_arguments': union_arguments, | 1318 'use_output_parameter_for_result': use_output_parameter_for_result, |
1024 'v8_set_return_value': idl_type.v8_set_return_value('result', extended_a
ttributes=extended_attributes, script_wrappable='impl', release=idl_type.release
), | 1319 'v8_set_return_value': idl_type.v8_set_return_value('result', extended_a
ttributes=extended_attributes, script_wrappable='impl', release=idl_type.release
), |
1025 } | 1320 } |
1026 | 1321 |
1027 | 1322 |
1028 def property_setter(setter): | 1323 def property_setter(setter, interface): |
| 1324 if not setter: |
| 1325 return None |
| 1326 |
| 1327 extended_attributes = setter.extended_attributes |
1029 idl_type = setter.arguments[1].idl_type | 1328 idl_type = setter.arguments[1].idl_type |
1030 extended_attributes = setter.extended_attributes | 1329 idl_type.add_includes_for_type(extended_attributes) |
| 1330 is_call_with_script_state = v8_utilities.has_extended_attribute_value(setter
, 'CallWith', 'ScriptState') |
1031 is_raises_exception = 'RaisesException' in extended_attributes | 1331 is_raises_exception = 'RaisesException' in extended_attributes |
| 1332 |
| 1333 # [TypeChecking=Interface] / [LegacyInterfaceTypeChecking] |
| 1334 has_type_checking_interface = ( |
| 1335 not is_legacy_interface_type_checking(interface, setter) and |
| 1336 idl_type.is_wrapper_type) |
| 1337 |
1032 return { | 1338 return { |
1033 'has_type_checking_interface': | |
1034 has_extended_attribute_value(setter, 'TypeChecking', 'Interface') an
d | |
1035 idl_type.is_wrapper_type, | |
1036 'idl_type': idl_type.base_type, | |
1037 'is_custom': 'Custom' in extended_attributes, | |
1038 'has_exception_state': (is_raises_exception or | 1339 'has_exception_state': (is_raises_exception or |
1039 idl_type.v8_conversion_needs_exception_state), | 1340 idl_type.v8_conversion_needs_exception_state), |
| 1341 'has_type_checking_interface': has_type_checking_interface, |
| 1342 'idl_type': idl_type.base_type, |
| 1343 'is_call_with_script_state': is_call_with_script_state, |
| 1344 'is_custom': 'Custom' in extended_attributes, |
| 1345 'is_nullable': idl_type.is_nullable, |
1040 'is_raises_exception': is_raises_exception, | 1346 'is_raises_exception': is_raises_exception, |
1041 'name': cpp_name(setter), | 1347 'name': cpp_name(setter), |
1042 'v8_value_to_local_cpp_value': idl_type.v8_value_to_local_cpp_value( | 1348 'v8_value_to_local_cpp_value': idl_type.v8_value_to_local_cpp_value( |
1043 extended_attributes, 'v8Value', 'propertyValue'), | 1349 extended_attributes, 'v8Value', 'propertyValue'), |
1044 } | 1350 } |
1045 | 1351 |
1046 | 1352 |
1047 def property_deleter(deleter): | 1353 def property_deleter(deleter): |
| 1354 if not deleter: |
| 1355 return None |
| 1356 |
| 1357 extended_attributes = deleter.extended_attributes |
1048 idl_type = deleter.idl_type | 1358 idl_type = deleter.idl_type |
1049 if str(idl_type) != 'boolean': | 1359 is_call_with_script_state = v8_utilities.has_extended_attribute_value(delete
r, 'CallWith', 'ScriptState') |
1050 raise Exception( | |
1051 'Only deleters with boolean type are allowed, but type is "%s"' % | |
1052 idl_type) | |
1053 extended_attributes = deleter.extended_attributes | |
1054 return { | 1360 return { |
| 1361 'is_call_with_script_state': is_call_with_script_state, |
1055 'is_custom': 'Custom' in extended_attributes, | 1362 'is_custom': 'Custom' in extended_attributes, |
1056 'is_raises_exception': 'RaisesException' in extended_attributes, | 1363 'is_raises_exception': 'RaisesException' in extended_attributes, |
1057 'name': cpp_name(deleter), | 1364 'name': cpp_name(deleter), |
1058 } | 1365 } |
1059 | |
1060 | |
1061 ################################################################################ | |
1062 # Indexed properties | |
1063 # http://heycam.github.io/webidl/#idl-indexed-properties | |
1064 ################################################################################ | |
1065 | |
1066 def indexed_property_getter(interface): | |
1067 try: | |
1068 # Find indexed property getter, if present; has form: | |
1069 # getter TYPE [OPTIONAL_IDENTIFIER](unsigned long ARG1) | |
1070 getter = next( | |
1071 method | |
1072 for method in interface.operations | |
1073 if ('getter' in method.specials and | |
1074 len(method.arguments) == 1 and | |
1075 str(method.arguments[0].idl_type) == 'unsigned long')) | |
1076 except StopIteration: | |
1077 return None | |
1078 | |
1079 return property_getter(getter, ['index']) | |
1080 | |
1081 | |
1082 def indexed_property_setter(interface): | |
1083 try: | |
1084 # Find indexed property setter, if present; has form: | |
1085 # setter RETURN_TYPE [OPTIONAL_IDENTIFIER](unsigned long ARG1, ARG_TYPE
ARG2) | |
1086 setter = next( | |
1087 method | |
1088 for method in interface.operations | |
1089 if ('setter' in method.specials and | |
1090 len(method.arguments) == 2 and | |
1091 str(method.arguments[0].idl_type) == 'unsigned long')) | |
1092 except StopIteration: | |
1093 return None | |
1094 | |
1095 return property_setter(setter) | |
1096 | |
1097 | |
1098 def indexed_property_deleter(interface): | |
1099 try: | |
1100 # Find indexed property deleter, if present; has form: | |
1101 # deleter TYPE [OPTIONAL_IDENTIFIER](unsigned long ARG) | |
1102 deleter = next( | |
1103 method | |
1104 for method in interface.operations | |
1105 if ('deleter' in method.specials and | |
1106 len(method.arguments) == 1 and | |
1107 str(method.arguments[0].idl_type) == 'unsigned long')) | |
1108 except StopIteration: | |
1109 return None | |
1110 | |
1111 return property_deleter(deleter) | |
1112 | |
1113 | |
1114 ################################################################################ | |
1115 # Named properties | |
1116 # http://heycam.github.io/webidl/#idl-named-properties | |
1117 ################################################################################ | |
1118 | |
1119 def named_property_getter(interface): | |
1120 try: | |
1121 # Find named property getter, if present; has form: | |
1122 # getter TYPE [OPTIONAL_IDENTIFIER](DOMString ARG1) | |
1123 getter = next( | |
1124 method | |
1125 for method in interface.operations | |
1126 if ('getter' in method.specials and | |
1127 len(method.arguments) == 1 and | |
1128 str(method.arguments[0].idl_type) == 'DOMString')) | |
1129 except StopIteration: | |
1130 return None | |
1131 | |
1132 getter.name = getter.name or 'anonymousNamedGetter' | |
1133 return property_getter(getter, ['propertyName']) | |
1134 | |
1135 | |
1136 def named_property_setter(interface): | |
1137 try: | |
1138 # Find named property setter, if present; has form: | |
1139 # setter RETURN_TYPE [OPTIONAL_IDENTIFIER](DOMString ARG1, ARG_TYPE ARG2
) | |
1140 setter = next( | |
1141 method | |
1142 for method in interface.operations | |
1143 if ('setter' in method.specials and | |
1144 len(method.arguments) == 2 and | |
1145 str(method.arguments[0].idl_type) == 'DOMString')) | |
1146 except StopIteration: | |
1147 return None | |
1148 | |
1149 return property_setter(setter) | |
1150 | |
1151 | |
1152 def named_property_deleter(interface): | |
1153 try: | |
1154 # Find named property deleter, if present; has form: | |
1155 # deleter TYPE [OPTIONAL_IDENTIFIER](DOMString ARG) | |
1156 deleter = next( | |
1157 method | |
1158 for method in interface.operations | |
1159 if ('deleter' in method.specials and | |
1160 len(method.arguments) == 1 and | |
1161 str(method.arguments[0].idl_type) == 'DOMString')) | |
1162 except StopIteration: | |
1163 return None | |
1164 | |
1165 return property_deleter(deleter) | |
OLD | NEW |