| #!/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 RangeError.index(index, 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 RangeError.index(index, 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 |