| #!/usr/bin/env python3 | |
| # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
| # for details. All rights reserved. Use of this source code is governed by a | |
| # BSD-style license that can be found in the LICENSE file. | |
| """This module provides shared functionality for the systems to generate | |
| native binding from the IDL database.""" | |
| import emitter | |
| import logging | |
| import os | |
| from generator import * | |
| from htmldartgenerator import * | |
| from idlnode import IDLArgument, IDLAttribute, IDLEnum, IDLMember | |
| from systemhtml import js_support_checks, GetCallbackInfo, HTML_LIBRARY_NAMES | |
| _logger = logging.getLogger('systemnative') | |
| # TODO(vsm): This should be recoverable from IDL, but we appear to not | |
| # track the necessary info. | |
| _url_utils = [ | |
| 'hash', 'host', 'hostname', 'origin', 'password', 'pathname', 'port', | |
| 'protocol', 'search', 'username' | |
| ] | |
| _promise_to_future = Conversion('promiseToFuture', 'dynamic', 'Future') | |
| def array_type(data_type): | |
| matched = re.match(r'([\w\d_\s]+)\[\]', data_type) | |
| if not matched: | |
| return None | |
| return matched.group(1) | |
| _sequence_matcher = re.compile('sequence\<(.+)\>') | |
| def TypeIdToBlinkName(interface_id, database): | |
| # Maybe should use the type_registry here? | |
| if database.HasEnum(interface_id): | |
| return "DOMString" # All enums are strings. | |
| seq_match = _sequence_matcher.match(interface_id) | |
| if seq_match is not None: | |
| t = TypeIdToBlinkName(seq_match.group(1), database) | |
| return "sequence<%s>" % t | |
| arr_match = array_type(interface_id) | |
| if arr_match is not None: | |
| t = TypeIdToBlinkName(arr_match, database) | |
| return "%s[]" % t | |
| return interface_id | |
| def DeriveQualifiedName(library_name, name): | |
| return library_name + "." + name | |
| def DeriveBlinkClassName(name): | |
| return "Blink" + name | |
| _type_encoding_map = { | |
| 'long long': "ll", | |
| 'unsigned long': "ul", | |
| 'unsigned long long': "ull", | |
| 'unsigned short': "us", | |
| } | |
| def EncodeType(t): | |
| seq_match = _sequence_matcher.match(t) | |
| if seq_match is not None: | |
| t2 = EncodeType(seq_match.group(1)) | |
| t = "SEQ_%s_SEQ" % t2 | |
| return t | |
| arr_match = array_type(t) | |
| if arr_match is not None: | |
| t = EncodeType(arr_match) | |
| return "A_%s_A" % t | |
| return _type_encoding_map.get(t) or t | |
| class DartiumBackend(HtmlDartGenerator): | |
| """Generates Dart implementation for one DOM IDL interface.""" | |
| def __init__(self, interface, cpp_library_emitter, options, loggerParent): | |
| super(DartiumBackend, self).__init__(interface, options, True, | |
| loggerParent) | |
| self._interface = interface | |
| self._cpp_library_emitter = cpp_library_emitter | |
| self._database = options.database | |
| self._template_loader = options.templates | |
| self._type_registry = options.type_registry | |
| self._interface_type_info = self._type_registry.TypeInfo( | |
| self._interface.id) | |
| self._metadata = options.metadata | |
| # These get initialized by StartInterface | |
| self._cpp_header_emitter = None | |
| self._cpp_impl_emitter = None | |
| self._members_emitter = None | |
| self._cpp_declarations_emitter = None | |
| self._cpp_impl_includes = None | |
| self._cpp_definitions_emitter = None | |
| self._cpp_resolver_emitter = None | |
| self._dart_js_interop = options.dart_js_interop | |
| _logger.setLevel(loggerParent.level) | |
| def ImplementsMergedMembers(self): | |
| # We could not add merged functions to implementation class because | |
| # underlying c++ object doesn't implement them. Merged functions are | |
| # generated on merged interface implementation instead. | |
| return False | |
| def CustomJSMembers(self): | |
| return {} | |
| def _OutputConversion(self, idl_type, member): | |
| conversion = FindConversion(idl_type, 'get', self._interface.id, member) | |
| # TODO(jacobr) handle promise consistently in dart2js and dartium. | |
| if idl_type == 'Promise': | |
| return _promise_to_future | |
| if conversion: | |
| if conversion.function_name in ('convertNativeToDart_DateTime', | |
| 'convertNativeToDart_ImageData'): | |
| return None | |
| return conversion | |
| def _InputConversion(self, idl_type, member): | |
| return FindConversion(idl_type, 'set', self._interface.id, member) | |
| def GenerateCallback(self, info): | |
| return None | |
| def ImplementationTemplate(self): | |
| template = None | |
| interface_name = self._interface.doc_js_name | |
| if interface_name == self._interface.id or not self._database.HasInterface( | |
| interface_name): | |
| template_file = 'impl_%s.darttemplate' % interface_name | |
| template = self._template_loader.TryLoad(template_file) | |
| if not template: | |
| template = self._template_loader.Load( | |
| 'dart_implementation.darttemplate') | |
| return template | |
| def RootClassName(self): | |
| return 'DartHtmlDomObject' | |
| # This code matches up with the _generate_native_entry code in | |
| # dart_utilities.py in the dartium repository. Any changes to this | |
| # should have matching changes on that end. | |
| def DeriveNativeEntry(self, name, kind, count): | |
| interface_id = self._interface.id | |
| database = self._database | |
| tag = "" | |
| if kind == 'Getter': | |
| tag = "%s_Getter" % name | |
| blink_entry = tag | |
| elif kind == 'Setter': | |
| tag = "%s_Setter" % name | |
| blink_entry = tag | |
| elif kind == 'Constructor': | |
| tag = "constructorCallback" | |
| blink_entry = tag | |
| elif kind == 'Method': | |
| tag = "%s_Callback" % name | |
| blink_entry = tag | |
| interface_id = TypeIdToBlinkName(interface_id, database) | |
| def mkPublic(s): | |
| if s.startswith("_") or s.startswith("$"): | |
| return "$" + s | |
| return s | |
| if count is not None: | |
| arity = str(count) | |
| dart_name = mkPublic("_".join([tag, arity])) | |
| else: | |
| dart_name = mkPublic(tag) | |
| resolver_string = "_".join([interface_id, tag]) | |
| return (dart_name, resolver_string) | |
| def DeriveNativeName(self, name, suffix=""): | |
| fields = ['$' + name] | |
| if suffix != "": | |
| fields.append(suffix) | |
| return "_".join(fields) | |
| def DeriveQualifiedBlinkName(self, interface_name, name): | |
| blinkClass = DeriveQualifiedName("_blink", | |
| DeriveBlinkClassName(interface_name)) | |
| blinkInstance = DeriveQualifiedName(blinkClass, "instance") | |
| return DeriveQualifiedName(blinkInstance, name + "_") | |
| def NativeSpec(self): | |
| return '' | |
| def StartInterface(self, members_emitter): | |
| # Create emitters for c++ implementation. | |
| if not IsPureInterface(self._interface.id, self._database) and \ | |
| not IsCustomType(self._interface.id): | |
| self._cpp_header_emitter = self._cpp_library_emitter.CreateHeaderEmitter( | |
| self._interface.id, | |
| self._renamer.GetLibraryName(self._interface)) | |
| self._cpp_impl_emitter = \ | |
| self._cpp_library_emitter.CreateSourceEmitter(self._interface.id) | |
| else: | |
| self._cpp_header_emitter = emitter.Emitter() | |
| self._cpp_impl_emitter = emitter.Emitter() | |
| self._interface_type_info = self._TypeInfo(self._interface.id) | |
| self._members_emitter = members_emitter | |
| self._cpp_declarations_emitter = emitter.Emitter() | |
| # This is a hack to work around a strange C++ compile error that we weren't | |
| # able to track down the true cause of. | |
| if self._interface.id == 'Timing': | |
| self._cpp_impl_includes.add('"core/animation/TimedItem.h"') | |
| self._cpp_definitions_emitter = emitter.Emitter() | |
| self._cpp_resolver_emitter = emitter.Emitter() | |
| # We need to revisit our treatment of typed arrays, right now | |
| # it is full of hacks. | |
| if self._interface.ext_attrs.get('ConstructorTemplate') == 'TypedArray': | |
| self._cpp_resolver_emitter.Emit( | |
| ' if (name == "$(INTERFACE_NAME)_constructor_Callback")\n' | |
| ' return Dart$(INTERFACE_NAME)Internal::constructorCallback;\n', | |
| INTERFACE_NAME=self._interface.id) | |
| self._cpp_impl_includes.add('"DartArrayBufferViewCustom.h"') | |
| self._cpp_definitions_emitter.Emit( | |
| '\n' | |
| 'static void constructorCallback(Dart_NativeArguments args)\n' | |
| '{\n' | |
| ' WebCore::DartArrayBufferViewInternal::constructWebGLArray<Dart$(INTERFACE_NAME)>(args);\n' | |
| '}\n', | |
| INTERFACE_NAME=self._interface.id) | |
| def _EmitConstructorInfrastructure(self, | |
| constructor_info, | |
| cpp_prefix, | |
| cpp_suffix, | |
| factory_method_name, | |
| arguments=None, | |
| emit_to_native=False, | |
| is_custom=False): | |
| constructor_callback_cpp_name = cpp_prefix + cpp_suffix | |
| if arguments is None: | |
| arguments = constructor_info.idl_args[0] | |
| argument_count = len(arguments) | |
| else: | |
| argument_count = len(arguments) | |
| typed_formals = constructor_info.ParametersAsArgumentList( | |
| argument_count) | |
| parameters = constructor_info.ParametersAsStringOfVariables( | |
| argument_count) | |
| interface_name = self._interface_type_info.interface_name() | |
| dart_native_name, constructor_callback_id = \ | |
| self.DeriveNativeEntry(cpp_suffix, 'Constructor', argument_count) | |
| # Then we emit the impedance matching wrapper to call out to the | |
| # toplevel wrapper | |
| if not emit_to_native: | |
| toplevel_name = \ | |
| self.DeriveQualifiedBlinkName(self._interface.id, | |
| dart_native_name) | |
| self._members_emitter.Emit( | |
| ' static $INTERFACE_NAME $FACTORY_METHOD_NAME($PARAMETERS) => ' | |
| '$TOPLEVEL_NAME($OUTPARAMETERS);\n', | |
| INTERFACE_NAME=self._interface_type_info.interface_name(), | |
| FACTORY_METHOD_NAME=factory_method_name, | |
| PARAMETERS=typed_formals, | |
| TOPLEVEL_NAME=toplevel_name, | |
| OUTPARAMETERS=parameters) | |
| self._cpp_resolver_emitter.Emit( | |
| ' if (name == "$ID")\n' | |
| ' return Dart$(WEBKIT_INTERFACE_NAME)Internal::$CPP_CALLBACK;\n', | |
| ID=constructor_callback_id, | |
| WEBKIT_INTERFACE_NAME=self._interface.id, | |
| CPP_CALLBACK=constructor_callback_cpp_name) | |
| def GenerateCustomFactory(self, constructor_info): | |
| if 'CustomConstructor' not in self._interface.ext_attrs: | |
| return False | |
| annotations = self._metadata.GetFormattedMetadata( | |
| self._library_name, self._interface, self._interface.id, ' ') | |
| self._members_emitter.Emit( | |
| '\n $(ANNOTATIONS)factory $CTOR($PARAMS) => _create($FACTORY_PARAMS);\n', | |
| ANNOTATIONS=annotations, | |
| CTOR=constructor_info._ConstructorFullName(self._DartType), | |
| PARAMS=constructor_info.ParametersAsDeclaration(self._DartType), | |
| FACTORY_PARAMS= \ | |
| constructor_info.ParametersAsArgumentList()) | |
| # MutationObserver has custom _create. TODO(terry): Consider table but this is only one. | |
| if self._interface.id != 'MutationObserver': | |
| constructor_callback_cpp_name = 'constructorCallback' | |
| self._EmitConstructorInfrastructure( | |
| constructor_info, | |
| "", | |
| constructor_callback_cpp_name, | |
| '_create', | |
| is_custom=True) | |
| self._cpp_declarations_emitter.Emit( | |
| '\n' | |
| 'void $CPP_CALLBACK(Dart_NativeArguments);\n', | |
| CPP_CALLBACK=constructor_callback_cpp_name) | |
| return True | |
| def IsConstructorArgumentOptional(self, argument): | |
| return IsOptional(argument) | |
| def MakeFactoryCall(self, factory, method, arguments, constructor_info): | |
| return emitter.Format( | |
| '$FACTORY.$METHOD($ARGUMENTS)', | |
| FACTORY=factory, | |
| METHOD=method, | |
| ARGUMENTS=arguments) | |
| def EmitStaticFactoryOverload(self, constructor_info, name, arguments): | |
| constructor_callback_cpp_name = name + 'constructorCallback' | |
| self._EmitConstructorInfrastructure( | |
| constructor_info, | |
| name, | |
| 'constructorCallback', | |
| name, | |
| arguments, | |
| emit_to_native=True, | |
| is_custom=False) | |
| ext_attrs = self._interface.ext_attrs | |
| create_function = 'create' | |
| if 'NamedConstructor' in ext_attrs: | |
| create_function = 'createForJSConstructor' | |
| function_expression = '%s::%s' % ( | |
| self._interface_type_info.native_type(), create_function) | |
| def HasSupportCheck(self): | |
| # Need to omit a support check if it is conditional in JS. | |
| return self._interface.doc_js_name in js_support_checks | |
| def GetSupportCheck(self): | |
| # Assume that everything is supported on Dartium. | |
| value = js_support_checks.get(self._interface.doc_js_name) | |
| if type(value) == tuple: | |
| return (value[0], 'true') | |
| else: | |
| return 'true' | |
| def FinishInterface(self): | |
| interface = self._interface | |
| if interface.parents: | |
| supertype = '%sClassId' % interface.parents[0].type.id | |
| else: | |
| supertype = '-1' | |
| self._GenerateCPPHeader() | |
| self._cpp_impl_emitter.Emit( | |
| self._template_loader.Load('cpp_implementation.template'), | |
| INTERFACE=self._interface.id, | |
| SUPER_INTERFACE=supertype, | |
| INCLUDES=self._GenerateCPPIncludes(self._cpp_impl_includes), | |
| CALLBACKS=self._cpp_definitions_emitter.Fragments(), | |
| RESOLVER=self._cpp_resolver_emitter.Fragments(), | |
| WEBCORE_CLASS_NAME=self._interface_type_info.native_type(), | |
| WEBCORE_CLASS_NAME_ESCAPED=self._interface_type_info.native_type(). | |
| replace('<', '_').replace('>', '_'), | |
| DART_IMPLEMENTATION_CLASS=self._interface_type_info. | |
| implementation_name(), | |
| DART_IMPLEMENTATION_LIBRARY_ID='Dart%sLibraryId' % | |
| self._renamer.GetLibraryId(self._interface)) | |
| def _GenerateCPPHeader(self): | |
| to_native_emitter = emitter.Emitter() | |
| if self._interface_type_info.custom_to_native(): | |
| return_type = 'PassRefPtr<NativeType>' | |
| to_native_body = ';' | |
| to_native_arg_body = ';' | |
| else: | |
| return_type = 'NativeType*' | |
| to_native_body = emitter.Format( | |
| '\n' | |
| ' {\n' | |
| ' DartDOMData* domData = DartDOMData::current();\n' | |
| ' return DartDOMWrapper::unwrapDartWrapper<Dart$INTERFACE>(domData, handle, exception);\n' | |
| ' }', | |
| INTERFACE=self._interface.id) | |
| to_native_arg_body = emitter.Format( | |
| '\n' | |
| ' {\n' | |
| ' return DartDOMWrapper::unwrapDartWrapper<Dart$INTERFACE>(args, index, exception);\n' | |
| ' }', | |
| INTERFACE=self._interface.id) | |
| to_native_emitter.Emit( | |
| ' static $RETURN_TYPE toNative(Dart_Handle handle, Dart_Handle& exception)$TO_NATIVE_BODY\n' | |
| '\n' | |
| ' static $RETURN_TYPE toNativeWithNullCheck(Dart_Handle handle, Dart_Handle& exception)\n' | |
| ' {\n' | |
| ' return Dart_IsNull(handle) ? 0 : toNative(handle, exception);\n' | |
| ' }\n' | |
| '\n' | |
| ' static $RETURN_TYPE toNative(Dart_NativeArguments args, int index, Dart_Handle& exception)$TO_NATIVE_ARG_BODY\n' | |
| '\n' | |
| ' static $RETURN_TYPE toNativeWithNullCheck(Dart_NativeArguments args, int index, Dart_Handle& exception)\n' | |
| ' {\n' | |
| ' // toNative accounts for Null objects also.\n' | |
| ' return toNative(args, index, exception);\n' | |
| ' }\n', | |
| RETURN_TYPE=return_type, | |
| TO_NATIVE_BODY=to_native_body, | |
| TO_NATIVE_ARG_BODY=to_native_arg_body, | |
| INTERFACE=self._interface.id) | |
| to_dart_emitter = emitter.Emitter() | |
| ext_attrs = self._interface.ext_attrs | |
| to_dart_emitter.Emit( | |
| ' static Dart_Handle toDart(NativeType* value)\n' | |
| ' {\n' | |
| ' if (!value)\n' | |
| ' return Dart_Null();\n' | |
| ' DartDOMData* domData = DartDOMData::current();\n' | |
| ' Dart_WeakPersistentHandle result =\n' | |
| ' DartDOMWrapper::lookupWrapper<Dart$(INTERFACE)>(domData, value);\n' | |
| ' if (result)\n' | |
| ' return Dart_HandleFromWeakPersistent(result);\n' | |
| ' return createWrapper(domData, value);\n' | |
| ' }\n' | |
| ' static void returnToDart(Dart_NativeArguments args,\n' | |
| ' NativeType* value,\n' | |
| ' bool autoDartScope = true)\n' | |
| ' {\n' | |
| ' if (value) {\n' | |
| ' DartDOMData* domData = static_cast<DartDOMData*>(\n' | |
| ' Dart_GetNativeIsolateData(args));\n' | |
| ' Dart_WeakPersistentHandle result =\n' | |
| ' DartDOMWrapper::lookupWrapper<Dart$(INTERFACE)>(domData, value);\n' | |
| ' if (result)\n' | |
| ' Dart_SetWeakHandleReturnValue(args, result);\n' | |
| ' else {\n' | |
| ' if (autoDartScope) {\n' | |
| ' Dart_SetReturnValue(args, createWrapper(domData, value));\n' | |
| ' } else {\n' | |
| ' DartApiScope apiScope;\n' | |
| ' Dart_SetReturnValue(args, createWrapper(domData, value));\n' | |
| ' }\n' | |
| ' }\n' | |
| ' }\n' | |
| ' }\n', | |
| INTERFACE=self._interface.id) | |
| if ('CustomToV8' in ext_attrs or 'PureInterface' in ext_attrs or | |
| 'CPPPureInterface' in ext_attrs or | |
| 'SpecialWrapFor' in ext_attrs or | |
| ('Custom' in ext_attrs and ext_attrs['Custom'] == 'Wrap') or | |
| ('Custom' in ext_attrs and ext_attrs['Custom'] == 'ToV8') or | |
| self._interface_type_info.custom_to_dart()): | |
| to_dart_emitter.Emit( | |
| ' static Dart_Handle createWrapper(DartDOMData* domData, NativeType* value);\n' | |
| ) | |
| else: | |
| to_dart_emitter.Emit( | |
| ' static Dart_Handle createWrapper(DartDOMData* domData, NativeType* value)\n' | |
| ' {\n' | |
| ' return DartDOMWrapper::createWrapper<Dart$(INTERFACE)>(domData, value, Dart$(INTERFACE)::dartClassId);\n' | |
| ' }\n', | |
| INTERFACE=self._interface.id) | |
| webcore_includes = self._GenerateCPPIncludes( | |
| self._interface_type_info.webcore_includes()) | |
| is_node_test = lambda interface: interface.id == 'Node' | |
| is_active_test = lambda interface: 'ActiveDOMObject' in interface.ext_attrs | |
| is_event_target_test = lambda interface: 'EventTarget' in interface.ext_attrs | |
| def TypeCheckHelper(test): | |
| return 'true' if any( | |
| map(test, self._database.Hierarchy( | |
| self._interface))) else 'false' | |
| to_active_emitter = emitter.Emitter() | |
| to_node_emitter = emitter.Emitter() | |
| to_event_target_emitter = emitter.Emitter() | |
| if (any(map(is_active_test, | |
| self._database.Hierarchy(self._interface)))): | |
| to_active_emitter.Emit('return toNative(value);') | |
| else: | |
| to_active_emitter.Emit('return 0;') | |
| if (any(map(is_node_test, self._database.Hierarchy(self._interface)))): | |
| to_node_emitter.Emit('return toNative(value);') | |
| else: | |
| to_node_emitter.Emit('return 0;') | |
| if (any( | |
| map(is_event_target_test, | |
| self._database.Hierarchy(self._interface)))): | |
| to_event_target_emitter.Emit('return toNative(value);') | |
| else: | |
| to_event_target_emitter.Emit('return 0;') | |
| v8_interface_include = '' | |
| # V8AbstractWorker.h does not exist so we have to hard code this case. | |
| if self._interface.id != 'AbstractWorker': | |
| # FIXME: We need this to access the WrapperTypeInfo. | |
| v8_interface_include = '#include "V8%s.h"' % (self._interface.id) | |
| self._cpp_header_emitter.Emit( | |
| self._template_loader.Load('cpp_header.template'), | |
| INTERFACE=self._interface.id, | |
| WEBCORE_INCLUDES=webcore_includes, | |
| V8_INTERFACE_INCLUDE=v8_interface_include, | |
| WEBCORE_CLASS_NAME=self._interface_type_info.native_type(), | |
| WEBCORE_CLASS_NAME_ESCAPED=self._interface_type_info.native_type(). | |
| replace('<', '_').replace('>', '_'), | |
| DECLARATIONS=self._cpp_declarations_emitter.Fragments(), | |
| IS_NODE=TypeCheckHelper(is_node_test), | |
| IS_ACTIVE=TypeCheckHelper(is_active_test), | |
| IS_EVENT_TARGET=TypeCheckHelper(is_event_target_test), | |
| TO_NODE=to_node_emitter.Fragments(), | |
| TO_ACTIVE=to_active_emitter.Fragments(), | |
| TO_EVENT_TARGET=to_event_target_emitter.Fragments(), | |
| TO_NATIVE=to_native_emitter.Fragments(), | |
| TO_DART=to_dart_emitter.Fragments()) | |
| def EmitAttribute(self, attribute, html_name, read_only): | |
| self._AddGetter(attribute, html_name, read_only) | |
| if not read_only: | |
| self._AddSetter(attribute, html_name) | |
| def _GenerateAutoSetupScope(self, idl_name, native_suffix): | |
| return None | |
| def _AddGetter(self, attr, html_name, read_only): | |
| # Temporary hack to force dart:scalarlist clamped array for ImageData.data. | |
| # TODO(antonm): solve in principled way. | |
| if self._interface.id == 'ImageData' and html_name == 'data': | |
| html_name = '_data' | |
| type_info = self._TypeInfo(attr.type.id) | |
| return_type = self.SecureOutputType( | |
| attr.type.id, False, False if self._dart_use_blink else True) | |
| dictionary_returned = False | |
| # Return type for dictionary is any (untyped). | |
| if attr.type.id == 'Dictionary': | |
| return_type = '' | |
| dictionary_returned = True | |
| parameters = [] | |
| dart_declaration = '%s get %s' % (return_type, html_name) | |
| is_custom = _IsCustom(attr) and (_IsCustomValue(attr, None) or | |
| _IsCustomValue(attr, 'Getter')) | |
| # Operation uses blink? | |
| wrap_unwrap_list = [] | |
| return_wrap_jso = False | |
| if self._dart_use_blink: | |
| # Unwrap the type to get the JsObject if Type is: | |
| # | |
| # - known IDL type | |
| # - type_id is None then it's probably a union type or overloaded | |
| # it's a dynamic/any type | |
| # - type is Object | |
| # | |
| # JsObject maybe stored in the Dart class. | |
| return_wrap_jso = wrap_return_type_blink(return_type, attr.type.id, | |
| self._type_registry) | |
| wrap_unwrap_list.append(return_wrap_jso) # wrap_jso the returned object | |
| wrap_unwrap_list.append(self._dart_use_blink) | |
| # This seems to have been replaced with Custom=Getter (see above), but | |
| # check to be sure we don't see the old syntax | |
| assert (not ('CustomGetter' in attr.ext_attrs)) | |
| native_suffix = 'Getter' | |
| auto_scope_setup = self._GenerateAutoSetupScope(attr.id, native_suffix) | |
| native_entry = \ | |
| self.DeriveNativeEntry(attr.id, 'Getter', None) | |
| output_conversion = self._OutputConversion(attr.type.id, attr.id) | |
| cpp_callback_name = self._GenerateNativeBinding( | |
| attr.id, | |
| 1, | |
| dart_declaration, | |
| attr.is_static, | |
| return_type, | |
| parameters, | |
| native_suffix, | |
| is_custom, | |
| auto_scope_setup, | |
| native_entry=native_entry, | |
| wrap_unwrap_list=wrap_unwrap_list, | |
| dictionary_return=dictionary_returned, | |
| output_conversion=output_conversion) | |
| if is_custom: | |
| return | |
| if 'Reflect' in attr.ext_attrs: | |
| webcore_function_name = self._TypeInfo( | |
| attr.type.id).webcore_getter_name() | |
| if 'URL' in attr.ext_attrs: | |
| if 'NonEmpty' in attr.ext_attrs: | |
| webcore_function_name = 'getNonEmptyURLAttribute' | |
| else: | |
| webcore_function_name = 'getURLAttribute' | |
| elif 'ImplementedAs' in attr.ext_attrs: | |
| webcore_function_name = attr.ext_attrs['ImplementedAs'] | |
| else: | |
| if attr.id == 'operator': | |
| webcore_function_name = '_operator' | |
| elif attr.id == 'target' and attr.type.id == 'SVGAnimatedString': | |
| webcore_function_name = 'svgTarget' | |
| elif attr.id == 'CSS': | |
| webcore_function_name = 'css' | |
| else: | |
| webcore_function_name = self._ToWebKitName(attr.id) | |
| function_expression = self._GenerateWebCoreFunctionExpression( | |
| webcore_function_name, attr) | |
| raises = ('RaisesException' in attr.ext_attrs and | |
| attr.ext_attrs['RaisesException'] != 'Setter') | |
| def _AddSetter(self, attr, html_name): | |
| return_type = 'void' | |
| ptype = self._DartType(attr.type.id) | |
| type_info = self._TypeInfo(attr.type.id) | |
| # Is the setter value a DartClass (that has a JsObject) or the type is | |
| # None (it's a dynamic/any type) then unwrap_jso before passing to blink. | |
| parameters = ['value'] | |
| dart_declaration = 'set %s(%s value)' % (html_name, ptype) | |
| is_custom = _IsCustom(attr) and (_IsCustomValue(attr, None) or | |
| _IsCustomValue(attr, 'Setter')) | |
| # This seems to have been replaced with Custom=Setter (see above), but | |
| # check to be sure we don't see the old syntax | |
| assert (not ('CustomSetter' in attr.ext_attrs)) | |
| assert (not ('V8CustomSetter' in attr.ext_attrs)) | |
| native_suffix = 'Setter' | |
| auto_scope_setup = self._GenerateAutoSetupScope(attr.id, native_suffix) | |
| native_entry = \ | |
| self.DeriveNativeEntry(attr.id, 'Setter', None) | |
| # setters return no object and if blink this must be unwrapped.? | |
| wrap_unwrap_list = [False, self._dart_use_blink] | |
| cpp_callback_name = self._GenerateNativeBinding( | |
| attr.id, | |
| 2, | |
| dart_declaration, | |
| attr.is_static, | |
| return_type, | |
| parameters, | |
| native_suffix, | |
| is_custom, | |
| auto_scope_setup, | |
| native_entry=native_entry, | |
| wrap_unwrap_list=wrap_unwrap_list) | |
| if is_custom: | |
| return | |
| if 'Reflect' in attr.ext_attrs: | |
| webcore_function_name = self._TypeInfo( | |
| attr.type.id).webcore_setter_name() | |
| else: | |
| if 'ImplementedAs' in attr.ext_attrs: | |
| attr_name = attr.ext_attrs['ImplementedAs'] | |
| else: | |
| attr_name = attr.id | |
| webcore_function_name = re.sub(r'^(xml|css|(?=[A-Z])|\w)', | |
| lambda s: s.group(1).upper(), | |
| attr_name) | |
| webcore_function_name = 'set%s' % webcore_function_name | |
| function_expression = self._GenerateWebCoreFunctionExpression( | |
| webcore_function_name, attr) | |
| raises = ('RaisesException' in attr.ext_attrs and | |
| attr.ext_attrs['RaisesException'] != 'Getter') | |
| def AddIndexer(self, element_type, nullable): | |
| """Adds all the methods required to complete implementation of List.""" | |
| # We would like to simply inherit the implementation of everything except | |
| # length, [], and maybe []=. It is possible to extend from a base | |
| # array implementation class only when there is no other implementation | |
| # inheritance. There might be no implementation inheritance other than | |
| # DOMBaseWrapper for many classes, but there might be some where the | |
| # array-ness is introduced by a non-root interface: | |
| # | |
| # interface Y extends X, List<T> ... | |
| # | |
| # In the non-root case we have to choose between: | |
| # | |
| # class YImpl extends XImpl { add List<T> methods; } | |
| # | |
| # and | |
| # | |
| # class YImpl extends ListBase<T> { copies of transitive XImpl methods; } | |
| # | |
| dart_element_type = self._DartType(element_type) | |
| if self._HasNativeIndexGetter(): | |
| self._EmitNativeIndexGetter(dart_element_type) | |
| elif self._HasExplicitIndexedGetter(): | |
| self._EmitExplicitIndexedGetter(dart_element_type) | |
| else: | |
| is_custom = any((op.id == 'item' and _IsCustom(op)) | |
| for op in self._interface.operations) | |
| output_conversion = self._OutputConversion(element_type, 'item') | |
| conversion_name = '' | |
| if output_conversion: | |
| conversion_name = output_conversion.function_name | |
| # First emit a toplevel function to do the native call | |
| # Calls to this are emitted elsewhere, | |
| dart_native_name, resolver_string = \ | |
| self.DeriveNativeEntry("item", 'Method', 1) | |
| # Emit the method which calls the toplevel function, along with | |
| # the [] operator. | |
| dart_qualified_name = \ | |
| self.DeriveQualifiedBlinkName(self._interface.id, | |
| dart_native_name) | |
| type_info = self._TypeInfo(element_type) | |
| blinkNativeIndexed = """ | |
| $TYPE operator[](int index) { | |
| if (index < 0 || index >= length) | |
| throw new IndexError.withLength(index, length, indexable: this); | |
| return _nativeIndexedGetter(index); | |
| } | |
| $TYPE _nativeIndexedGetter(int index) => $(CONVERSION_NAME)($(DART_NATIVE_NAME)(this, index)); | |
| """ | |
| blinkNativeIndexedGetter = \ | |
| ' $(DART_NATIVE_NAME)(this, index);\n' | |
| self._members_emitter.Emit( | |
| blinkNativeIndexed, | |
| DART_NATIVE_NAME=dart_qualified_name, | |
| TYPE=self.SecureOutputType(element_type), | |
| INTERFACE=self._interface.id, | |
| CONVERSION_NAME=conversion_name) | |
| if self._HasNativeIndexSetter(): | |
| self._EmitNativeIndexSetter(dart_element_type) | |
| else: | |
| self._members_emitter.Emit( | |
| '\n' | |
| ' void operator[]=(int index, $TYPE value) {\n' | |
| ' throw new UnsupportedError("Cannot assign element of immutable List.");\n' | |
| ' }\n', | |
| TYPE=dart_element_type) | |
| self.EmitListMixin(dart_element_type, nullable) | |
| def AmendIndexer(self, element_type): | |
| # If interface is marked as having native indexed | |
| # getter or setter, we must emit overrides as it's not | |
| # guaranteed that the corresponding methods in C++ would be | |
| # virtual. For example, as of time of writing, even though | |
| # Uint8ClampedArray inherits from Uint8Array, ::set method | |
| # is not virtual and accessing it through Uint8Array pointer | |
| # would lead to wrong semantics (modulo vs. clamping.) | |
| dart_element_type = self._DartType(element_type) | |
| if self._HasNativeIndexGetter(): | |
| self._EmitNativeIndexGetter(dart_element_type) | |
| if self._HasNativeIndexSetter(): | |
| self._EmitNativeIndexSetter(dart_element_type) | |
| def _HasNativeIndexGetter(self): | |
| return 'CustomIndexedGetter' in self._interface.ext_attrs | |
| def _EmitNativeIndexGetter(self, element_type): | |
| return_type = self.SecureOutputType(element_type, True) | |
| parameters = ['index'] | |
| dart_declaration = '%s operator[](int index)' % return_type | |
| self._GenerateNativeBinding('numericIndexGetter', 2, dart_declaration, | |
| False, return_type, parameters, 'Callback', | |
| True, False) | |
| def _HasExplicitIndexedGetter(self): | |
| return any(op.id == 'getItem' for op in self._interface.operations) | |
| def _EmitExplicitIndexedGetter(self, dart_element_type): | |
| if any(op.id == 'getItem' for op in self._interface.operations): | |
| indexed_getter = 'getItem' | |
| self._members_emitter.Emit( | |
| '\n' | |
| ' $TYPE operator[](int index) {\n' | |
| ' if (index < 0 || index >= length)\n' | |
| ' throw new IndexError.withLength(index, length, indexable: this);\n' | |
| ' return $INDEXED_GETTER(index);\n' | |
| ' }\n', | |
| TYPE=dart_element_type, | |
| INDEXED_GETTER=indexed_getter) | |
| def _HasNativeIndexSetter(self): | |
| return 'CustomIndexedSetter' in self._interface.ext_attrs | |
| def _EmitNativeIndexSetter(self, element_type): | |
| return_type = 'void' | |
| formals = ', '.join(['int index', '%s value' % element_type]) | |
| parameters = ['index', 'value'] | |
| dart_declaration = 'void operator[]=(%s)' % formals | |
| self._GenerateNativeBinding('numericIndexSetter', 3, dart_declaration, | |
| False, return_type, parameters, 'Callback', | |
| True, False) | |
| def _ChangePrivateOpMapArgToAny(self, operations): | |
| # TODO(terry): Hack to map any operations marked as private to not | |
| # handle converting Map to native (JsObject) the public | |
| # members that call the private method will have done | |
| # conversions. | |
| for operation in operations: | |
| for arg in operation.arguments: | |
| type = arg.type | |
| if type.id == 'Dictionary': | |
| type.id = 'any' | |
| def EmitOperation(self, info, html_name, dart_js_interop=False): | |
| """ | |
| Arguments: | |
| info: An OperationInfo object. | |
| """ | |
| if self._renamer.isPrivate(self._interface, info.operations[0].id): | |
| # Any private operations with Maps parameters changed to any type. | |
| # The public method that delegates to this private operation has already | |
| # converted from Map to native (JsObject) e.g., Element.animate. | |
| self._ChangePrivateOpMapArgToAny(info.operations) | |
| return_type = self.SecureOutputType(info.type_name, False, | |
| False if dart_js_interop else True) | |
| formals = info.ParametersAsDeclaration(self._DartType) | |
| parameters = info.ParametersAsListOfVariables( | |
| None, self._type_registry if self._dart_use_blink else None, | |
| dart_js_interop, self) | |
| operation = info.operations[0] | |
| output_conversion = self._OutputConversion(operation.type.id, | |
| operation.id) | |
| dictionary_returned = False | |
| # Return type for dictionary is any (untyped). | |
| if operation.type.id == 'Dictionary': | |
| return_type = '' | |
| dictionary_returned = True | |
| dart_declaration = '%s%s %s(%s)' % ('static ' if info.IsStatic() else | |
| '', return_type, html_name, formals) | |
| is_custom = _IsCustom(operation) | |
| has_optional_arguments = any( | |
| IsOptional(argument) for argument in operation.arguments) | |
| needs_dispatcher = not is_custom and (len(info.operations) > 1 or | |
| has_optional_arguments) | |
| # Operation uses blink? | |
| wrap_unwrap_list = [] | |
| return_wrap_jso = False | |
| # return type wrapped? | |
| if self._dart_use_blink: | |
| # Wrap the type to store the JsObject if Type is: | |
| # | |
| # it's a dynamic/any type | |
| # - type is Object | |
| # | |
| # JsObject maybe stored in the Dart class. | |
| return_wrap_jso = wrap_return_type_blink( | |
| return_type, info.type_name, self._type_registry) | |
| return_type_info = self._type_registry.TypeInfo(info.type_name) | |
| # wrap_jso the returned object | |
| wrap_unwrap_list.append(return_wrap_jso) | |
| wrap_unwrap_list.append(self._dart_use_blink) | |
| if info.callback_args: | |
| self._AddFutureifiedOperation(info, html_name) | |
| elif not needs_dispatcher: | |
| # Bind directly to native implementation | |
| argument_count = (0 if info.IsStatic() else 1) + len( | |
| info.param_infos) | |
| native_suffix = 'Callback' | |
| auto_scope_setup = self._GenerateAutoSetupScope( | |
| info.name, native_suffix) | |
| native_entry = \ | |
| self.DeriveNativeEntry(operation.id, 'Method', len(info.param_infos)) | |
| cpp_callback_name = self._GenerateNativeBinding( | |
| info.name, | |
| argument_count, | |
| dart_declaration, | |
| info.IsStatic(), | |
| return_type, | |
| parameters, | |
| native_suffix, | |
| is_custom, | |
| auto_scope_setup, | |
| native_entry=native_entry, | |
| wrap_unwrap_list=wrap_unwrap_list, | |
| dictionary_return=dictionary_returned, | |
| output_conversion=output_conversion) | |
| if not is_custom: | |
| self._GenerateOperationNativeCallback( | |
| operation, operation.arguments, cpp_callback_name, | |
| auto_scope_setup) | |
| else: | |
| self._GenerateDispatcher(info, info.operations, dart_declaration, | |
| html_name) | |
| def _GenerateDispatcher(self, info, operations, dart_declaration, | |
| html_name): | |
| def GenerateCall(stmts_emitter, call_emitter, version, operation, | |
| argument_count): | |
| native_suffix = 'Callback' | |
| actuals = info.ParametersAsListOfVariables( | |
| argument_count, | |
| self._type_registry if self._dart_use_blink else None, | |
| self._dart_js_interop, self) | |
| actuals_s = ", ".join(actuals) | |
| formals = actuals | |
| return_type = self.SecureOutputType(operation.type.id) | |
| return_wrap_jso = False | |
| if self._dart_use_blink: | |
| return_wrap_jso = wrap_return_type_blink( | |
| return_type, info.type_name, self._type_registry) | |
| native_suffix = 'Callback' | |
| is_custom = _IsCustom(operation) | |
| base_name = '_%s_%s' % (operation.id, version) | |
| static = True | |
| if not operation.is_static: | |
| actuals = ['this'] + actuals | |
| formals = ['mthis'] + formals | |
| actuals_s = ", ".join(actuals) | |
| formals_s = ", ".join(formals) | |
| dart_declaration = '%s(%s)' % (base_name, formals_s) | |
| native_entry = \ | |
| self.DeriveNativeEntry(operation.id, 'Method', argument_count) | |
| overload_base_name = native_entry[0] | |
| overload_name = \ | |
| self.DeriveQualifiedBlinkName(self._interface.id, | |
| overload_base_name) | |
| call_emitter.Emit( | |
| '$NAME($ARGS)', NAME=overload_name, ARGS=actuals_s) | |
| auto_scope_setup = \ | |
| self._GenerateAutoSetupScope(base_name, native_suffix) | |
| cpp_callback_name = self._GenerateNativeBinding( | |
| base_name, (0 if static else 1) + argument_count, | |
| dart_declaration, | |
| static, | |
| return_type, | |
| formals, | |
| native_suffix, | |
| is_custom, | |
| auto_scope_setup, | |
| emit_metadata=False, | |
| emit_to_native=True, | |
| native_entry=native_entry) | |
| if not is_custom: | |
| self._GenerateOperationNativeCallback( | |
| operation, operation.arguments[:argument_count], | |
| cpp_callback_name, auto_scope_setup) | |
| self._GenerateDispatcherBody(info, operations, dart_declaration, | |
| GenerateCall, IsOptional) | |
| def SecondaryContext(self, interface): | |
| pass | |
| def _GenerateOperationNativeCallback(self, | |
| operation, | |
| arguments, | |
| cpp_callback_name, | |
| auto_scope_setup=True): | |
| webcore_function_name = operation.ext_attrs.get('ImplementedAs', | |
| operation.id) | |
| function_expression = self._GenerateWebCoreFunctionExpression( | |
| webcore_function_name, operation, cpp_callback_name) | |
| def _GenerateNativeBinding(self, | |
| idl_name, | |
| argument_count, | |
| dart_declaration, | |
| static, | |
| return_type, | |
| parameters, | |
| native_suffix, | |
| is_custom, | |
| auto_scope_setup=True, | |
| emit_metadata=True, | |
| emit_to_native=False, | |
| native_entry=None, | |
| wrap_unwrap_list=[], | |
| dictionary_return=False, | |
| output_conversion=None): | |
| metadata = [] | |
| if emit_metadata: | |
| metadata = self._metadata.GetFormattedMetadata( | |
| self._renamer.GetLibraryName(self._interface), self._interface, | |
| idl_name, ' ') | |
| if (native_entry): | |
| dart_native_name, native_binding = native_entry | |
| else: | |
| dart_native_name = \ | |
| self.DeriveNativeName(idl_name, native_suffix) | |
| native_binding_id = self._interface.id | |
| native_binding_id = TypeIdToBlinkName(native_binding_id, | |
| self._database) | |
| native_binding = \ | |
| '%s_%s_%s' % (native_binding_id, idl_name, native_suffix) | |
| if not static: | |
| formals = ", ".join(['mthis'] + parameters) | |
| actuals = ", ".join(['this'] + parameters) | |
| else: | |
| formals = ", ".join(parameters) | |
| actuals = ", ".join(parameters) | |
| if not emit_to_native: | |
| caller_emitter = self._members_emitter | |
| full_dart_name = \ | |
| self.DeriveQualifiedBlinkName(self._interface.id, | |
| dart_native_name) | |
| if IsPureInterface(self._interface.id, self._database): | |
| caller_emitter.Emit('\n' | |
| ' $METADATA$DART_DECLARATION;\n', | |
| METADATA=metadata, | |
| DART_DECLARATION=dart_declaration) | |
| else: | |
| emit_template = ''' | |
| $METADATA$DART_DECLARATION => $DART_NAME($ACTUALS); | |
| ''' | |
| if output_conversion and not dictionary_return: | |
| conversion_template = ''' | |
| $METADATA$DART_DECLARATION => %s($DART_NAME($ACTUALS)); | |
| ''' | |
| emit_template = conversion_template % output_conversion.function_name | |
| elif wrap_unwrap_list and wrap_unwrap_list[0]: | |
| if return_type == 'Rectangle': | |
| jso_util_method = 'make_dart_rectangle' | |
| elif wrap_unwrap_list[0]: | |
| jso_util_method = '' | |
| if dictionary_return: | |
| emit_jso_template = ''' | |
| $METADATA$DART_DECLARATION => convertNativeDictionaryToDartDictionary(%s($DART_NAME($ACTUALS))); | |
| ''' | |
| else: | |
| emit_jso_template = ''' | |
| $METADATA$DART_DECLARATION => %s($DART_NAME($ACTUALS)); | |
| ''' | |
| emit_template = emit_jso_template % jso_util_method | |
| if caller_emitter: | |
| caller_emitter.Emit( | |
| emit_template, | |
| METADATA=metadata, | |
| DART_DECLARATION=dart_declaration, | |
| DART_NAME=full_dart_name, | |
| ACTUALS=actuals) | |
| cpp_callback_name = '%s%s' % (idl_name, native_suffix) | |
| self._cpp_resolver_emitter.Emit( | |
| ' if (argumentCount == $ARGC && name == "$NATIVE_BINDING") {\n' | |
| ' *autoSetupScope = $AUTO_SCOPE_SETUP;\n' | |
| ' return Dart$(INTERFACE_NAME)Internal::$CPP_CALLBACK_NAME;\n' | |
| ' }\n', | |
| ARGC=argument_count, | |
| NATIVE_BINDING=native_binding, | |
| INTERFACE_NAME=self._interface.id, | |
| AUTO_SCOPE_SETUP='true' if auto_scope_setup else 'false', | |
| CPP_CALLBACK_NAME=cpp_callback_name) | |
| if is_custom: | |
| self._cpp_declarations_emitter.Emit( | |
| '\n' | |
| 'void $CPP_CALLBACK_NAME(Dart_NativeArguments);\n', | |
| CPP_CALLBACK_NAME=cpp_callback_name) | |
| return cpp_callback_name | |
| def _GenerateWebCoreReflectionAttributeName(self, attr): | |
| namespace = 'HTMLNames' | |
| svg_exceptions = [ | |
| 'class', 'id', 'onabort', 'onclick', 'onerror', 'onload', | |
| 'onmousedown', 'onmousemove', 'onmouseout', 'onmouseover', | |
| 'onmouseup', 'onresize', 'onscroll', 'onunload' | |
| ] | |
| if self._interface.id.startswith( | |
| 'SVG') and not attr.id in svg_exceptions: | |
| namespace = 'SVGNames' | |
| self._cpp_impl_includes.add('"%s.h"' % namespace) | |
| attribute_name = attr.ext_attrs['Reflect'] or attr.id.lower() | |
| return 'WebCore::%s::%sAttr' % (namespace, attribute_name) | |
| def _IsStatic(self, attribute_name): | |
| return False | |
| def _GenerateWebCoreFunctionExpression(self, | |
| function_name, | |
| idl_node, | |
| cpp_callback_name=None): | |
| return None | |
| def _IsArgumentOptionalInWebCore(self, operation, argument): | |
| if not IsOptional(argument): | |
| return False | |
| if 'Callback' in argument.ext_attrs: | |
| return False | |
| if operation.id in ['addEventListener', 'removeEventListener' | |
| ] and argument.id == 'useCapture': | |
| return False | |
| if 'DartForceOptional' in argument.ext_attrs: | |
| return False | |
| if argument.type.id == 'Dictionary': | |
| return False | |
| return True | |
| def _GenerateCPPIncludes(self, includes): | |
| return None | |
| def _ToWebKitName(self, name): | |
| name = name[0].lower() + name[1:] | |
| name = re.sub(r'^(hTML|uRL|jS|xML|xSLT)', lambda s: s.group(1).lower(), | |
| name) | |
| return re.sub(r'^(create|exclusive)', | |
| lambda s: 'is' + s.group(1).capitalize(), name) | |
| class CPPLibraryEmitter(): | |
| def __init__(self, emitters, cpp_sources_dir): | |
| self._emitters = emitters | |
| self._cpp_sources_dir = cpp_sources_dir | |
| self._library_headers = dict((lib, []) for lib in HTML_LIBRARY_NAMES) | |
| self._sources_list = [] | |
| def CreateHeaderEmitter(self, | |
| interface_name, | |
| library_name, | |
| is_callback=False): | |
| path = os.path.join(self._cpp_sources_dir, 'Dart%s.h' % interface_name) | |
| if not is_callback: | |
| self._library_headers[library_name].append(path) | |
| return self._emitters.FileEmitter(path) | |
| def CreateSourceEmitter(self, interface_name): | |
| path = os.path.join(self._cpp_sources_dir, | |
| 'Dart%s.cpp' % interface_name) | |
| self._sources_list.append(path) | |
| return self._emitters.FileEmitter(path) | |
| def EmitDerivedSources(self, template, output_dir): | |
| partitions = 20 # FIXME: this should be configurable. | |
| sources_count = len(self._sources_list) | |
| for i in range(0, partitions): | |
| file_path = os.path.join(output_dir, | |
| 'DartDerivedSources%02i.cpp' % (i + 1)) | |
| includes_emitter = self._emitters.FileEmitter(file_path).Emit( | |
| template) | |
| for source_file in self._sources_list[i::partitions]: | |
| path = os.path.relpath(source_file, output_dir) | |
| includes_emitter.Emit('#include "$PATH"\n', PATH=path) | |
| def EmitResolver(self, template, output_dir): | |
| for library_name in self._library_headers.keys(): | |
| file_path = os.path.join(output_dir, | |
| '%s_DartResolver.cpp' % library_name) | |
| includes_emitter, body_emitter = self._emitters.FileEmitter( | |
| file_path).Emit( | |
| template, LIBRARY_NAME=library_name) | |
| headers = self._library_headers[library_name] | |
| for header_file in headers: | |
| path = os.path.relpath(header_file, output_dir) | |
| includes_emitter.Emit('#include "$PATH"\n', PATH=path) | |
| body_emitter.Emit( | |
| ' if (Dart_NativeFunction func = $CLASS_NAME::resolver(name, argumentCount, autoSetupScope))\n' | |
| ' return func;\n', | |
| CLASS_NAME=os.path.splitext(os.path.basename(path))[0]) | |
| def EmitClassIdTable(self, database, output_dir, type_registry, renamer): | |
| def HasConverters(interface): | |
| is_node_test = lambda interface: interface.id == 'Node' | |
| is_active_test = lambda interface: 'ActiveDOMObject' in interface.ext_attrs | |
| is_event_target_test = lambda interface: 'EventTarget' in interface.ext_attrs | |
| return ( | |
| any(map(is_node_test, database.Hierarchy(interface))) or | |
| any(map(is_active_test, database.Hierarchy(interface))) or | |
| any(map(is_event_target_test, database.Hierarchy(interface)))) | |
| path = os.path.join(output_dir, 'DartWebkitClassIds.h') | |
| e = self._emitters.FileEmitter(path) | |
| e.Emit( | |
| '// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file\n' | |
| ) | |
| e.Emit( | |
| '// for details. All rights reserved. Use of this source code is governed by a\n' | |
| ) | |
| e.Emit('// BSD-style license that can be found in the LICENSE file.\n') | |
| e.Emit('// WARNING: Do not edit - generated code.\n') | |
| e.Emit('// See dart/tools/dom/scripts/systemnative.py\n') | |
| e.Emit('\n') | |
| e.Emit('#ifndef DartWebkitClassIds_h\n') | |
| e.Emit('#define DartWebkitClassIds_h\n') | |
| e.Emit('\n') | |
| e.Emit('namespace WebCore {\n') | |
| e.Emit('\n') | |
| e.Emit('enum {\n') | |
| e.Emit(' _InvalidClassId = 0,\n') | |
| e.Emit(' _HistoryCrossFrameClassId,\n') | |
| e.Emit(' _LocationCrossFrameClassId,\n') | |
| e.Emit(' _DOMWindowCrossFrameClassId,\n') | |
| e.Emit(' _DateTimeClassId,\n') | |
| e.Emit(' _JsObjectClassId,\n') | |
| e.Emit(' _JsFunctionClassId,\n') | |
| e.Emit(' _JsArrayClassId,\n') | |
| e.Emit( | |
| ' // New types that are not auto-generated should be added here.\n' | |
| ) | |
| e.Emit('\n') | |
| for interface in database.GetInterfaces(): | |
| e.Emit(' %sClassId,\n' % interface.id) | |
| e.Emit(' NumWebkitClassIds\n') | |
| e.Emit('};\n') | |
| e.Emit( | |
| 'class ActiveDOMObject;\n' | |
| 'class EventTarget;\n' | |
| 'class Node;\n' | |
| 'typedef ActiveDOMObject* (*ToActiveDOMObject)(void* value);\n' | |
| 'typedef EventTarget* (*ToEventTarget)(void* value);\n' | |
| 'typedef Node* (*ToNode)(void* value);\n' | |
| 'typedef struct {\n' | |
| ' const char* class_name;\n' | |
| ' int library_id;\n' | |
| ' int base_class_id;\n' | |
| ' ToActiveDOMObject toActiveDOMObject;\n' | |
| ' ToEventTarget toEventTarget;\n' | |
| ' ToNode toNode;\n' | |
| '} DartWrapperTypeInfo;\n' | |
| 'typedef DartWrapperTypeInfo _DartWebkitClassInfo[NumWebkitClassIds];\n' | |
| '\n' | |
| 'extern _DartWebkitClassInfo DartWebkitClassInfo;\n' | |
| '\n' | |
| '} // namespace WebCore\n' | |
| '#endif // DartWebkitClassIds_h\n') | |
| path = os.path.join(output_dir, 'DartWebkitClassIds.cpp') | |
| e = self._emitters.FileEmitter(path) | |
| e.Emit( | |
| '// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file\n' | |
| ) | |
| e.Emit( | |
| '// for details. All rights reserved. Use of this source code is governed by a\n' | |
| ) | |
| e.Emit('// BSD-style license that can be found in the LICENSE file.\n') | |
| e.Emit('// WARNING: Do not edit - generated code.\n') | |
| e.Emit('// See dart/tools/dom/scripts/systemnative.py\n') | |
| e.Emit('\n') | |
| e.Emit('#include "config.h"\n') | |
| e.Emit('#include "DartWebkitClassIds.h"\n') | |
| e.Emit('\n') | |
| e.Emit('#include "bindings/dart/DartLibraryIds.h"\n') | |
| for interface in database.GetInterfaces(): | |
| if HasConverters(interface): | |
| e.Emit('#include "Dart%s.h"\n' % interface.id) | |
| e.Emit('\n') | |
| e.Emit('namespace WebCore {\n') | |
| e.Emit('\n') | |
| e.Emit( | |
| 'ActiveDOMObject* toNullActiveDOMObject(void* value) { return 0; }\n' | |
| ) | |
| e.Emit('EventTarget* toNullEventTarget(void* value) { return 0; }\n') | |
| e.Emit('Node* toNullNode(void* value) { return 0; }\n') | |
| e.Emit("_DartWebkitClassInfo DartWebkitClassInfo = {\n") | |
| e.Emit(' {\n' | |
| ' "_InvalidClassId", -1, -1,\n' | |
| ' toNullActiveDOMObject, toNullEventTarget, toNullNode\n' | |
| ' },\n') | |
| e.Emit(' {\n' | |
| ' "_HistoryCrossFrame", DartHtmlLibraryId, -1,\n' | |
| ' toNullActiveDOMObject, toNullEventTarget, toNullNode\n' | |
| ' },\n') | |
| e.Emit(' {\n' | |
| ' "_LocationCrossFrame", DartHtmlLibraryId, -1,\n' | |
| ' toNullActiveDOMObject, toNullEventTarget, toNullNode\n' | |
| ' },\n') | |
| e.Emit(' {\n' | |
| ' "_DOMWindowCrossFrame", DartHtmlLibraryId, -1,\n' | |
| ' toNullActiveDOMObject, toNullEventTarget, toNullNode\n' | |
| ' },\n') | |
| e.Emit(' {\n' | |
| ' "DateTime", DartCoreLibraryId, -1,\n' | |
| ' toNullActiveDOMObject, toNullEventTarget, toNullNode\n' | |
| ' },\n') | |
| e.Emit(' {\n' | |
| ' "JsObject", DartJsLibraryId, -1,\n' | |
| ' toNullActiveDOMObject, toNullEventTarget, toNullNode\n' | |
| ' },\n') | |
| e.Emit(' {\n' | |
| ' "JsFunction", DartJsLibraryId, _JsObjectClassId,\n' | |
| ' toNullActiveDOMObject, toNullEventTarget, toNullNode\n' | |
| ' },\n') | |
| e.Emit(' {\n' | |
| ' "JsArray", DartJsLibraryId, _JsObjectClassId,\n' | |
| ' toNullActiveDOMObject, toNullEventTarget, toNullNode\n' | |
| ' },\n') | |
| e.Emit( | |
| ' // New types that are not auto-generated should be added here.\n' | |
| ) | |
| for interface in database.GetInterfaces(): | |
| name = interface.id | |
| type_info = type_registry.TypeInfo(name) | |
| type_info.native_type().replace('<', '_').replace('>', '_') | |
| e.Emit(' {\n') | |
| e.Emit(' "%s", ' % type_info.implementation_name()) | |
| e.Emit('Dart%sLibraryId, ' % renamer.GetLibraryId(interface)) | |
| if interface.parents: | |
| supertype = interface.parents[0].type.id | |
| e.Emit('%sClassId,\n' % supertype) | |
| else: | |
| e.Emit(' -1,\n') | |
| if HasConverters(interface): | |
| e.Emit( | |
| ' Dart%s::toActiveDOMObject, Dart%s::toEventTarget,' | |
| ' Dart%s::toNode\n' % (name, name, name)) | |
| else: | |
| e.Emit( | |
| ' toNullActiveDOMObject, toNullEventTarget, toNullNode\n' | |
| ) | |
| e.Emit(' },\n') | |
| e.Emit("};\n") | |
| e.Emit('\n') | |
| e.Emit('} // namespace WebCore\n') | |
| def _IsOptionalStringArgumentInInitEventMethod(interface, operation, argument): | |
| return (interface.id.endswith('Event') and | |
| operation.id.startswith('init') and | |
| argument.default_value == 'Undefined' and | |
| argument.type.id == 'DOMString') | |
| def _IsCustom(op_or_attr): | |
| assert (isinstance(op_or_attr, IDLMember)) | |
| return 'Custom' in op_or_attr.ext_attrs or 'DartCustom' in op_or_attr.ext_attrs | |
| def _IsCustomValue(op_or_attr, value): | |
| if _IsCustom(op_or_attr): | |
| return op_or_attr.ext_attrs.get('Custom') == value \ | |
| or op_or_attr.ext_attrs.get('DartCustom') == value | |
| return False |