Home | History | Annotate | Download | only in scripts
      1 # Copyright (C) 2013 Google Inc. All rights reserved.
      2 #
      3 # Redistribution and use in source and binary forms, with or without
      4 # modification, are permitted provided that the following conditions are
      5 # met:
      6 #
      7 #     * Redistributions of source code must retain the above copyright
      8 # notice, this list of conditions and the following disclaimer.
      9 #     * Redistributions in binary form must reproduce the above
     10 # copyright notice, this list of conditions and the following disclaimer
     11 # in the documentation and/or other materials provided with the
     12 # distribution.
     13 #     * Neither the name of Google Inc. nor the names of its
     14 # contributors may be used to endorse or promote products derived from
     15 # this software without specific prior written permission.
     16 #
     17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28 
     29 """Generate template values for a callback interface.
     30 
     31 Extends IdlType with property |callback_cpp_type|.
     32 
     33 Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
     34 """
     35 
     36 from idl_types import IdlType
     37 from v8_globals import includes
     38 import v8_types
     39 import v8_utilities
     40 
     41 CALLBACK_INTERFACE_H_INCLUDES = frozenset([
     42     'bindings/v8/ActiveDOMCallback.h',
     43     'bindings/v8/DOMWrapperWorld.h',
     44     'bindings/v8/ScopedPersistent.h',
     45 ])
     46 CALLBACK_INTERFACE_CPP_INCLUDES = frozenset([
     47     'bindings/v8/V8Binding.h',
     48     'bindings/v8/V8Callback.h',
     49     'core/dom/ExecutionContext.h',
     50     'wtf/Assertions.h',
     51     'wtf/GetPtr.h',
     52     'wtf/RefPtr.h',
     53 ])
     54 
     55 
     56 def cpp_type(idl_type):
     57     # FIXME: remove this function by making callback types consistent
     58     # (always use usual v8_types.cpp_type)
     59     idl_type_name = idl_type.name
     60     if idl_type_name == 'String':
     61         return 'const String&'
     62     if idl_type_name == 'void':
     63         return 'void'
     64     # Callbacks use raw pointers, so used_as_argument=True
     65     usual_cpp_type = idl_type.cpp_type_args(used_as_argument=True)
     66     if usual_cpp_type.startswith(('Vector', 'HeapVector', 'WillBeHeapVector')):
     67         return 'const %s&' % usual_cpp_type
     68     return usual_cpp_type
     69 
     70 IdlType.callback_cpp_type = property(cpp_type)
     71 
     72 
     73 def generate_callback_interface(callback_interface):
     74     includes.clear()
     75     includes.update(CALLBACK_INTERFACE_CPP_INCLUDES)
     76     return {
     77         'conditional_string': v8_utilities.conditional_string(callback_interface),
     78         'cpp_class': callback_interface.name,
     79         'v8_class': v8_utilities.v8_class_name(callback_interface),
     80         'header_includes': set(CALLBACK_INTERFACE_H_INCLUDES),
     81         'methods': [generate_method(operation)
     82                     for operation in callback_interface.operations],
     83     }
     84 
     85 
     86 def add_includes_for_operation(operation):
     87     operation.idl_type.add_includes_for_type()
     88     for argument in operation.arguments:
     89         argument.idl_type.add_includes_for_type()
     90 
     91 
     92 def generate_method(operation):
     93     extended_attributes = operation.extended_attributes
     94     idl_type = operation.idl_type
     95     idl_type_str = str(idl_type)
     96     if idl_type_str not in ['boolean', 'void']:
     97         raise Exception('We only support callbacks that return boolean or void values.')
     98     is_custom = 'Custom' in extended_attributes
     99     if not is_custom:
    100         add_includes_for_operation(operation)
    101     call_with = extended_attributes.get('CallWith')
    102     call_with_this_handle = v8_utilities.extended_attribute_value_contains(call_with, 'ThisValue')
    103     contents = {
    104         'call_with_this_handle': call_with_this_handle,
    105         'cpp_type': idl_type.callback_cpp_type,
    106         'custom': is_custom,
    107         'idl_type': idl_type_str,
    108         'name': operation.name,
    109     }
    110     contents.update(generate_arguments_contents(operation.arguments, call_with_this_handle))
    111     return contents
    112 
    113 
    114 def generate_arguments_contents(arguments, call_with_this_handle):
    115     def generate_argument(argument):
    116         return {
    117             'handle': '%sHandle' % argument.name,
    118             # FIXME: setting creation_context=v8::Handle<v8::Object>() is
    119             # wrong, as toV8 then implicitly uses the current context, which
    120             # causes leaks between isolated worlds if a different context is
    121             # used.
    122             'cpp_value_to_v8_value': argument.idl_type.cpp_value_to_v8_value(
    123                 argument.name, isolate='isolate',
    124                 creation_context='m_scriptState->context()->Global()'),
    125         }
    126 
    127     argument_declarations = ['ScriptValue thisValue'] if call_with_this_handle else []
    128     argument_declarations.extend(
    129         '%s %s' % (argument.idl_type.callback_cpp_type, argument.name)
    130         for argument in arguments)
    131     return  {
    132         'argument_declarations': argument_declarations,
    133         'arguments': [generate_argument(argument) for argument in arguments],
    134     }
    135