| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/python | |
| 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 | |
| 6 """This module provides shared functionality for the systems to generate | |
| 7 native binding from the IDL database.""" | |
| 8 | |
| 9 import emitter | |
| 10 import os | |
| 11 import systembase | |
| 12 from generator import * | |
| 13 | |
| 14 | |
| 15 class NativeImplementationSystem(systembase.System): | |
| 16 | |
| 17 def __init__(self, options, auxiliary_dir): | |
| 18 super(NativeImplementationSystem, self).__init__(options) | |
| 19 self._auxiliary_dir = auxiliary_dir | |
| 20 self._cpp_header_files = [] | |
| 21 self._cpp_impl_files = [] | |
| 22 | |
| 23 def ImplementationGenerator(self, interface): | |
| 24 return NativeImplementationGenerator(self, interface) | |
| 25 | |
| 26 def ProcessCallback(self, interface, info): | |
| 27 self._interface = interface | |
| 28 | |
| 29 if IsPureInterface(self._interface.id): | |
| 30 return None | |
| 31 | |
| 32 cpp_impl_includes = set() | |
| 33 cpp_header_handlers_emitter = emitter.Emitter() | |
| 34 cpp_impl_handlers_emitter = emitter.Emitter() | |
| 35 class_name = 'Dart%s' % self._interface.id | |
| 36 for operation in interface.operations: | |
| 37 if operation.type.id == 'void': | |
| 38 return_prefix = '' | |
| 39 error_return = '' | |
| 40 else: | |
| 41 return_prefix = 'return ' | |
| 42 error_return = ' false' | |
| 43 | |
| 44 parameters = [] | |
| 45 arguments = [] | |
| 46 conversion_includes = [] | |
| 47 for argument in operation.arguments: | |
| 48 argument_type_info = self._type_registry.TypeInfo(argument.type.id) | |
| 49 parameters.append('%s %s' % (argument_type_info.parameter_type(), | |
| 50 argument.id)) | |
| 51 arguments.append(argument_type_info.to_dart_conversion(argument.id)) | |
| 52 conversion_includes.extend(argument_type_info.conversion_includes()) | |
| 53 | |
| 54 native_return_type = self._type_registry.TypeInfo(operation.type.id).nativ
e_type() | |
| 55 cpp_header_handlers_emitter.Emit( | |
| 56 '\n' | |
| 57 ' virtual $TYPE handleEvent($PARAMETERS);\n', | |
| 58 TYPE=native_return_type, PARAMETERS=', '.join(parameters)) | |
| 59 | |
| 60 if 'Custom' in operation.ext_attrs: | |
| 61 continue | |
| 62 | |
| 63 cpp_impl_includes |= set(conversion_includes) | |
| 64 arguments_declaration = 'Dart_Handle arguments[] = { %s }' % ', '.join(arg
uments) | |
| 65 if not len(arguments): | |
| 66 arguments_declaration = 'Dart_Handle* arguments = 0' | |
| 67 cpp_impl_handlers_emitter.Emit( | |
| 68 '\n' | |
| 69 '$TYPE $CLASS_NAME::handleEvent($PARAMETERS)\n' | |
| 70 '{\n' | |
| 71 ' if (!m_callback.isolate()->isAlive())\n' | |
| 72 ' return$ERROR_RETURN;\n' | |
| 73 ' DartIsolate::Scope scope(m_callback.isolate());\n' | |
| 74 ' DartApiScope apiScope;\n' | |
| 75 ' $ARGUMENTS_DECLARATION;\n' | |
| 76 ' $(RETURN_PREFIX)m_callback.handleEvent($ARGUMENT_COUNT, arguments
);\n' | |
| 77 '}\n', | |
| 78 TYPE=native_return_type, | |
| 79 CLASS_NAME=class_name, | |
| 80 PARAMETERS=', '.join(parameters), | |
| 81 ERROR_RETURN=error_return, | |
| 82 RETURN_PREFIX=return_prefix, | |
| 83 ARGUMENTS_DECLARATION=arguments_declaration, | |
| 84 ARGUMENT_COUNT=len(arguments)) | |
| 85 | |
| 86 cpp_header_path = self._FilePathForCppHeader(self._interface.id) | |
| 87 cpp_header_emitter = self._emitters.FileEmitter(cpp_header_path) | |
| 88 cpp_header_emitter.Emit( | |
| 89 self._templates.Load('cpp_callback_header.template'), | |
| 90 INTERFACE=self._interface.id, | |
| 91 HANDLERS=cpp_header_handlers_emitter.Fragments()) | |
| 92 | |
| 93 cpp_impl_path = self._FilePathForCppImplementation(self._interface.id) | |
| 94 self._cpp_impl_files.append(cpp_impl_path) | |
| 95 cpp_impl_emitter = self._emitters.FileEmitter(cpp_impl_path) | |
| 96 cpp_impl_emitter.Emit( | |
| 97 self._templates.Load('cpp_callback_implementation.template'), | |
| 98 INCLUDES=_GenerateCPPIncludes(cpp_impl_includes), | |
| 99 INTERFACE=self._interface.id, | |
| 100 HANDLERS=cpp_impl_handlers_emitter.Fragments()) | |
| 101 | |
| 102 def GenerateLibraries(self, interface_files): | |
| 103 # Generate dart:html library. | |
| 104 auxiliary_dir = os.path.relpath(self._auxiliary_dir, self._output_dir) | |
| 105 self._GenerateLibFile( | |
| 106 'html_dartium.darttemplate', | |
| 107 os.path.join(self._output_dir, 'html_dartium.dart'), | |
| 108 interface_files, | |
| 109 AUXILIARY_DIR=systembase.MassagePath(auxiliary_dir)) | |
| 110 | |
| 111 # Generate DartDerivedSourcesXX.cpp. | |
| 112 partitions = 20 # FIXME: this should be configurable. | |
| 113 sources_count = len(self._cpp_impl_files) | |
| 114 for i in range(0, partitions): | |
| 115 derived_sources_path = os.path.join(self._output_dir, | |
| 116 'DartDerivedSources%02i.cpp' % (i + 1)) | |
| 117 | |
| 118 includes_emitter = emitter.Emitter() | |
| 119 for impl_file in self._cpp_impl_files[i::partitions]: | |
| 120 path = os.path.relpath(impl_file, os.path.dirname(derived_sources_path
)) | |
| 121 includes_emitter.Emit('#include "$PATH"\n', PATH=path) | |
| 122 | |
| 123 derived_sources_emitter = self._emitters.FileEmitter(derived_sources_path) | |
| 124 derived_sources_emitter.Emit( | |
| 125 self._templates.Load('cpp_derived_sources.template'), | |
| 126 INCLUDES=includes_emitter.Fragments()) | |
| 127 | |
| 128 # Generate DartResolver.cpp. | |
| 129 cpp_resolver_path = os.path.join(self._output_dir, 'DartResolver.cpp') | |
| 130 | |
| 131 includes_emitter = emitter.Emitter() | |
| 132 resolver_body_emitter = emitter.Emitter() | |
| 133 for file in self._cpp_header_files: | |
| 134 path = os.path.relpath(file, os.path.dirname(cpp_resolver_path)) | |
| 135 includes_emitter.Emit('#include "$PATH"\n', PATH=path) | |
| 136 resolver_body_emitter.Emit( | |
| 137 ' if (Dart_NativeFunction func = $CLASS_NAME::resolver(name, argu
mentCount))\n' | |
| 138 ' return func;\n', | |
| 139 CLASS_NAME=os.path.splitext(os.path.basename(path))[0]) | |
| 140 | |
| 141 cpp_resolver_emitter = self._emitters.FileEmitter(cpp_resolver_path) | |
| 142 cpp_resolver_emitter.Emit( | |
| 143 self._templates.Load('cpp_resolver.template'), | |
| 144 INCLUDES=includes_emitter.Fragments(), | |
| 145 RESOLVER_BODY=resolver_body_emitter.Fragments()) | |
| 146 | |
| 147 def Finish(self): | |
| 148 pass | |
| 149 | |
| 150 def _FilePathForCppHeader(self, interface_name): | |
| 151 return os.path.join(self._output_dir, 'cpp', 'Dart%s.h' % interface_name) | |
| 152 | |
| 153 def _FilePathForCppImplementation(self, interface_name): | |
| 154 return os.path.join(self._output_dir, 'cpp', 'Dart%s.cpp' % interface_name) | |
| 155 | |
| 156 | |
| 157 class NativeImplementationGenerator(systembase.BaseGenerator): | |
| 158 """Generates Dart implementation for one DOM IDL interface.""" | |
| 159 | |
| 160 def __init__(self, system, interface): | |
| 161 """Generates Dart and C++ code for the given interface. | |
| 162 | |
| 163 Args: | |
| 164 system: The NativeImplementationSystem. | |
| 165 interface: an IDLInterface instance. It is assumed that all types have | |
| 166 been converted to Dart types (e.g. int, String), unless they are in | |
| 167 the same package as the interface. | |
| 168 """ | |
| 169 super(NativeImplementationGenerator, self).__init__( | |
| 170 system._database, interface) | |
| 171 self._system = system | |
| 172 self._current_secondary_parent = None | |
| 173 self._html_interface_name = system._renamer.RenameInterface(self._interface) | |
| 174 | |
| 175 def HasImplementation(self): | |
| 176 return not IsPureInterface(self._interface.id) | |
| 177 | |
| 178 def ImplementationClassName(self): | |
| 179 return self._ImplClassName(self._interface.id) | |
| 180 | |
| 181 def FilePathForDartImplementation(self): | |
| 182 return os.path.join(self._system._output_dir, 'dart', | |
| 183 '%sImplementation.dart' % self._interface.id) | |
| 184 | |
| 185 def FilePathForDartFactoryProviderImplementation(self): | |
| 186 file_name = '%sFactoryProviderImplementation.dart' % self._interface.id | |
| 187 return os.path.join(self._system._output_dir, 'dart', file_name) | |
| 188 | |
| 189 def FilePathForDartElementsFactoryProviderImplementation(self): | |
| 190 return os.path.join(self._system._output_dir, 'dart', | |
| 191 '_ElementsFactoryProviderImplementation.dart') | |
| 192 | |
| 193 def SetImplementationEmitter(self, implementation_emitter): | |
| 194 self._dart_impl_emitter = implementation_emitter | |
| 195 | |
| 196 def ImplementsMergedMembers(self): | |
| 197 # We could not add merged functions to implementation class because | |
| 198 # underlying c++ object doesn't implement them. Merged functions are | |
| 199 # generated on merged interface implementation instead. | |
| 200 return False | |
| 201 | |
| 202 def StartInterface(self): | |
| 203 # Create emitters for c++ implementation. | |
| 204 if self.HasImplementation(): | |
| 205 cpp_header_path = self._system._FilePathForCppHeader(self._interface.id) | |
| 206 self._system._cpp_header_files.append(cpp_header_path) | |
| 207 self._cpp_header_emitter = self._system._emitters.FileEmitter(cpp_header_p
ath) | |
| 208 cpp_impl_path = self._system._FilePathForCppImplementation(self._interface
.id) | |
| 209 self._system._cpp_impl_files.append(cpp_impl_path) | |
| 210 self._cpp_impl_emitter = self._system._emitters.FileEmitter(cpp_impl_path) | |
| 211 else: | |
| 212 self._cpp_header_emitter = emitter.Emitter() | |
| 213 self._cpp_impl_emitter = emitter.Emitter() | |
| 214 | |
| 215 self._interface_type_info = self._TypeInfo(self._interface.id) | |
| 216 self._members_emitter = emitter.Emitter() | |
| 217 self._cpp_declarations_emitter = emitter.Emitter() | |
| 218 self._cpp_impl_includes = set() | |
| 219 self._cpp_definitions_emitter = emitter.Emitter() | |
| 220 self._cpp_resolver_emitter = emitter.Emitter() | |
| 221 | |
| 222 self._GenerateConstructors() | |
| 223 return self._members_emitter | |
| 224 | |
| 225 def _GenerateConstructors(self): | |
| 226 if not self._IsConstructable(): | |
| 227 return | |
| 228 | |
| 229 # TODO(antonm): currently we don't have information about number of argument
s expected by | |
| 230 # the constructor, so name only dispatch. | |
| 231 self._cpp_resolver_emitter.Emit( | |
| 232 ' if (name == "$(INTERFACE_NAME)_constructor_Callback")\n' | |
| 233 ' return Dart$(INTERFACE_NAME)Internal::constructorCallback;\n', | |
| 234 INTERFACE_NAME=self._interface.id) | |
| 235 | |
| 236 | |
| 237 constructor_info = AnalyzeConstructor(self._interface) | |
| 238 | |
| 239 ext_attrs = self._interface.ext_attrs | |
| 240 | |
| 241 if 'CustomConstructor' in ext_attrs: | |
| 242 # We have a custom implementation for it. | |
| 243 self._cpp_declarations_emitter.Emit( | |
| 244 '\n' | |
| 245 'void constructorCallback(Dart_NativeArguments);\n') | |
| 246 return | |
| 247 | |
| 248 if ext_attrs.get('ConstructorTemplate') == 'TypedArray': | |
| 249 self._cpp_impl_includes.add('"DartArrayBufferViewCustom.h"'); | |
| 250 self._cpp_definitions_emitter.Emit( | |
| 251 '\n' | |
| 252 'static void constructorCallback(Dart_NativeArguments args)\n' | |
| 253 '{\n' | |
| 254 ' WebCore::DartArrayBufferViewInternal::constructWebGLArray<Dart$(INT
ERFACE_NAME)>(args);\n' | |
| 255 '}\n', | |
| 256 INTERFACE_NAME=self._interface.id); | |
| 257 return | |
| 258 | |
| 259 create_function = 'create' | |
| 260 if 'NamedConstructor' in ext_attrs: | |
| 261 create_function = 'createForJSConstructor' | |
| 262 function_expression = '%s::%s' % (self._interface_type_info.native_type(), c
reate_function) | |
| 263 self._GenerateNativeCallback( | |
| 264 'constructorCallback', | |
| 265 False, | |
| 266 function_expression, | |
| 267 self._interface, | |
| 268 constructor_info.idl_args, | |
| 269 self._interface.id, | |
| 270 'ConstructorRaisesException' in ext_attrs) | |
| 271 | |
| 272 def _ImplClassName(self, interface_name): | |
| 273 return '_%sImpl' % interface_name | |
| 274 | |
| 275 def _BaseClassName(self): | |
| 276 root_class = 'NativeFieldWrapperClass1' | |
| 277 | |
| 278 if not self._interface.parents: | |
| 279 return root_class | |
| 280 | |
| 281 supertype = self._interface.parents[0].type.id | |
| 282 | |
| 283 if IsPureInterface(supertype): # The class is a root. | |
| 284 return root_class | |
| 285 | |
| 286 # FIXME: We're currently injecting List<..> and EventTarget as | |
| 287 # supertypes in dart.idl. We should annotate/preserve as | |
| 288 # attributes instead. For now, this hack lets the self._interfaces | |
| 289 # inherit, but not the classes. | |
| 290 # List methods are injected in AddIndexer. | |
| 291 if IsDartListType(supertype) or IsDartCollectionType(supertype): | |
| 292 return root_class | |
| 293 | |
| 294 return self._ImplClassName(supertype) | |
| 295 | |
| 296 ATTRIBUTES_OF_CONSTRUCTABLE = set([ | |
| 297 'CustomConstructor', | |
| 298 'V8CustomConstructor', | |
| 299 'Constructor', | |
| 300 'NamedConstructor']) | |
| 301 | |
| 302 def _IsConstructable(self): | |
| 303 ext_attrs = self._interface.ext_attrs | |
| 304 | |
| 305 if self.ATTRIBUTES_OF_CONSTRUCTABLE & set(ext_attrs): | |
| 306 return True | |
| 307 | |
| 308 # FIXME: support other types of ConstructorTemplate. | |
| 309 if ext_attrs.get('ConstructorTemplate') == 'TypedArray': | |
| 310 return True | |
| 311 | |
| 312 return False | |
| 313 | |
| 314 def EmitFactoryProvider(self, constructor_info, factory_provider, emitter): | |
| 315 template_file = 'factoryprovider_%s.darttemplate' % self._html_interface_nam
e | |
| 316 template = self._system._templates.TryLoad(template_file) | |
| 317 if not template: | |
| 318 template = self._system._templates.Load('factoryprovider.darttemplate') | |
| 319 | |
| 320 native_binding = '%s_constructor_Callback' % self._interface.id | |
| 321 emitter.Emit( | |
| 322 template, | |
| 323 FACTORYPROVIDER=factory_provider, | |
| 324 INTERFACE=self._html_interface_name, | |
| 325 PARAMETERS=constructor_info.ParametersImplementationDeclaration(self._Da
rtType), | |
| 326 ARGUMENTS=constructor_info.ParametersAsArgumentList(), | |
| 327 NATIVE_NAME=native_binding) | |
| 328 | |
| 329 def FinishInterface(self): | |
| 330 template = None | |
| 331 if self._html_interface_name == self._interface.id or not self._database.Has
Interface(self._html_interface_name): | |
| 332 template_file = 'impl_%s.darttemplate' % self._html_interface_name | |
| 333 template = self._system._templates.TryLoad(template_file) | |
| 334 if not template: | |
| 335 template = self._system._templates.Load('dart_implementation.darttemplate'
) | |
| 336 | |
| 337 class_name = self._ImplClassName(self._interface.id) | |
| 338 members_emitter = self._dart_impl_emitter.Emit( | |
| 339 template, | |
| 340 CLASSNAME=class_name, | |
| 341 EXTENDS=' extends ' + self._BaseClassName(), | |
| 342 IMPLEMENTS=' implements ' + self._html_interface_name, | |
| 343 NATIVESPEC='') | |
| 344 members_emitter.Emit(''.join(self._members_emitter.Fragments())) | |
| 345 | |
| 346 self._GenerateCppHeader() | |
| 347 | |
| 348 self._cpp_impl_emitter.Emit( | |
| 349 self._system._templates.Load('cpp_implementation.template'), | |
| 350 INTERFACE=self._interface.id, | |
| 351 INCLUDES=_GenerateCPPIncludes(self._cpp_impl_includes), | |
| 352 CALLBACKS=self._cpp_definitions_emitter.Fragments(), | |
| 353 RESOLVER=self._cpp_resolver_emitter.Fragments(), | |
| 354 DART_IMPLEMENTATION_CLASS=class_name) | |
| 355 | |
| 356 def _GenerateCppHeader(self): | |
| 357 to_native_emitter = emitter.Emitter() | |
| 358 if self._interface_type_info.custom_to_native(): | |
| 359 to_native_emitter.Emit( | |
| 360 ' static PassRefPtr<NativeType> toNative(Dart_Handle handle, Dart_H
andle& exception);\n') | |
| 361 else: | |
| 362 to_native_emitter.Emit( | |
| 363 ' static NativeType* toNative(Dart_Handle handle, Dart_Handle& exce
ption)\n' | |
| 364 ' {\n' | |
| 365 ' return DartDOMWrapper::unwrapDartWrapper<Dart$INTERFACE>(hand
le, exception);\n' | |
| 366 ' }\n', | |
| 367 INTERFACE=self._interface.id) | |
| 368 | |
| 369 to_dart_emitter = emitter.Emitter() | |
| 370 | |
| 371 ext_attrs = self._interface.ext_attrs | |
| 372 | |
| 373 if ('CustomToJS' in ext_attrs or | |
| 374 ('CustomToJSObject' in ext_attrs and 'TypedArray' not in ext_attrs) or | |
| 375 'PureInterface' in ext_attrs or | |
| 376 'CPPPureInterface' in ext_attrs or | |
| 377 self._interface_type_info.custom_to_dart()): | |
| 378 to_dart_emitter.Emit( | |
| 379 ' static Dart_Handle toDart(NativeType* value);\n') | |
| 380 else: | |
| 381 to_dart_emitter.Emit( | |
| 382 ' static Dart_Handle toDart(NativeType* value)\n' | |
| 383 ' {\n' | |
| 384 ' return DartDOMWrapper::toDart<Dart$(INTERFACE)>(value);\n' | |
| 385 ' }\n', | |
| 386 INTERFACE=self._interface.id) | |
| 387 | |
| 388 webcore_includes = _GenerateCPPIncludes(self._interface_type_info.webcore_in
cludes()) | |
| 389 | |
| 390 is_node_test = lambda interface: interface.id == 'Node' | |
| 391 is_active_test = lambda interface: 'ActiveDOMObject' in interface.ext_attrs | |
| 392 is_event_target_test = lambda interface: 'EventTarget' in interface.ext_attr
s | |
| 393 def TypeCheckHelper(test): | |
| 394 return 'true' if any(map(test, self._database.Hierarchy(self._interface)))
else 'false' | |
| 395 | |
| 396 self._cpp_header_emitter.Emit( | |
| 397 self._system._templates.Load('cpp_header.template'), | |
| 398 INTERFACE=self._interface.id, | |
| 399 WEBCORE_INCLUDES=webcore_includes, | |
| 400 WEBCORE_CLASS_NAME=self._interface_type_info.native_type(), | |
| 401 DECLARATIONS=self._cpp_declarations_emitter.Fragments(), | |
| 402 IS_NODE=TypeCheckHelper(is_node_test), | |
| 403 IS_ACTIVE=TypeCheckHelper(is_active_test), | |
| 404 IS_EVENT_TARGET=TypeCheckHelper(is_event_target_test), | |
| 405 TO_NATIVE=to_native_emitter.Fragments(), | |
| 406 TO_DART=to_dart_emitter.Fragments()) | |
| 407 | |
| 408 def AddAttribute(self, attribute, html_name, read_only): | |
| 409 if 'CheckSecurityForNode' in attribute.ext_attrs: | |
| 410 # FIXME: exclude from interface as well. | |
| 411 return | |
| 412 | |
| 413 self._AddGetter(attribute, html_name) | |
| 414 if not read_only: | |
| 415 self._AddSetter(attribute, html_name) | |
| 416 | |
| 417 def _AddGetter(self, attr, html_name): | |
| 418 type_info = self._TypeInfo(attr.type.id) | |
| 419 dart_declaration = '%s get %s()' % (self._DartType(attr.type.id), html_name) | |
| 420 is_custom = 'Custom' in attr.ext_attrs or 'CustomGetter' in attr.ext_attrs | |
| 421 cpp_callback_name = self._GenerateNativeBinding(attr.id, 1, | |
| 422 dart_declaration, 'Getter', is_custom) | |
| 423 if is_custom: | |
| 424 return | |
| 425 | |
| 426 if 'Reflect' in attr.ext_attrs: | |
| 427 webcore_function_name = self._TypeInfo(attr.type.id).webcore_getter_name() | |
| 428 if 'URL' in attr.ext_attrs: | |
| 429 if 'NonEmpty' in attr.ext_attrs: | |
| 430 webcore_function_name = 'getNonEmptyURLAttribute' | |
| 431 else: | |
| 432 webcore_function_name = 'getURLAttribute' | |
| 433 elif 'ImplementedAs' in attr.ext_attrs: | |
| 434 webcore_function_name = attr.ext_attrs['ImplementedAs'] | |
| 435 else: | |
| 436 if attr.id == 'operator': | |
| 437 webcore_function_name = '_operator' | |
| 438 elif attr.id == 'target' and attr.type.id == 'SVGAnimatedString': | |
| 439 webcore_function_name = 'svgTarget' | |
| 440 else: | |
| 441 webcore_function_name = _ToWebKitName(attr.id) | |
| 442 if attr.type.id.startswith('SVGAnimated'): | |
| 443 webcore_function_name += 'Animated' | |
| 444 | |
| 445 function_expression = self._GenerateWebCoreFunctionExpression(webcore_functi
on_name, attr) | |
| 446 self._GenerateNativeCallback( | |
| 447 cpp_callback_name, | |
| 448 True, | |
| 449 function_expression, | |
| 450 attr, | |
| 451 [], | |
| 452 attr.type.id, | |
| 453 attr.get_raises) | |
| 454 | |
| 455 def _AddSetter(self, attr, html_name): | |
| 456 type_info = self._TypeInfo(attr.type.id) | |
| 457 dart_declaration = 'void set %s(%s)' % (html_name, self._DartType(attr.type.
id)) | |
| 458 is_custom = set(['Custom', 'CustomSetter', 'V8CustomSetter']) & set(attr.ext
_attrs) | |
| 459 cpp_callback_name = self._GenerateNativeBinding(attr.id, 2, | |
| 460 dart_declaration, 'Setter', is_custom) | |
| 461 if is_custom: | |
| 462 return | |
| 463 | |
| 464 if 'Reflect' in attr.ext_attrs: | |
| 465 webcore_function_name = self._TypeInfo(attr.type.id).webcore_setter_name() | |
| 466 else: | |
| 467 webcore_function_name = re.sub(r'^(xml(?=[A-Z])|\w)', | |
| 468 lambda s: s.group(1).upper(), | |
| 469 attr.id) | |
| 470 webcore_function_name = 'set%s' % webcore_function_name | |
| 471 if attr.type.id.startswith('SVGAnimated'): | |
| 472 webcore_function_name += 'Animated' | |
| 473 | |
| 474 function_expression = self._GenerateWebCoreFunctionExpression(webcore_functi
on_name, attr) | |
| 475 self._GenerateNativeCallback( | |
| 476 cpp_callback_name, | |
| 477 True, | |
| 478 function_expression, | |
| 479 attr, | |
| 480 [attr], | |
| 481 'void', | |
| 482 attr.set_raises) | |
| 483 | |
| 484 def AddIndexer(self, element_type): | |
| 485 """Adds all the methods required to complete implementation of List.""" | |
| 486 # We would like to simply inherit the implementation of everything except | |
| 487 # get length(), [], and maybe []=. It is possible to extend from a base | |
| 488 # array implementation class only when there is no other implementation | |
| 489 # inheritance. There might be no implementation inheritance other than | |
| 490 # DOMBaseWrapper for many classes, but there might be some where the | |
| 491 # array-ness is introduced by a non-root interface: | |
| 492 # | |
| 493 # interface Y extends X, List<T> ... | |
| 494 # | |
| 495 # In the non-root case we have to choose between: | |
| 496 # | |
| 497 # class YImpl extends XImpl { add List<T> methods; } | |
| 498 # | |
| 499 # and | |
| 500 # | |
| 501 # class YImpl extends ListBase<T> { copies of transitive XImpl methods; } | |
| 502 # | |
| 503 dart_element_type = self._DartType(element_type) | |
| 504 if self._HasNativeIndexGetter(): | |
| 505 self._EmitNativeIndexGetter(dart_element_type) | |
| 506 else: | |
| 507 self._members_emitter.Emit( | |
| 508 '\n' | |
| 509 ' $TYPE operator[](int index) native "$(INTERFACE)_item_Callback";\n'
, | |
| 510 TYPE=dart_element_type, INTERFACE=self._interface.id) | |
| 511 | |
| 512 if self._HasNativeIndexSetter(): | |
| 513 self._EmitNativeIndexSetter(dart_element_type) | |
| 514 else: | |
| 515 # The HTML library implementation of NodeList has a custom indexed setter | |
| 516 # implementation that uses the parent node the NodeList is associated | |
| 517 # with if one is available. | |
| 518 if self._interface.id != 'NodeList': | |
| 519 self._members_emitter.Emit( | |
| 520 '\n' | |
| 521 ' void operator[]=(int index, $TYPE value) {\n' | |
| 522 ' throw new UnsupportedOperationException("Cannot assign element
of immutable List.");\n' | |
| 523 ' }\n', | |
| 524 TYPE=dart_element_type) | |
| 525 | |
| 526 # The list interface for this class is manually generated. | |
| 527 if self._interface.id == 'NodeList': | |
| 528 return | |
| 529 | |
| 530 # TODO(sra): Use separate mixins for mutable implementations of List<T>. | |
| 531 # TODO(sra): Use separate mixins for typed array implementations of List<T>. | |
| 532 template_file = 'immutable_list_mixin.darttemplate' | |
| 533 template = self._system._templates.Load(template_file) | |
| 534 self._members_emitter.Emit(template, E=dart_element_type) | |
| 535 | |
| 536 def AmendIndexer(self, element_type): | |
| 537 # If interface is marked as having native indexed | |
| 538 # getter or setter, we must emit overrides as it's not | |
| 539 # guaranteed that the corresponding methods in C++ would be | |
| 540 # virtual. For example, as of time of writing, even though | |
| 541 # Uint8ClampedArray inherits from Uint8Array, ::set method | |
| 542 # is not virtual and accessing it through Uint8Array pointer | |
| 543 # would lead to wrong semantics (modulo vs. clamping.) | |
| 544 dart_element_type = self._DartType(element_type) | |
| 545 | |
| 546 if self._HasNativeIndexGetter(): | |
| 547 self._EmitNativeIndexGetter(dart_element_type) | |
| 548 if self._HasNativeIndexSetter(): | |
| 549 self._EmitNativeIndexSetter(dart_element_type) | |
| 550 | |
| 551 def _HasNativeIndexGetter(self): | |
| 552 ext_attrs = self._interface.ext_attrs | |
| 553 return ('CustomIndexedGetter' in ext_attrs or | |
| 554 'NumericIndexedGetter' in ext_attrs) | |
| 555 | |
| 556 def _EmitNativeIndexGetter(self, element_type): | |
| 557 dart_declaration = '%s operator[](int index)' % element_type | |
| 558 self._GenerateNativeBinding('numericIndexGetter', 2, dart_declaration, | |
| 559 'Callback', True) | |
| 560 | |
| 561 def _HasNativeIndexSetter(self): | |
| 562 return 'CustomIndexedSetter' in self._interface.ext_attrs | |
| 563 | |
| 564 def _EmitNativeIndexSetter(self, element_type): | |
| 565 dart_declaration = 'void operator[]=(int index, %s value)' % element_type | |
| 566 self._GenerateNativeBinding('numericIndexSetter', 3, dart_declaration, | |
| 567 'Callback', True) | |
| 568 | |
| 569 def AddOperation(self, info, html_name): | |
| 570 """ | |
| 571 Arguments: | |
| 572 info: An OperationInfo object. | |
| 573 """ | |
| 574 | |
| 575 operation = info.operations[0] | |
| 576 | |
| 577 if 'CheckSecurityForNode' in operation.ext_attrs: | |
| 578 # FIXME: exclude from interface as well. | |
| 579 return | |
| 580 | |
| 581 is_custom = 'Custom' in operation.ext_attrs | |
| 582 has_optional_arguments = any(self._IsArgumentOptionalInWebCore(operation, ar
gument) for argument in operation.arguments) | |
| 583 needs_dispatcher = not is_custom and (len(info.operations) > 1 or has_option
al_arguments) | |
| 584 | |
| 585 if not needs_dispatcher: | |
| 586 type_renamer = self._DartType | |
| 587 default_value = 'null' | |
| 588 else: | |
| 589 type_renamer = lambda x: 'Dynamic' | |
| 590 default_value = '_null' | |
| 591 | |
| 592 dart_declaration = '%s%s %s(%s)' % ( | |
| 593 'static ' if info.IsStatic() else '', | |
| 594 self._DartType(info.type_name), | |
| 595 html_name, | |
| 596 info.ParametersImplementationDeclaration(type_renamer, default_value)) | |
| 597 | |
| 598 if not needs_dispatcher: | |
| 599 # Bind directly to native implementation | |
| 600 argument_count = (0 if info.IsStatic() else 1) + len(info.param_infos) | |
| 601 cpp_callback_name = self._GenerateNativeBinding( | |
| 602 info.name, argument_count, dart_declaration, 'Callback', is_custom) | |
| 603 if not is_custom: | |
| 604 self._GenerateOperationNativeCallback(operation, operation.arguments, cp
p_callback_name) | |
| 605 else: | |
| 606 self._GenerateDispatcher(info.operations, dart_declaration, [info.name for
info in info.param_infos]) | |
| 607 | |
| 608 def _GenerateDispatcher(self, operations, dart_declaration, argument_names): | |
| 609 | |
| 610 body = self._members_emitter.Emit( | |
| 611 '\n' | |
| 612 ' $DECLARATION {\n' | |
| 613 '$!BODY' | |
| 614 ' }\n', | |
| 615 DECLARATION=dart_declaration) | |
| 616 | |
| 617 version = [1] | |
| 618 def GenerateCall(operation, argument_count, checks): | |
| 619 if checks: | |
| 620 if operation.type.id != 'void': | |
| 621 template = ' if ($CHECKS) {\n return $CALL;\n }\n' | |
| 622 else: | |
| 623 template = ' if ($CHECKS) {\n $CALL;\n return;\n }\n' | |
| 624 else: | |
| 625 if operation.type.id != 'void': | |
| 626 template = ' return $CALL;\n' | |
| 627 else: | |
| 628 template = ' $CALL;\n' | |
| 629 | |
| 630 overload_name = '%s_%s' % (operation.id, version[0]) | |
| 631 version[0] += 1 | |
| 632 argument_list = ', '.join(argument_names[:argument_count]) | |
| 633 call = '_%s(%s)' % (overload_name, argument_list) | |
| 634 body.Emit(template, CHECKS=' && '.join(checks), CALL=call) | |
| 635 | |
| 636 dart_declaration = '%s%s _%s(%s)' % ( | |
| 637 'static ' if operation.is_static else '', | |
| 638 self._DartType(operation.type.id), overload_name, argument_list) | |
| 639 cpp_callback_name = self._GenerateNativeBinding( | |
| 640 overload_name, (0 if operation.is_static else 1) + argument_count, | |
| 641 dart_declaration, 'Callback', False) | |
| 642 self._GenerateOperationNativeCallback(operation, operation.arguments[:argu
ment_count], cpp_callback_name) | |
| 643 | |
| 644 def GenerateChecksAndCall(operation, argument_count): | |
| 645 checks = ['%s === _null' % name for name in argument_names] | |
| 646 for i in range(0, argument_count): | |
| 647 argument = operation.arguments[i] | |
| 648 argument_name = argument_names[i] | |
| 649 checks[i] = '(%s is %s || %s === null)' % ( | |
| 650 argument_name, self._DartType(argument.type.id), argument_name) | |
| 651 GenerateCall(operation, argument_count, checks) | |
| 652 | |
| 653 # TODO: Optimize the dispatch to avoid repeated checks. | |
| 654 if len(operations) > 1: | |
| 655 for operation in operations: | |
| 656 for position, argument in enumerate(operation.arguments): | |
| 657 if self._IsArgumentOptionalInWebCore(operation, argument): | |
| 658 GenerateChecksAndCall(operation, position) | |
| 659 GenerateChecksAndCall(operation, len(operation.arguments)) | |
| 660 body.Emit(' throw "Incorrect number or type of arguments";\n'); | |
| 661 else: | |
| 662 operation = operations[0] | |
| 663 argument_count = len(operation.arguments) | |
| 664 for position, argument in list(enumerate(operation.arguments))[::-1]: | |
| 665 if self._IsArgumentOptionalInWebCore(operation, argument): | |
| 666 check = '%s !== _null' % argument_names[position] | |
| 667 # argument_count instead of position + 1 is used here to cover one | |
| 668 # complicated case with the effectively optional argument in the middl
e. | |
| 669 # Consider foo(x, [Optional] y, [Optional=DefaultIsNullString] z) | |
| 670 # (as of now it's modelled after HTMLMediaElement.webkitAddKey). | |
| 671 # y is optional in WebCore, while z is not. | |
| 672 # In this case, if y !== _null, we'd like to emit foo(x, y, z) invocat
ion, not | |
| 673 # foo(x, y). | |
| 674 GenerateCall(operation, argument_count, [check]) | |
| 675 argument_count = position | |
| 676 GenerateCall(operation, argument_count, []) | |
| 677 | |
| 678 def SecondaryContext(self, interface): | |
| 679 pass | |
| 680 | |
| 681 def _GenerateOperationNativeCallback(self, operation, arguments, cpp_callback_
name): | |
| 682 webcore_function_name = operation.ext_attrs.get('ImplementedAs', operation.i
d) | |
| 683 function_expression = self._GenerateWebCoreFunctionExpression(webcore_functi
on_name, operation) | |
| 684 self._GenerateNativeCallback( | |
| 685 cpp_callback_name, | |
| 686 not operation.is_static, | |
| 687 function_expression, | |
| 688 operation, | |
| 689 arguments, | |
| 690 operation.type.id, | |
| 691 operation.raises) | |
| 692 | |
| 693 def _GenerateNativeCallback(self, | |
| 694 callback_name, | |
| 695 needs_receiver, | |
| 696 function_expression, | |
| 697 node, | |
| 698 arguments, | |
| 699 return_type, | |
| 700 raises_dom_exception): | |
| 701 ext_attrs = node.ext_attrs | |
| 702 | |
| 703 cpp_arguments = [] | |
| 704 requires_v8_scope = \ | |
| 705 any((self._TypeInfo(argument.type.id).requires_v8_scope() for argument i
n arguments)) | |
| 706 runtime_check = None | |
| 707 raises_exceptions = raises_dom_exception or arguments | |
| 708 | |
| 709 requires_stack_info = ext_attrs.get('CallWith') == 'ScriptArguments|CallStac
k' | |
| 710 if requires_stack_info: | |
| 711 raises_exceptions = True | |
| 712 requires_v8_scope = True | |
| 713 cpp_arguments = ['scriptArguments', 'scriptCallStack'] | |
| 714 # WebKit uses scriptArguments to reconstruct last argument, so | |
| 715 # it's not needed and should be just removed. | |
| 716 arguments = arguments[:-1] | |
| 717 | |
| 718 requires_script_execution_context = ext_attrs.get('CallWith') == 'ScriptExec
utionContext' | |
| 719 if requires_script_execution_context: | |
| 720 raises_exceptions = True | |
| 721 cpp_arguments = ['context'] | |
| 722 | |
| 723 requires_dom_window = 'NamedConstructor' in ext_attrs | |
| 724 if requires_dom_window: | |
| 725 raises_exceptions = True | |
| 726 cpp_arguments = ['document'] | |
| 727 | |
| 728 if 'ImplementedBy' in ext_attrs: | |
| 729 assert needs_receiver | |
| 730 self._cpp_impl_includes.add('"%s.h"' % ext_attrs['ImplementedBy']) | |
| 731 cpp_arguments.append('receiver') | |
| 732 | |
| 733 if 'Reflect' in ext_attrs: | |
| 734 cpp_arguments = [self._GenerateWebCoreReflectionAttributeName(node)] | |
| 735 | |
| 736 v8EnabledPerContext = ext_attrs.get('synthesizedV8EnabledPerContext', ext_at
trs.get('V8EnabledPerContext')) | |
| 737 v8EnabledAtRuntime = ext_attrs.get('synthesizedV8EnabledAtRuntime', ext_attr
s.get('V8EnabledAtRuntime')) | |
| 738 assert(not (v8EnabledPerContext and v8EnabledAtRuntime)) | |
| 739 | |
| 740 if v8EnabledPerContext: | |
| 741 raises_exceptions = True | |
| 742 self._cpp_impl_includes.add('"ContextFeatures.h"') | |
| 743 self._cpp_impl_includes.add('"DOMWindow.h"') | |
| 744 runtime_check = emitter.Format( | |
| 745 ' if (!ContextFeatures::$(FEATURE)Enabled(DartUtilities::domWin
dowForCurrentIsolate()->document())) {\n' | |
| 746 ' exception = Dart_NewString("Feature $FEATURE is not enabl
ed");\n' | |
| 747 ' goto fail;\n' | |
| 748 ' }', | |
| 749 FEATURE=v8EnabledPerContext) | |
| 750 | |
| 751 if v8EnabledAtRuntime: | |
| 752 raises_exceptions = True | |
| 753 self._cpp_impl_includes.add('"RuntimeEnabledFeatures.h"') | |
| 754 runtime_check = emitter.Format( | |
| 755 ' if (!RuntimeEnabledFeatures::$(FEATURE)Enabled()) {\n' | |
| 756 ' exception = Dart_NewString("Feature $FEATURE is not enabl
ed");\n' | |
| 757 ' goto fail;\n' | |
| 758 ' }', | |
| 759 FEATURE=_ToWebKitName(v8EnabledAtRuntime)) | |
| 760 | |
| 761 body_emitter = self._cpp_definitions_emitter.Emit( | |
| 762 '\n' | |
| 763 'static void $CALLBACK_NAME(Dart_NativeArguments args)\n' | |
| 764 '{\n' | |
| 765 ' DartApiScope dartApiScope;\n' | |
| 766 '$!BODY' | |
| 767 '}\n', | |
| 768 CALLBACK_NAME=callback_name) | |
| 769 | |
| 770 if raises_exceptions: | |
| 771 body_emitter = body_emitter.Emit( | |
| 772 ' Dart_Handle exception = 0;\n' | |
| 773 '$!BODY' | |
| 774 '\n' | |
| 775 'fail:\n' | |
| 776 ' Dart_ThrowException(exception);\n' | |
| 777 ' ASSERT_NOT_REACHED();\n') | |
| 778 | |
| 779 body_emitter = body_emitter.Emit( | |
| 780 ' {\n' | |
| 781 '$!BODY' | |
| 782 ' return;\n' | |
| 783 ' }\n') | |
| 784 | |
| 785 if requires_v8_scope: | |
| 786 body_emitter.Emit( | |
| 787 ' V8Scope v8scope;\n\n') | |
| 788 | |
| 789 if runtime_check: | |
| 790 body_emitter.Emit( | |
| 791 '$RUNTIME_CHECK\n', | |
| 792 RUNTIME_CHECK=runtime_check) | |
| 793 | |
| 794 if requires_script_execution_context: | |
| 795 body_emitter.Emit( | |
| 796 ' ScriptExecutionContext* context = DartUtilities::scriptExecut
ionContext();\n' | |
| 797 ' if (!context) {\n' | |
| 798 ' exception = Dart_NewString("Failed to retrieve a context"
);\n' | |
| 799 ' goto fail;\n' | |
| 800 ' }\n\n') | |
| 801 | |
| 802 if requires_dom_window: | |
| 803 self._cpp_impl_includes.add('"DOMWindow.h"') | |
| 804 body_emitter.Emit( | |
| 805 ' DOMWindow* domWindow = DartUtilities::domWindowForCurrentIsol
ate();\n' | |
| 806 ' if (!domWindow) {\n' | |
| 807 ' exception = Dart_NewString("Failed to fetch domWindow");\
n' | |
| 808 ' goto fail;\n' | |
| 809 ' }\n' | |
| 810 ' Document* document = domWindow->document();\n') | |
| 811 | |
| 812 if needs_receiver: | |
| 813 body_emitter.Emit( | |
| 814 ' $WEBCORE_CLASS_NAME* receiver = DartDOMWrapper::receiver< $WE
BCORE_CLASS_NAME >(args);\n', | |
| 815 WEBCORE_CLASS_NAME=self._interface_type_info.native_type()) | |
| 816 | |
| 817 if requires_stack_info: | |
| 818 self._cpp_impl_includes.add('"ScriptArguments.h"') | |
| 819 self._cpp_impl_includes.add('"ScriptCallStack.h"') | |
| 820 body_emitter.Emit( | |
| 821 '\n' | |
| 822 ' Dart_Handle customArgument = Dart_GetNativeArgument(args, $IN
DEX);\n' | |
| 823 ' RefPtr<ScriptArguments> scriptArguments(DartUtilities::create
ScriptArguments(customArgument, exception));\n' | |
| 824 ' if (!scriptArguments)\n' | |
| 825 ' goto fail;\n' | |
| 826 ' RefPtr<ScriptCallStack> scriptCallStack(DartUtilities::create
ScriptCallStack());\n' | |
| 827 ' if (!scriptCallStack->size())\n' | |
| 828 ' return;\n', | |
| 829 INDEX=len(arguments) + 1) | |
| 830 | |
| 831 # Emit arguments. | |
| 832 start_index = 1 if needs_receiver else 0 | |
| 833 for i, argument in enumerate(arguments): | |
| 834 argument_expression_template, type, cls, function = \ | |
| 835 self._TypeInfo(argument.type.id).to_native_info(argument, self._interf
ace.id) | |
| 836 | |
| 837 if ((IsOptional(argument) and not self._IsArgumentOptionalInWebCore(node,
argument)) or | |
| 838 (argument.ext_attrs.get('Optional') == 'DefaultIsNullString')): | |
| 839 function += 'WithNullCheck' | |
| 840 | |
| 841 argument_name = DartDomNameOfAttribute(argument) | |
| 842 body_emitter.Emit( | |
| 843 '\n' | |
| 844 ' $TYPE $ARGUMENT_NAME = $CLS::$FUNCTION(Dart_GetNativeArgument
(args, $INDEX), exception);\n' | |
| 845 ' if (exception)\n' | |
| 846 ' goto fail;\n', | |
| 847 TYPE=type, | |
| 848 ARGUMENT_NAME=argument_name, | |
| 849 CLS=cls, | |
| 850 FUNCTION=function, | |
| 851 INDEX=start_index + i) | |
| 852 self._cpp_impl_includes.add('"%s.h"' % cls) | |
| 853 cpp_arguments.append(argument_expression_template % argument_name) | |
| 854 | |
| 855 body_emitter.Emit('\n') | |
| 856 | |
| 857 if 'NeedsUserGestureCheck' in ext_attrs: | |
| 858 cpp_arguments.append('DartUtilities::processingUserGesture') | |
| 859 | |
| 860 invocation_emitter = body_emitter | |
| 861 if raises_dom_exception: | |
| 862 cpp_arguments.append('ec') | |
| 863 invocation_emitter = body_emitter.Emit( | |
| 864 ' ExceptionCode ec = 0;\n' | |
| 865 '$!INVOCATION' | |
| 866 ' if (UNLIKELY(ec)) {\n' | |
| 867 ' exception = DartDOMWrapper::exceptionCodeToDartException(ec
);\n' | |
| 868 ' goto fail;\n' | |
| 869 ' }\n') | |
| 870 | |
| 871 function_call = '%s(%s)' % (function_expression, ', '.join(cpp_arguments)) | |
| 872 if return_type == 'void': | |
| 873 invocation_emitter.Emit( | |
| 874 ' $FUNCTION_CALL;\n', | |
| 875 FUNCTION_CALL=function_call) | |
| 876 else: | |
| 877 return_type_info = self._TypeInfo(return_type) | |
| 878 self._cpp_impl_includes |= set(return_type_info.conversion_includes()) | |
| 879 | |
| 880 # Generate to Dart conversion of C++ value. | |
| 881 to_dart_conversion = return_type_info.to_dart_conversion(function_call, se
lf._interface.id, ext_attrs) | |
| 882 invocation_emitter.Emit( | |
| 883 ' Dart_Handle returnValue = $TO_DART_CONVERSION;\n' | |
| 884 ' if (returnValue)\n' | |
| 885 ' Dart_SetReturnValue(args, returnValue);\n', | |
| 886 TO_DART_CONVERSION=to_dart_conversion) | |
| 887 | |
| 888 def _GenerateNativeBinding(self, idl_name, argument_count, dart_declaration, | |
| 889 native_suffix, is_custom): | |
| 890 native_binding = '%s_%s_%s' % (self._interface.id, idl_name, native_suffix) | |
| 891 self._members_emitter.Emit( | |
| 892 '\n' | |
| 893 ' $DART_DECLARATION native "$NATIVE_BINDING";\n', | |
| 894 DART_DECLARATION=dart_declaration, NATIVE_BINDING=native_binding) | |
| 895 | |
| 896 cpp_callback_name = '%s%s' % (idl_name, native_suffix) | |
| 897 self._cpp_resolver_emitter.Emit( | |
| 898 ' if (argumentCount == $ARGC && name == "$NATIVE_BINDING")\n' | |
| 899 ' return Dart$(INTERFACE_NAME)Internal::$CPP_CALLBACK_NAME;\n', | |
| 900 ARGC=argument_count, | |
| 901 NATIVE_BINDING=native_binding, | |
| 902 INTERFACE_NAME=self._interface.id, | |
| 903 CPP_CALLBACK_NAME=cpp_callback_name) | |
| 904 | |
| 905 if is_custom: | |
| 906 self._cpp_declarations_emitter.Emit( | |
| 907 '\n' | |
| 908 'void $CPP_CALLBACK_NAME(Dart_NativeArguments);\n', | |
| 909 CPP_CALLBACK_NAME=cpp_callback_name) | |
| 910 | |
| 911 return cpp_callback_name | |
| 912 | |
| 913 def _GenerateWebCoreReflectionAttributeName(self, attr): | |
| 914 namespace = 'HTMLNames' | |
| 915 svg_exceptions = ['class', 'id', 'onabort', 'onclick', 'onerror', 'onload', | |
| 916 'onmousedown', 'onmousemove', 'onmouseout', 'onmouseover', | |
| 917 'onmouseup', 'onresize', 'onscroll', 'onunload'] | |
| 918 if self._interface.id.startswith('SVG') and not attr.id in svg_exceptions: | |
| 919 namespace = 'SVGNames' | |
| 920 self._cpp_impl_includes.add('"%s.h"' % namespace) | |
| 921 | |
| 922 attribute_name = attr.ext_attrs['Reflect'] or attr.id.lower() | |
| 923 return 'WebCore::%s::%sAttr' % (namespace, attribute_name) | |
| 924 | |
| 925 def _GenerateWebCoreFunctionExpression(self, function_name, idl_node): | |
| 926 if 'ImplementedBy' in idl_node.ext_attrs: | |
| 927 return '%s::%s' % (idl_node.ext_attrs['ImplementedBy'], function_name) | |
| 928 if idl_node.is_static: | |
| 929 return '%s::%s' % (self._interface_type_info.idl_type(), function_name) | |
| 930 return '%s%s' % (self._interface_type_info.receiver(), function_name) | |
| 931 | |
| 932 def _TypeInfo(self, type_name): | |
| 933 return self._system._type_registry.TypeInfo(type_name) | |
| 934 | |
| 935 def _IsArgumentOptionalInWebCore(self, operation, argument): | |
| 936 if not IsOptional(argument): | |
| 937 return False | |
| 938 if 'Callback' in argument.ext_attrs: | |
| 939 return False | |
| 940 if operation.id in ['addEventListener', 'removeEventListener'] and argument.
id == 'useCapture': | |
| 941 return False | |
| 942 # Another option would be to adjust in IDLs, but let's keep it here for now | |
| 943 # as it's a single instance. | |
| 944 if self._interface.id == 'CSSStyleDeclaration' and operation.id == 'setPrope
rty' and argument.id == 'priority': | |
| 945 return False | |
| 946 return True | |
| 947 | |
| 948 | |
| 949 def _GenerateCPPIncludes(includes): | |
| 950 return ''.join(['#include %s\n' % include for include in sorted(includes)]) | |
| 951 | |
| 952 def _FindInHierarchy(database, interface, test): | |
| 953 if test(interface): | |
| 954 return interface | |
| 955 for parent in interface.parents: | |
| 956 parent_name = parent.type.id | |
| 957 if not database.HasInterface(parent.type.id): | |
| 958 continue | |
| 959 parent_interface = database.GetInterface(parent.type.id) | |
| 960 parent_interface = _FindInHierarchy(database, parent_interface, test) | |
| 961 if parent_interface: | |
| 962 return parent_interface | |
| 963 | |
| 964 def _ToWebKitName(name): | |
| 965 name = name[0].lower() + name[1:] | |
| 966 name = re.sub(r'^(hTML|uRL|jS|xML|xSLT)', lambda s: s.group(1).lower(), | |
| 967 name) | |
| 968 return re.sub(r'^(create|exclusive)', lambda s: 'is' + s.group(1).capitalize()
, | |
| 969 name) | |
| OLD | NEW |