Index: client/dom/scripts/systemnative.py |
=================================================================== |
--- client/dom/scripts/systemnative.py (revision 5796) |
+++ client/dom/scripts/systemnative.py (working copy) |
@@ -1,840 +0,0 @@ |
-#!/usr/bin/python |
-# 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 os |
-import systemwrapping |
-from generator import * |
-from systembase import * |
- |
-class NativeImplementationSystem(System): |
- |
- def __init__(self, templates, database, emitters, auxiliary_dir, output_dir): |
- super(NativeImplementationSystem, self).__init__( |
- templates, database, emitters, output_dir) |
- |
- self._auxiliary_dir = auxiliary_dir |
- self._dom_public_files = [] |
- self._dom_impl_files = [] |
- self._cpp_header_files = [] |
- self._cpp_impl_files = [] |
- |
- def InterfaceGenerator(self, |
- interface, |
- common_prefix, |
- super_interface_name, |
- source_filter): |
- interface_name = interface.id |
- |
- dart_interface_path = self._FilePathForDartInterface(interface_name) |
- self._dom_public_files.append(dart_interface_path) |
- |
- if IsPureInterface(interface_name): |
- return None |
- |
- dart_impl_path = self._FilePathForDartImplementation(interface_name) |
- self._dom_impl_files.append(dart_impl_path) |
- |
- cpp_header_path = self._FilePathForCppHeader(interface_name) |
- self._cpp_header_files.append(cpp_header_path) |
- |
- cpp_impl_path = self._FilePathForCppImplementation(interface_name) |
- self._cpp_impl_files.append(cpp_impl_path) |
- |
- return NativeImplementationGenerator(self, interface, super_interface_name, |
- self._emitters.FileEmitter(dart_impl_path), |
- self._emitters.FileEmitter(cpp_header_path), |
- self._emitters.FileEmitter(cpp_impl_path), |
- self._BaseDefines(interface), |
- self._templates) |
- |
- def ProcessCallback(self, interface, info): |
- self._interface = interface |
- |
- dart_interface_path = self._FilePathForDartInterface(self._interface.id) |
- self._dom_public_files.append(dart_interface_path) |
- |
- cpp_impl_includes = set() |
- cpp_header_handlers_emitter = emitter.Emitter() |
- cpp_impl_handlers_emitter = emitter.Emitter() |
- class_name = 'Dart%s' % self._interface.id |
- for operation in interface.operations: |
- if operation.type.id == 'void': |
- return_type = 'void' |
- return_prefix = '' |
- else: |
- return_type = 'bool' |
- return_prefix = 'return ' |
- |
- parameters = [] |
- arguments = [] |
- for argument in operation.arguments: |
- argument_type_info = GetIDLTypeInfo(argument.type.id) |
- parameters.append('%s %s' % (argument_type_info.parameter_type(), |
- argument.id)) |
- arguments.append(argument.id) |
- cpp_impl_includes |= set(argument_type_info.conversion_includes()) |
- |
- cpp_header_handlers_emitter.Emit( |
- '\n' |
- ' virtual $TYPE handleEvent($PARAMETERS);\n', |
- TYPE=return_type, PARAMETERS=', '.join(parameters)) |
- |
- cpp_impl_handlers_emitter.Emit( |
- '\n' |
- '$TYPE $CLASS_NAME::handleEvent($PARAMETERS)\n' |
- '{\n' |
- ' $(RETURN_PREFIX)m_callback.handleEvent($ARGUMENTS);\n' |
- '}\n', |
- TYPE=return_type, |
- CLASS_NAME=class_name, |
- PARAMETERS=', '.join(parameters), |
- RETURN_PREFIX=return_prefix, |
- ARGUMENTS=', '.join(arguments)) |
- |
- cpp_header_path = self._FilePathForCppHeader(self._interface.id) |
- cpp_header_emitter = self._emitters.FileEmitter(cpp_header_path) |
- cpp_header_emitter.Emit( |
- self._templates.Load('cpp_callback_header.template'), |
- INTERFACE=self._interface.id, |
- HANDLERS=cpp_header_handlers_emitter.Fragments()) |
- |
- cpp_impl_path = self._FilePathForCppImplementation(self._interface.id) |
- self._cpp_impl_files.append(cpp_impl_path) |
- cpp_impl_emitter = self._emitters.FileEmitter(cpp_impl_path) |
- cpp_impl_emitter.Emit( |
- self._templates.Load('cpp_callback_implementation.template'), |
- INCLUDES=_GenerateCPPIncludes(cpp_impl_includes), |
- INTERFACE=self._interface.id, |
- HANDLERS=cpp_impl_handlers_emitter.Fragments()) |
- |
- def GenerateLibraries(self, lib_dir): |
- auxiliary_dir = os.path.relpath(self._auxiliary_dir, self._output_dir) |
- |
- # Generate dom_public.dart. |
- self._GenerateLibFile( |
- 'dom_public.darttemplate', |
- os.path.join(self._output_dir, 'dom_public.dart'), |
- self._dom_public_files, |
- AUXILIARY_DIR=MassagePath(auxiliary_dir)); |
- |
- # Generate dom_impl.dart. |
- self._GenerateLibFile( |
- 'dom_impl.darttemplate', |
- os.path.join(self._output_dir, 'dom_impl.dart'), |
- self._dom_impl_files, |
- AUXILIARY_DIR=MassagePath(auxiliary_dir)); |
- |
- # Generate DartDerivedSourcesXX.cpp. |
- partitions = 20 # FIXME: this should be configurable. |
- sources_count = len(self._cpp_impl_files) |
- for i in range(0, partitions): |
- derived_sources_path = os.path.join(self._output_dir, |
- 'DartDerivedSources%02i.cpp' % (i + 1)) |
- |
- includes_emitter = emitter.Emitter() |
- for impl_file in self._cpp_impl_files[i::partitions]: |
- path = os.path.relpath(impl_file, os.path.dirname(derived_sources_path)) |
- includes_emitter.Emit('#include "$PATH"\n', PATH=path) |
- |
- derived_sources_emitter = self._emitters.FileEmitter(derived_sources_path) |
- derived_sources_emitter.Emit( |
- self._templates.Load('cpp_derived_sources.template'), |
- INCLUDES=includes_emitter.Fragments()) |
- |
- # Generate DartResolver.cpp. |
- cpp_resolver_path = os.path.join(self._output_dir, 'DartResolver.cpp') |
- |
- includes_emitter = emitter.Emitter() |
- resolver_body_emitter = emitter.Emitter() |
- for file in self._cpp_header_files: |
- path = os.path.relpath(file, os.path.dirname(cpp_resolver_path)) |
- includes_emitter.Emit('#include "$PATH"\n', PATH=path) |
- resolver_body_emitter.Emit( |
- ' if (Dart_NativeFunction func = $CLASS_NAME::resolver(name, argumentCount))\n' |
- ' return func;\n', |
- CLASS_NAME=os.path.splitext(os.path.basename(path))[0]) |
- |
- cpp_resolver_emitter = self._emitters.FileEmitter(cpp_resolver_path) |
- cpp_resolver_emitter.Emit( |
- self._templates.Load('cpp_resolver.template'), |
- INCLUDES=includes_emitter.Fragments(), |
- RESOLVER_BODY=resolver_body_emitter.Fragments()) |
- |
- def Finish(self): |
- pass |
- |
- def _FilePathForDartInterface(self, interface_name): |
- return os.path.join(self._output_dir, 'src', 'interface', |
- '%s.dart' % interface_name) |
- |
- def _FilePathForDartImplementation(self, interface_name): |
- return os.path.join(self._output_dir, 'dart', |
- '%sImplementation.dart' % interface_name) |
- |
- def _FilePathForDartFactoryProvider(self, interface_name): |
- return os.path.join(self._output_dir, 'dart', |
- '_%sFactoryProvider.dart' % interface_name) |
- |
- def _FilePathForDartFactoryProviderImplementation(self, interface_name): |
- return os.path.join(self._output_dir, 'dart', |
- '%sFactoryProviderImplementation.dart' % interface_name) |
- |
- def _FilePathForCppHeader(self, interface_name): |
- return os.path.join(self._output_dir, 'cpp', 'Dart%s.h' % interface_name) |
- |
- def _FilePathForCppImplementation(self, interface_name): |
- return os.path.join(self._output_dir, 'cpp', 'Dart%s.cpp' % interface_name) |
- |
- |
-class NativeImplementationGenerator(systemwrapping.WrappingInterfaceGenerator): |
- """Generates Dart implementation for one DOM IDL interface.""" |
- |
- def __init__(self, system, interface, super_interface, |
- dart_impl_emitter, cpp_header_emitter, cpp_impl_emitter, |
- base_members, templates): |
- """Generates Dart and C++ code for the given interface. |
- |
- Args: |
- system: The NativeImplementationSystem. |
- interface: an IDLInterface instance. It is assumed that all types have |
- been converted to Dart types (e.g. int, String), unless they are in |
- the same package as the interface. |
- super_interface: A string or None, the name of the common interface that |
- this interface implements, if any. |
- dart_impl_emitter: an Emitter for the file containing the Dart |
- implementation class. |
- cpp_header_emitter: an Emitter for the file containing the C++ header. |
- cpp_impl_emitter: an Emitter for the file containing the C++ |
- implementation. |
- base_members: a set of names of members defined in a base class. This is |
- used to avoid static member 'overriding' in the generated Dart code. |
- """ |
- self._system = system |
- self._interface = interface |
- self._super_interface = super_interface |
- self._dart_impl_emitter = dart_impl_emitter |
- self._cpp_header_emitter = cpp_header_emitter |
- self._cpp_impl_emitter = cpp_impl_emitter |
- self._base_members = base_members |
- self._templates = templates |
- self._current_secondary_parent = None |
- |
- def StartInterface(self): |
- self._class_name = self._ImplClassName(self._interface.id) |
- self._interface_type_info = GetIDLTypeInfo(self._interface.id) |
- self._members_emitter = emitter.Emitter() |
- self._cpp_declarations_emitter = emitter.Emitter() |
- self._cpp_impl_includes = set() |
- self._cpp_definitions_emitter = emitter.Emitter() |
- self._cpp_resolver_emitter = emitter.Emitter() |
- |
- self._GenerateConstructors() |
- |
- def _GenerateConstructors(self): |
- if not self._IsConstructable(): |
- return |
- |
- # TODO(antonm): currently we don't have information about number of arguments expected by |
- # the constructor, so name only dispatch. |
- self._cpp_resolver_emitter.Emit( |
- ' if (name == "$(INTERFACE_NAME)_constructor_Callback")\n' |
- ' return Dart$(INTERFACE_NAME)Internal::constructorCallback;\n', |
- INTERFACE_NAME=self._interface.id) |
- |
- |
- constructor_info = AnalyzeConstructor(self._interface) |
- if constructor_info: |
- self._EmitFactoryProvider(self._interface.id, constructor_info) |
- |
- if constructor_info is None: |
- # We have a custom implementation for it. |
- self._cpp_declarations_emitter.Emit( |
- '\n' |
- 'void constructorCallback(Dart_NativeArguments);\n') |
- return |
- |
- raises_dom_exceptions = 'ConstructorRaisesException' in self._interface.ext_attrs |
- raises_exceptions = raises_dom_exceptions or len(constructor_info.idl_args) > 0 |
- arguments = [] |
- parameter_definitions_emitter = emitter.Emitter() |
- create_function = 'create' |
- if 'NamedConstructor' in self._interface.ext_attrs: |
- raises_exceptions = True |
- parameter_definitions_emitter.Emit( |
- ' DOMWindow* domWindow = DartUtilities::domWindowForCurrentIsolate();\n' |
- ' if (!domWindow) {\n' |
- ' exception = Dart_NewString("Failed to fetch domWindow");\n' |
- ' goto fail;\n' |
- ' }\n' |
- ' Document* document = domWindow->document();\n') |
- self._cpp_impl_includes.add('"DOMWindow.h"') |
- arguments.append('document') |
- create_function = 'createForJSConstructor' |
- if 'CallWith' in self._interface.ext_attrs: |
- call_with = self._interface.ext_attrs['CallWith'] |
- if call_with == 'ScriptExecutionContext': |
- raises_exceptions = True |
- parameter_definitions_emitter.Emit( |
- ' ScriptExecutionContext* context = DartUtilities::scriptExecutionContext();\n' |
- ' if (!context) {\n' |
- ' exception = Dart_NewString("Failed to create an object");\n' |
- ' goto fail;\n' |
- ' }\n') |
- arguments.append('context') |
- else: |
- raise Exception('Unsupported CallWith=%s attribute' % call_with) |
- |
- # Process constructor arguments. |
- for (i, arg) in enumerate(constructor_info.idl_args): |
- self._GenerateParameterAdapter(parameter_definitions_emitter, arg, i - 1) |
- arguments.append(arg.id) |
- |
- function_expression = '%s::%s' % (self._interface_type_info.native_type(), create_function) |
- invocation = self._GenerateWebCoreInvocation(function_expression, arguments, |
- self._interface.id, self._interface.ext_attrs, raises_dom_exceptions) |
- self._GenerateNativeCallback(callback_name='constructorCallback', |
- parameter_definitions=parameter_definitions_emitter.Fragments(), |
- needs_receiver=False, invocation=invocation, |
- raises_exceptions=raises_exceptions) |
- |
- def _ImplClassName(self, interface_name): |
- return interface_name + 'Implementation' |
- |
- def _IsConstructable(self): |
- # FIXME: support ConstructorTemplate. |
- return set(['CustomConstructor', 'V8CustomConstructor', 'Constructor', 'NamedConstructor']) & set(self._interface.ext_attrs) |
- |
- def _EmitFactoryProvider(self, interface_name, constructor_info): |
- factory_provider = '_' + interface_name + 'FactoryProvider' |
- implementation_class = interface_name + 'FactoryProviderImplementation' |
- implementation_function = 'create' + interface_name |
- native_implementation_function = '%s_constructor_Callback' % interface_name |
- |
- # Emit private factory provider in public library. |
- template_file = 'factoryprovider_%s.darttemplate' % interface_name |
- template = self._system._templates.TryLoad(template_file) |
- if not template: |
- template = self._system._templates.Load('factoryprovider.darttemplate') |
- |
- dart_impl_path = self._system._FilePathForDartFactoryProvider( |
- interface_name) |
- self._system._dom_public_files.append(dart_impl_path) |
- |
- emitter = self._system._emitters.FileEmitter(dart_impl_path) |
- emitter.Emit( |
- template, |
- FACTORY_PROVIDER=factory_provider, |
- CONSTRUCTOR=interface_name, |
- PARAMETERS=constructor_info.ParametersImplementationDeclaration(), |
- IMPL_CLASS=implementation_class, |
- IMPL_FUNCTION=implementation_function, |
- ARGUMENTS=constructor_info.ParametersAsArgumentList()) |
- |
- # Emit public implementation in implementation libary. |
- dart_impl_path = self._system._FilePathForDartFactoryProviderImplementation( |
- interface_name) |
- self._system._dom_impl_files.append(dart_impl_path) |
- emitter = self._system._emitters.FileEmitter(dart_impl_path) |
- emitter.Emit( |
- 'class $IMPL_CLASS {\n' |
- ' static $INTERFACE_NAME $IMPL_FUNCTION($PARAMETERS)\n' |
- ' native "$NATIVE_NAME";\n' |
- '}', |
- INTERFACE_NAME=interface_name, |
- PARAMETERS=constructor_info.ParametersImplementationDeclaration(), |
- IMPL_CLASS=implementation_class, |
- IMPL_FUNCTION=implementation_function, |
- NATIVE_NAME=native_implementation_function) |
- |
- def FinishInterface(self): |
- base = self._BaseClassName(self._interface) |
- self._dart_impl_emitter.Emit( |
- self._templates.Load('dart_implementation.darttemplate'), |
- CLASS=self._class_name, BASE=base, INTERFACE=self._interface.id, |
- MEMBERS=self._members_emitter.Fragments()) |
- |
- self._GenerateCppHeader() |
- |
- self._cpp_impl_emitter.Emit( |
- self._templates.Load('cpp_implementation.template'), |
- INTERFACE=self._interface.id, |
- INCLUDES=_GenerateCPPIncludes(self._cpp_impl_includes), |
- CALLBACKS=self._cpp_definitions_emitter.Fragments(), |
- RESOLVER=self._cpp_resolver_emitter.Fragments()) |
- |
- def _GenerateCppHeader(self): |
- webcore_includes = _GenerateCPPIncludes(self._interface_type_info.webcore_includes()) |
- |
- if ('CustomToJS' in self._interface.ext_attrs or |
- 'CustomToJSObject' in self._interface.ext_attrs or |
- 'PureInterface' in self._interface.ext_attrs or |
- 'CPPPureInterface' in self._interface.ext_attrs or |
- self._interface_type_info.custom_to_dart()): |
- to_dart_value_template = ( |
- 'Dart_Handle toDartValue($(WEBCORE_CLASS_NAME)* value);\n') |
- else: |
- to_dart_value_template = ( |
- 'inline Dart_Handle toDartValue($(WEBCORE_CLASS_NAME)* value)\n' |
- '{\n' |
- ' return DartDOMWrapper::toDart<Dart$(INTERFACE)>(value);\n' |
- '}\n') |
- to_dart_value_emitter = emitter.Emitter() |
- to_dart_value_emitter.Emit( |
- to_dart_value_template, |
- INTERFACE=self._interface.id, |
- WEBCORE_CLASS_NAME=self._interface_type_info.native_type()) |
- |
- self._cpp_header_emitter.Emit( |
- self._templates.Load('cpp_header.template'), |
- INTERFACE=self._interface.id, |
- WEBCORE_INCLUDES=webcore_includes, |
- WEBCORE_CLASS_NAME=self._interface_type_info.native_type(), |
- TO_DART_VALUE=to_dart_value_emitter.Fragments(), |
- DECLARATIONS=self._cpp_declarations_emitter.Fragments()) |
- |
- def _GenerateCallWithHandling(self, node, parameter_definitions_emitter, arguments): |
- if 'CallWith' not in node.ext_attrs: |
- return False |
- |
- call_with = node.ext_attrs['CallWith'] |
- if call_with == 'ScriptExecutionContext': |
- parameter_definitions_emitter.Emit( |
- '\n' |
- ' ScriptExecutionContext* context = DartUtilities::scriptExecutionContext();\n' |
- ' if (!context)\n' |
- ' return;\n') |
- arguments.append('context') |
- return False |
- |
- if call_with == 'ScriptArguments|CallStack': |
- self._cpp_impl_includes.add('"DOMWindow.h"') |
- self._cpp_impl_includes.add('"ScriptArguments.h"') |
- self._cpp_impl_includes.add('"ScriptCallStack.h"') |
- self._cpp_impl_includes.add('"V8Proxy.h"') |
- self._cpp_impl_includes.add('"v8.h"') |
- parameter_definitions_emitter.Emit( |
- '\n' |
- ' v8::HandleScope handleScope;\n' |
- ' v8::Context::Scope scope(V8Proxy::mainWorldContext(DartUtilities::domWindowForCurrentIsolate()->frame()));\n' |
- ' Dart_Handle customArgument = Dart_GetNativeArgument(args, $INDEX);\n' |
- ' RefPtr<ScriptArguments> scriptArguments(DartUtilities::createScriptArguments(customArgument, exception));\n' |
- ' if (!scriptArguments)\n' |
- ' goto fail;\n' |
- ' RefPtr<ScriptCallStack> scriptCallStack(DartUtilities::createScriptCallStack());\n' |
- ' if (!scriptCallStack->size())\n' |
- ' return;\n', |
- INDEX=len(node.arguments)) |
- arguments.extend(['scriptArguments', 'scriptCallStack']) |
- return True |
- |
- return False |
- |
- def AddAttribute(self, getter, setter): |
- # FIXME: Dartium does not support attribute event listeners. However, JS |
- # implementation falls back to them when addEventListener is not available. |
- # Make sure addEventListener is available in all EventTargets and remove |
- # this check. |
- if (getter or setter).type.id == 'EventListener': |
- return |
- |
- if 'CheckSecurityForNode' in (getter or setter).ext_attrs: |
- # FIXME: exclude from interface as well. |
- return |
- |
- # FIXME: these should go away. |
- classes_with_unsupported_custom_getters = [ |
- 'Clipboard', 'Console', 'Coordinates', 'DeviceMotionEvent', |
- 'DeviceOrientationEvent', 'FileReader', 'JavaScriptCallFrame', |
- 'HTMLInputElement', 'HTMLOptionsCollection', 'HTMLOutputElement', |
- 'ScriptProfileNode', 'WebKitAnimation'] |
- if (self._interface.id in classes_with_unsupported_custom_getters and |
- getter and set(['Custom', 'CustomGetter']) & set(getter.ext_attrs)): |
- return |
- |
- if getter: |
- self._AddGetter(getter) |
- if setter: |
- self._AddSetter(setter) |
- |
- def _AddGetter(self, attr): |
- type_info = GetIDLTypeInfo(attr.type.id) |
- dart_declaration = '%s get %s()' % ( |
- type_info.dart_type(), DartDomNameOfAttribute(attr)) |
- is_custom = 'Custom' in attr.ext_attrs or 'CustomGetter' in attr.ext_attrs |
- cpp_callback_name = self._GenerateNativeBinding(attr.id, 1, |
- dart_declaration, 'Getter', is_custom) |
- if is_custom: |
- return |
- |
- arguments = [] |
- parameter_definitions_emitter = emitter.Emitter() |
- raises_exceptions = self._GenerateCallWithHandling(attr, parameter_definitions_emitter, arguments) |
- raises_exceptions = raises_exceptions or attr.get_raises |
- |
- if 'Reflect' in attr.ext_attrs: |
- webcore_function_name = GetIDLTypeInfo(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' |
- arguments.append(self._GenerateWebCoreReflectionAttributeName(attr)) |
- else: |
- if attr.id == 'operator': |
- webcore_function_name = '_operator' |
- elif attr.id == 'target' and attr.type.id == 'SVGAnimatedString': |
- webcore_function_name = 'svgTarget' |
- else: |
- webcore_function_name = re.sub(r'^(HTML|URL|JS|XML|XSLT|\w)', |
- lambda s: s.group(1).lower(), |
- attr.id) |
- webcore_function_name = re.sub(r'^(create|exclusive)', |
- lambda s: 'is' + s.group(1).capitalize(), |
- webcore_function_name) |
- if attr.type.id.startswith('SVGAnimated'): |
- webcore_function_name += 'Animated' |
- |
- function_expression = self._GenerateWebCoreFunctionExpression(webcore_function_name, attr) |
- invocation = self._GenerateWebCoreInvocation(function_expression, |
- arguments, attr.type.id, attr.ext_attrs, attr.get_raises) |
- self._GenerateNativeCallback(cpp_callback_name, parameter_definitions_emitter.Fragments(), |
- True, invocation, raises_exceptions=raises_exceptions) |
- |
- def _AddSetter(self, attr): |
- type_info = GetIDLTypeInfo(attr.type.id) |
- dart_declaration = 'void set %s(%s)' % ( |
- DartDomNameOfAttribute(attr), type_info.dart_type()) |
- is_custom = set(['Custom', 'CustomSetter', 'V8CustomSetter']) & set(attr.ext_attrs) |
- cpp_callback_name = self._GenerateNativeBinding(attr.id, 2, |
- dart_declaration, 'Setter', is_custom) |
- if is_custom: |
- return |
- |
- arguments = [] |
- parameter_definitions_emitter = emitter.Emitter() |
- self._GenerateCallWithHandling(attr, parameter_definitions_emitter, arguments) |
- |
- if 'Reflect' in attr.ext_attrs: |
- webcore_function_name = GetIDLTypeInfo(attr.type.id).webcore_setter_name() |
- arguments.append(self._GenerateWebCoreReflectionAttributeName(attr)) |
- else: |
- webcore_function_name = re.sub(r'^(xml(?=[A-Z])|\w)', |
- lambda s: s.group(1).upper(), |
- attr.id) |
- webcore_function_name = 'set%s' % webcore_function_name |
- if attr.type.id.startswith('SVGAnimated'): |
- webcore_function_name += 'Animated' |
- |
- arguments.append('value') |
- |
- self._GenerateParameterAdapter( |
- parameter_definitions_emitter, attr, 0, adapter_name='value') |
- parameter_definitions = parameter_definitions_emitter.Fragments() |
- |
- function_expression = self._GenerateWebCoreFunctionExpression(webcore_function_name, attr) |
- invocation = self._GenerateWebCoreInvocation(function_expression, |
- arguments, 'void', attr.ext_attrs, attr.set_raises) |
- |
- self._GenerateNativeCallback(cpp_callback_name, parameter_definitions_emitter.Fragments(), |
- True, invocation, raises_exceptions=True) |
- |
- def _HasNativeIndexGetter(self, interface): |
- return ('CustomIndexedGetter' in interface.ext_attrs or |
- 'NumericIndexedGetter' in interface.ext_attrs) |
- |
- def _EmitNativeIndexGetter(self, interface, element_type): |
- dart_declaration = '%s operator[](int index)' % element_type |
- self._GenerateNativeBinding('numericIndexGetter', 2, dart_declaration, |
- 'Callback', True) |
- |
- def _EmitNativeIndexSetter(self, interface, element_type): |
- dart_declaration = 'void operator[]=(int index, %s value)' % element_type |
- self._GenerateNativeBinding('numericIndexSetter', 3, dart_declaration, |
- 'Callback', True) |
- |
- def AddOperation(self, info): |
- """ |
- Arguments: |
- info: An OperationInfo object. |
- """ |
- |
- if 'CheckSecurityForNode' in info.overloads[0].ext_attrs: |
- # FIXME: exclude from interface as well. |
- return |
- |
- if 'Custom' in info.overloads[0].ext_attrs: |
- parameters = info.ParametersImplementationDeclaration() |
- dart_declaration = '%s %s(%s)' % (info.type_name, info.name, parameters) |
- argument_count = 1 + len(info.arg_infos) |
- self._GenerateNativeBinding(info.name, argument_count, dart_declaration, |
- 'Callback', True) |
- return |
- |
- body = self._members_emitter.Emit( |
- '\n' |
- ' $TYPE $NAME($PARAMETERS) {\n' |
- '$!BODY' |
- ' }\n', |
- TYPE=info.type_name, |
- NAME=info.name, |
- PARAMETERS=info.ParametersImplementationDeclaration()) |
- |
- # Process in order of ascending number of arguments to ensure missing |
- # optional arguments are processed early. |
- overloads = sorted(info.overloads, |
- key=lambda overload: len(overload.arguments)) |
- self._native_version = 0 |
- fallthrough = self.GenerateDispatch(body, info, ' ', 0, overloads) |
- if fallthrough: |
- body.Emit(' throw "Incorrect number or type of arguments";\n'); |
- |
- def GenerateSingleOperation(self, dispatch_emitter, info, indent, operation): |
- """Generates a call to a single operation. |
- |
- Arguments: |
- dispatch_emitter: an dispatch_emitter for the body of a block of code. |
- info: the compound information about the operation and its overloads. |
- indent: an indentation string for generated code. |
- operation: the IDLOperation to call. |
- """ |
- |
- self._native_version += 1 |
- native_name = info.name |
- if self._native_version > 1: |
- native_name = '%s_%s' % (native_name, self._native_version) |
- argument_list = ', '.join([info.arg_infos[i][0] |
- for (i, arg) in enumerate(operation.arguments)]) |
- |
- # Generate dispatcher. |
- if info.type_name != 'void': |
- dispatch_emitter.Emit('$(INDENT)return _$NATIVENAME($ARGS);\n', |
- INDENT=indent, |
- NATIVENAME=native_name, |
- ARGS=argument_list) |
- else: |
- dispatch_emitter.Emit('$(INDENT)_$NATIVENAME($ARGS);\n' |
- '$(INDENT)return;\n', |
- INDENT=indent, |
- NATIVENAME=native_name, |
- ARGS=argument_list) |
- # Generate binding. |
- dart_declaration = '%s _%s(%s)' % (info.type_name, native_name, |
- argument_list) |
- is_custom = 'Custom' in operation.ext_attrs |
- cpp_callback_name = self._GenerateNativeBinding( |
- native_name, 1 + len(operation.arguments), dart_declaration, 'Callback', |
- is_custom) |
- if is_custom: |
- return |
- |
- # Generate callback. |
- webcore_function_name = operation.ext_attrs.get('ImplementedAs', operation.id) |
- |
- parameter_definitions_emitter = emitter.Emitter() |
- arguments = [] |
- raises_exceptions = self._GenerateCallWithHandling( |
- operation, parameter_definitions_emitter, arguments) |
- raises_exceptions = raises_exceptions or len(operation.arguments) > 0 or operation.raises |
- |
- # Process Dart arguments. |
- for (i, argument) in enumerate(operation.arguments): |
- if (i == len(operation.arguments) - 1 and |
- self._interface.id == 'Console' and |
- argument.id == 'arg'): |
- # FIXME: we are skipping last argument here because it was added in |
- # supplemental dart.idl. Cleanup dart.idl and remove this check. |
- break |
- self._GenerateParameterAdapter(parameter_definitions_emitter, argument, i) |
- arguments.append(argument.id) |
- |
- if operation.id in ['addEventListener', 'removeEventListener']: |
- # addEventListener's and removeEventListener's last argument is marked |
- # as optional in idl, but is not optional in webcore implementation. |
- if len(operation.arguments) == 2: |
- arguments.append('false') |
- |
- if self._interface.id == 'CSSStyleDeclaration' and operation.id == 'setProperty': |
- # CSSStyleDeclaration.setProperty priority parameter is optional in Dart |
- # idl, but is not optional in webcore implementation. |
- if len(operation.arguments) == 2: |
- arguments.append('String()') |
- |
- if 'NeedsUserGestureCheck' in operation.ext_attrs: |
- arguments.append('DartUtilities::processingUserGesture') |
- |
- function_expression = self._GenerateWebCoreFunctionExpression(webcore_function_name, operation) |
- invocation = self._GenerateWebCoreInvocation(function_expression, arguments, |
- operation.type.id, operation.ext_attrs, operation.raises) |
- self._GenerateNativeCallback(cpp_callback_name, |
- parameter_definitions=parameter_definitions_emitter.Fragments(), |
- needs_receiver=True, invocation=invocation, |
- raises_exceptions=raises_exceptions) |
- |
- def _GenerateNativeCallback(self, callback_name, parameter_definitions, |
- needs_receiver, invocation, raises_exceptions): |
- |
- if needs_receiver: |
- parameter_definitions = emitter.Format( |
- ' $WEBCORE_CLASS_NAME* receiver = DartDOMWrapper::receiver< $WEBCORE_CLASS_NAME >(args);\n' |
- ' $PARAMETER_DEFINITIONS\n', |
- WEBCORE_CLASS_NAME=self._interface_type_info.native_type(), |
- PARAMETER_DEFINITIONS=parameter_definitions) |
- |
- body = emitter.Format( |
- ' {\n' |
- '$PARAMETER_DEFINITIONS' |
- '$INVOCATION' |
- ' return;\n' |
- ' }\n', |
- PARAMETER_DEFINITIONS=parameter_definitions, |
- INVOCATION=invocation) |
- |
- if raises_exceptions: |
- body = emitter.Format( |
- ' Dart_Handle exception;\n' |
- '$BODY' |
- '\n' |
- 'fail:\n' |
- ' Dart_ThrowException(exception);\n' |
- ' ASSERT_NOT_REACHED();\n', |
- BODY=body) |
- |
- self._cpp_definitions_emitter.Emit( |
- '\n' |
- 'static void $CALLBACK_NAME(Dart_NativeArguments args)\n' |
- '{\n' |
- ' DartApiScope dartApiScope;\n' |
- '$BODY' |
- '}\n', |
- CALLBACK_NAME=callback_name, |
- BODY=body) |
- |
- def _GenerateParameterAdapter(self, emitter, idl_node, index, |
- adapter_name=None): |
- """idl_node is IDLArgument or IDLAttribute.""" |
- type_info = GetIDLTypeInfo(idl_node.type.id) |
- (adapter_type, include_name) = type_info.parameter_adapter_info() |
- if include_name: |
- self._cpp_impl_includes.add(include_name) |
- flags = '' |
- if (idl_node.ext_attrs.get('Optional') == 'DefaultIsNullString' or |
- 'RequiredCppParameter' in idl_node.ext_attrs): |
- flags = ', DartUtilities::ConvertNullToDefaultValue' |
- emitter.Emit( |
- '\n' |
- ' const $ADAPTER_TYPE $NAME(Dart_GetNativeArgument(args, $INDEX)$FLAGS);\n' |
- ' if (!$NAME.conversionSuccessful()) {\n' |
- ' exception = $NAME.exception();\n' |
- ' goto fail;\n' |
- ' }\n', |
- ADAPTER_TYPE=adapter_type, |
- NAME=adapter_name or idl_node.id, |
- INDEX=index + 1, |
- FLAGS=flags) |
- |
- def _GenerateNativeBinding(self, idl_name, argument_count, dart_declaration, |
- native_suffix, is_custom): |
- native_binding = '%s_%s_%s' % (self._interface.id, idl_name, native_suffix) |
- self._members_emitter.Emit( |
- '\n' |
- ' $DART_DECLARATION native "$NATIVE_BINDING";\n', |
- DART_DECLARATION=dart_declaration, NATIVE_BINDING=native_binding) |
- |
- cpp_callback_name = '%s%s' % (idl_name, native_suffix) |
- self._cpp_resolver_emitter.Emit( |
- ' if (argumentCount == $ARGC && name == "$NATIVE_BINDING")\n' |
- ' return Dart$(INTERFACE_NAME)Internal::$CPP_CALLBACK_NAME;\n', |
- ARGC=argument_count, |
- NATIVE_BINDING=native_binding, |
- INTERFACE_NAME=self._interface.id, |
- 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 _GenerateWebCoreFunctionExpression(self, function_name, idl_node): |
- if 'ImplementedBy' in idl_node.ext_attrs: |
- return '%s::%s' % (idl_node.ext_attrs['ImplementedBy'], function_name) |
- return '%s%s' % (self._interface_type_info.receiver(), function_name) |
- |
- def _GenerateWebCoreInvocation(self, function_expression, arguments, |
- idl_return_type, attributes, raises_dom_exceptions): |
- invocation_template = ' $FUNCTION_CALL;\n' |
- if idl_return_type != 'void': |
- return_type_info = GetIDLTypeInfo(idl_return_type) |
- self._cpp_impl_includes |= set(return_type_info.conversion_includes()) |
- |
- # Generate C++ cast based on idl return type. |
- conversion_cast = return_type_info.conversion_cast('$FUNCTION_CALL') |
- if isinstance(return_type_info, SVGTearOffIDLTypeInfo): |
- svg_primitive_types = ['SVGAngle', 'SVGLength', 'SVGMatrix', |
- 'SVGNumber', 'SVGPoint', 'SVGRect', 'SVGTransform'] |
- conversion_cast = '%s::create($FUNCTION_CALL)' |
- if self._interface.id.startswith('SVGAnimated'): |
- conversion_cast = 'static_cast<%s*>($FUNCTION_CALL)' |
- elif return_type_info.idl_type() == 'SVGStringList': |
- conversion_cast = '%s::create(receiver, $FUNCTION_CALL)' |
- elif self._interface.id.endswith('List'): |
- conversion_cast = 'static_cast<%s*>($FUNCTION_CALL.get())' |
- elif return_type_info.idl_type() in svg_primitive_types: |
- conversion_cast = '%s::create($FUNCTION_CALL)' |
- else: |
- conversion_cast = 'static_cast<%s*>($FUNCTION_CALL)' |
- conversion_cast = conversion_cast % return_type_info.native_type() |
- |
- # Generate to Dart conversion of C++ value. |
- conversion_arguments = [conversion_cast] |
- if (return_type_info.idl_type() in ['DOMString', 'AtomicString'] and |
- 'TreatReturnedNullStringAs' in attributes): |
- conversion_arguments.append('ConvertDefaultToNull') |
- |
- invocation_template = emitter.Format( |
- ' Dart_Handle returnValue = toDartValue($ARGUMENTS);\n' |
- ' if (returnValue)\n' |
- ' Dart_SetReturnValue(args, returnValue);\n', |
- ARGUMENTS=', '.join(conversion_arguments)) |
- |
- if raises_dom_exceptions: |
- # Add 'ec' argument to WebCore invocation and convert DOM exception to Dart exception. |
- arguments.append('ec') |
- invocation_template = emitter.Format( |
- ' ExceptionCode ec = 0;\n' |
- '$INVOCATION' |
- ' if (UNLIKELY(ec)) {\n' |
- ' exception = DartDOMWrapper::exceptionCodeToDartException(ec);\n' |
- ' goto fail;\n' |
- ' }\n', |
- INVOCATION=invocation_template) |
- |
- if 'ImplementedBy' in attributes: |
- arguments.insert(0, 'receiver') |
- self._cpp_impl_includes.add('"%s.h"' % attributes['ImplementedBy']) |
- |
- return emitter.Format(invocation_template, |
- FUNCTION_CALL='%s(%s)' % (function_expression, ', '.join(arguments))) |
- |
-def _GenerateCPPIncludes(includes): |
- return ''.join(['#include %s\n' % include for include in includes]) |