def _process_interface(self, interface, component, interfaces):
        def has_impl(interface):
            # Non legacy callback interface does not provide V8 callbacks.
            if interface.is_callback:
                return len(interface.constants) > 0
            if 'RuntimeEnabled' in interface.extended_attributes:
                return False
            if 'Exposed' not in interface.extended_attributes:
                return True
            return any(
                exposure.exposed == 'Window'
                and exposure.runtime_enabled is None
                for exposure in interface.extended_attributes['Exposed'])

        if not has_impl(interface):
            return

        context_builder = InterfaceTemplateContextBuilder(
            self._opts, self._info_provider)
        context = context_builder.create_interface_context(
            interface, component, interfaces)
        name = '%s%s' % (interface.name,
                         'Partial' if interface.is_partial else '')
        self._interface_contexts[name] = context

        # Do not include unnecessary header files.
        if not context['attributes'] and not context['named_property_setter']:
            return

        include_file = 'third_party/blink/renderer/bindings/%s/v8/%s.h' % (
            component, utilities.to_snake_case(context['v8_class']))
        self._include_files.add(include_file)
示例#2
0
    def _process_interface(self, interface, component, interfaces):
        def has_impl(interface):
            if interface.name in WHITE_LIST_INTERFACES:
                return True
            # Non legacy callback interface does not provide V8 callbacks.
            if interface.is_callback:
                return len(interface.constants) > 0
            if 'RuntimeEnabled' in interface.extended_attributes:
                return False
            return True

        if not has_impl(interface):
            return

        context_builder = InterfaceTemplateContextBuilder(
            self._opts, self._info_provider)
        context = context_builder.create_interface_context(
            interface, interfaces)
        name = '%s%s' % (interface.name,
                         'Partial' if interface.is_partial else '')
        self._interface_contexts[name] = context
        if self._opts.snake_case_generated_files:
            include_file = 'bindings/%s/v8/%s.h' % (
                component, utilities.to_snake_case(context['v8_name']))
        else:
            include_file = 'bindings/%s/v8/%s.h' % (component,
                                                    context['v8_name'])
        self._include_files.add(include_file)
示例#3
0
 def _create_template_context(self):
     interfaces = []
     for name in sorted(self._interface_contexts):
         interfaces.append(self._interface_contexts[name])
     header_name = 'V8ContextSnapshotExternalReferences.h'
     if self._opts.snake_case_generated_files:
         header_name = 'v8_context_snapshot_external_references.h'
     include_files = list(self._include_files)
     # TODO(tkent): Update INCLUDES after the great mv, and remove the
     # following block. crbug.com/760462
     if self._opts.snake_case_generated_files:
         include_files = []
         for include in self._include_files:
             dirname, basename = posixpath.split(include)
             name, ext = posixpath.splitext(basename)
             include_files.append(
                 posixpath.join(dirname,
                                utilities.to_snake_case(name) + ext))
     return {
         'class': 'V8ContextSnapshotExternalReferences',
         'interfaces': interfaces,
         'include_files': sorted(include_files),
         'this_include_header_name': header_name,
         'code_generator': os.path.basename(__file__),
         'jinja_template_filename': TEMPLATE_FILE
     }
def member_impl_context(member, interfaces_info, header_includes,
                        header_forward_decls):
    idl_type = unwrap_nullable_if_needed(member.idl_type)
    cpp_name = to_snake_case(v8_utilities.cpp_name(member))

    nullable_indicator_name = None
    if not idl_type.cpp_type_has_null_value:
        nullable_indicator_name = 'has_' + cpp_name + '_'

    def has_method_expression():
        if nullable_indicator_name:
            return nullable_indicator_name
        if idl_type.is_union_type or idl_type.is_enum or idl_type.is_string_type:
            return '!%s_.IsNull()' % cpp_name
        if idl_type.name == 'Any':
            return '!({0}_.IsEmpty() || {0}_.IsUndefined())'.format(cpp_name)
        if idl_type.name == 'Object':
            return '!({0}_.IsEmpty() || {0}_.IsNull() || {0}_.IsUndefined())'.format(cpp_name)
        if idl_type.name == 'Dictionary':
            return '!%s_.IsUndefinedOrNull()' % cpp_name
        return '%s_' % cpp_name

    cpp_default_value = None
    if member.default_value and not member.default_value.is_null:
        cpp_default_value = idl_type.literal_cpp_value(member.default_value)

    forward_decl_name = idl_type.impl_forward_declaration_name
    if forward_decl_name:
        includes.update(idl_type.impl_includes_for_type(interfaces_info))
        header_forward_decls.add(forward_decl_name)
    else:
        header_includes.update(idl_type.impl_includes_for_type(interfaces_info))

    setter_value = 'value'
    if idl_type.is_array_buffer_view_or_typed_array:
        setter_value += '.View()'

    non_null_type = idl_type.inner_type if idl_type.is_nullable else idl_type
    setter_inline = 'inline ' if (
        non_null_type.is_basic_type or
        non_null_type.is_enum or
        non_null_type.is_wrapper_type) else ''

    return {
        'cpp_default_value': cpp_default_value,
        'cpp_name': cpp_name,
        'getter_expression': cpp_name + '_',
        'getter_name': getter_name_for_dictionary_member(member),
        'has_method_expression': has_method_expression(),
        'has_method_name': has_method_name_for_dictionary_member(member),
        'is_nullable': idl_type.is_nullable,
        'is_traceable': idl_type.is_traceable,
        'member_cpp_type': idl_type.cpp_type_args(used_in_cpp_sequence=True),
        'null_setter_name': null_setter_name_for_dictionary_member(member),
        'nullable_indicator_name': nullable_indicator_name,
        'rvalue_cpp_type': idl_type.cpp_type_args(used_as_rvalue_type=True),
        'setter_inline': setter_inline,
        'setter_name': setter_name_for_dictionary_member(member),
        'setter_value': setter_value,
    }
示例#5
0
def validate_blink_idl_definitions(idl_filename, idl_file_basename,
                                   definitions):
    """Validate file contents with filename convention.

       The Blink IDL conventions are:
       - If an IDL file defines an interface or a dictionary,
         the IDL file must contain exactly one definition. The definition
         name must agree with the file's basename, unless it is a partial
         definition. (e.g., 'partial interface Foo' can be in FooBar.idl).
       - An IDL file can contain typedefs and enums without having other
         definitions. There is no filename convention in this case.
       - Otherwise, an IDL file is invalid.
    """
    targets = (definitions.interfaces.values() +
               definitions.dictionaries.values())
    number_of_targets = len(targets)
    if number_of_targets > 1:
        raise Exception(
            'Expected exactly 1 definition in file {0}, but found {1}'
            .format(idl_filename, number_of_targets))
    if number_of_targets == 0:
        number_of_definitions = (
            len(definitions.enumerations) + len(definitions.typedefs) +
            len(definitions.callback_functions))
        if number_of_definitions == 0:
            raise Exception('No definition found in %s. (Missing semicolon?)' % idl_filename)
        return
    target = targets[0]
    if target.is_partial:
        return
    if target.name != idl_file_basename and to_snake_case(target.name) != idl_file_basename:
        raise Exception(
            'Definition name "{0}" disagrees with IDL file basename "{1}".'
            .format(target.name, idl_file_basename))
示例#6
0
def includes_for_type(idl_type, extended_attributes=None):
    idl_type = idl_type.preprocessed_type
    extended_attributes = extended_attributes or {}

    # Simple types
    base_idl_type = idl_type.base_type
    if base_idl_type in INCLUDES_FOR_TYPE:
        return INCLUDES_FOR_TYPE[base_idl_type]
    if base_idl_type in TYPED_ARRAY_TYPES:
        return INCLUDES_FOR_TYPE['ArrayBufferView'].union(
            set(['bindings/%s/v8/V8%s.h' % (component_dir[base_idl_type], base_idl_type)])
        )
    if idl_type.is_basic_type:
        return set(['bindings/core/v8/IDLTypes.h',
                    'bindings/core/v8/NativeValueTraitsImpl.h'])
    if base_idl_type.endswith('ConstructorConstructor'):
        # FIXME: rename to NamedConstructor
        # FIXME: replace with a [NamedConstructorAttribute] extended attribute
        # Ending with 'ConstructorConstructor' indicates a named constructor,
        # and these do not have header files, as they are part of the generated
        # bindings for the interface
        return set()
    if base_idl_type.endswith('Constructor'):
        # FIXME: replace with a [ConstructorAttribute] extended attribute
        base_idl_type = idl_type.constructor_type_name
    if idl_type.is_custom_callback_function:
        return set()
    if idl_type.is_callback_function:
        component = IdlType.callback_functions[base_idl_type]['component_dir']
        return set(['bindings/%s/v8/%s.h' % (component, to_snake_case('V8%s' % base_idl_type))])
    if base_idl_type not in component_dir:
        return set()
    return set(['bindings/%s/v8/V8%s.h' % (component_dir[base_idl_type],
                                           base_idl_type)])
    def generate_code_internal(self, callback_function, path):
        self.typedef_resolver.resolve(callback_function, callback_function.name)
        header_template = self.jinja_env.get_template('callback_function.h.tmpl')
        cpp_template = self.jinja_env.get_template('callback_function.cpp.tmpl')
        template_context = v8_callback_function.callback_function_context(
            callback_function)
        if not is_testing_target(path):
            template_context['exported'] = self.info_provider.specifier_for_export
            template_context['header_includes'].append(
                self.info_provider.include_path_for_export)

        # TODO(bashi): Dependency resolution shouldn't happen here.
        # Move this into includes_for_type() families.
        for argument in callback_function.arguments:
            if argument.idl_type.is_union_type:
                template_context['header_includes'].append(
                    self.info_provider.include_path_for_union_types(argument.idl_type))

        template_context['header_includes'] = normalize_and_sort_includes(
            template_context['header_includes'])
        template_context['cpp_includes'] = normalize_and_sort_includes(
            template_context['cpp_includes'])
        template_context['code_generator'] = MODULE_PYNAME
        header_text = render_template(header_template, template_context)
        cpp_text = render_template(cpp_template, template_context)
        snake_base_name = to_snake_case('V8%s' % callback_function.name)
        header_path = posixpath.join(self.output_dir, '%s.h' % snake_base_name)
        cpp_path = posixpath.join(self.output_dir, '%s.cc' % snake_base_name)
        return (
            (header_path, header_text),
            (cpp_path, cpp_text),
        )
def callback_function_context(callback_function):
    includes.clear()
    includes.update(CALLBACK_FUNCTION_CPP_INCLUDES)
    idl_type = callback_function.idl_type
    idl_type_str = str(idl_type)

    for argument in callback_function.arguments:
        argument.idl_type.add_includes_for_type(
            callback_function.extended_attributes)

    context = {
        # While both |callback_function_name| and |cpp_class| are identical at
        # the moment, the two are being defined because their values may change
        # in the future (e.g. if we support [ImplementedAs=] in callback
        # functions).
        'callback_function_name': callback_function.name,
        'cpp_class': 'V8%s' % callback_function.name,
        'cpp_includes': sorted(includes),
        'forward_declarations': sorted(forward_declarations(callback_function)),
        'header_includes': sorted(CALLBACK_FUNCTION_H_INCLUDES),
        'idl_type': idl_type_str,
        'return_cpp_type': idl_type.cpp_type,
        'this_include_header_name': to_snake_case('V8%s' % callback_function.name),
    }

    if idl_type_str != 'void':
        context.update({
            'return_value_conversion': idl_type.v8_value_to_local_cpp_value(
                callback_function.extended_attributes,
                'call_result', 'native_result', isolate='GetIsolate()',
                bailout_return_value='v8::Nothing<%s>()' % context['return_cpp_type']),
        })

    context.update(arguments_context(callback_function.arguments))
    return context
示例#9
0
def build_basename(name, prefix=None, ext=None):
    basename = to_snake_case(name)
    if prefix:
        basename = prefix + basename
    if not ext:
        return basename
    return basename + ext
示例#10
0
 def _generate_container_code(self, union_type):
     union_type = union_type.resolve_typedefs(self.typedefs)
     header_template = self.jinja_env.get_template('union_container.h.tmpl')
     cpp_template = self.jinja_env.get_template('union_container.cpp.tmpl')
     template_context = v8_union.container_context(union_type,
                                                   self.info_provider)
     template_context['header_includes'].append(
         self.info_provider.include_path_for_export)
     template_context['header_includes'] = normalize_and_sort_includes(
         template_context['header_includes'],
         self.snake_case_generated_files)
     template_context['cpp_includes'] = normalize_and_sort_includes(
         template_context['cpp_includes'], self.snake_case_generated_files)
     template_context['code_generator'] = self.generator_name
     template_context['exported'] = self.info_provider.specifier_for_export
     snake_base_name = to_snake_case(shorten_union_name(union_type))
     template_context['this_include_header_name'] = snake_base_name
     header_text = render_template(header_template, template_context)
     cpp_text = render_template(cpp_template, template_context)
     header_path = posixpath.join(self.output_dir, '%s.h' % snake_base_name)
     cpp_path = posixpath.join(self.output_dir, '%s.cc' % snake_base_name)
     return (
         (header_path, header_text),
         (cpp_path, cpp_text),
     )
def generate_content(component, basenames):
    # Add fixed content.
    output = [COPYRIGHT_TEMPLATE,
              '#define NO_IMPLICIT_ATOMICSTRING\n\n']

    basenames.sort()
    output.extend('#include "bindings/%s/v8/v8_%s.cc"\n' % (component, to_snake_case(basename))
                  for basename in basenames)
    return ''.join(output)
示例#12
0
def member_context(dictionary, member):
    extended_attributes = member.extended_attributes
    idl_type = member.idl_type
    idl_type.add_includes_for_type(extended_attributes)
    unwrapped_idl_type = unwrap_nullable_if_needed(idl_type)

    if member.is_required and member.default_value:
        raise Exception(
            'Required member %s must not have a default value.' % member.name)

    def default_values():
        if not member.default_value:
            return None, None
        if member.default_value.is_null:
            return None, 'v8::Null(isolate)'
        cpp_default_value = unwrapped_idl_type.literal_cpp_value(
            member.default_value)
        v8_default_value = unwrapped_idl_type.cpp_value_to_v8_value(
            cpp_value=cpp_default_value, isolate='isolate',
            creation_context='creationContext')
        return cpp_default_value, v8_default_value

    cpp_default_value, v8_default_value = default_values()
    cpp_name = to_snake_case(v8_utilities.cpp_name(member))
    getter_name = getter_name_for_dictionary_member(member)
    is_deprecated_dictionary = unwrapped_idl_type.name == 'Dictionary'

    return {
        'cpp_default_value': cpp_default_value,
        'cpp_name': cpp_name,
        'cpp_type': unwrapped_idl_type.cpp_type,
        'cpp_value_to_v8_value': unwrapped_idl_type.cpp_value_to_v8_value(
            cpp_value='impl.%s()' % getter_name, isolate='isolate',
            creation_context='creationContext',
            extended_attributes=extended_attributes),
        'deprecate_as': v8_utilities.deprecate_as(member),
        'enum_type': idl_type.enum_type,
        'enum_values': idl_type.enum_values,
        'getter_name': getter_name,
        'has_method_name': has_method_name_for_dictionary_member(member),
        'idl_type': idl_type.base_type,
        'is_interface_type': idl_type.is_interface_type and not is_deprecated_dictionary,
        'is_nullable': idl_type.is_nullable,
        'is_object': unwrapped_idl_type.name == 'Object' or is_deprecated_dictionary,
        'is_string_type': idl_type.preprocessed_type.is_string_type,
        'is_required': member.is_required,
        'name': member.name,
        'origin_trial_feature_name': v8_utilities.origin_trial_feature_name(member),  # [OriginTrialEnabled]
        'runtime_enabled_feature_name': v8_utilities.runtime_enabled_feature_name(member),  # [RuntimeEnabled]
        'setter_name': setter_name_for_dictionary_member(member),
        'null_setter_name': null_setter_name_for_dictionary_member(member),
        'v8_default_value': v8_default_value,
        'v8_value_to_local_cpp_value': idl_type.v8_value_to_local_cpp_value(
            extended_attributes, member.name + 'Value',
            member.name + 'CppValue', isolate='isolate', use_exception_state=True),
    }
示例#13
0
def normalize_and_sort_includes(include_paths, snake_case):
    normalized_include_paths = []
    for include_path in include_paths:
        match = re.search(r'/gen/blink/(.*)$', posixpath.abspath(include_path))
        if match:
            include_path = match.group(1)
        if snake_case:
            match = re.search(r'/([^/]+)\.h$', include_path)
            if match:
                name = match.group(1)
                if name.lower() != name:
                    include_path = include_path[0:match.start(1)] + to_snake_case(name) + '.h'
        normalized_include_paths.append(include_path)
    return sorted(normalized_include_paths)
示例#14
0
def build_basename(name, snake_case, prefix=None, ext=None):
    basename = name
    if prefix:
        basename = prefix + name
    if snake_case:
        basename = to_snake_case(basename)
        if not ext:
            return basename
        if ext == '.cpp':
            return basename + '.cc'
        return basename + ext
    if ext:
        return basename + ext
    return basename
示例#15
0
def member_context(member, info_provider):
    _update_includes_and_forward_decls(member, info_provider)
    if member.is_nullable:
        member = member.inner_type
    type_name = (member.inner_type
                 if member.is_annotated_type else member).name
    # When converting a sequence or frozen array, we need to call the GetMethod(V, @@iterator)
    # ES abstract operation and then use the result of that call to create a sequence from an
    # iterable. For the purposes of this method, it means we need to pass |script_iterator|
    # rather than |v8_value| in v8_value_to_local_cpp_value().
    if member.is_array_or_sequence_type:
        v8_value_name = 'std::move(script_iterator)'
    else:
        v8_value_name = 'v8_value'
    return {
        'cpp_name':
        to_snake_case(v8_utilities.cpp_name(member)),
        'cpp_type':
        member.cpp_type_args(used_in_cpp_sequence=True),
        'cpp_local_type':
        member.cpp_type,
        'cpp_value_to_v8_value':
        member.cpp_value_to_v8_value(
            cpp_value='impl.GetAs%s()' % type_name,
            isolate='isolate',
            creation_context='creationContext'),
        'enum_type':
        member.enum_type,
        'enum_values':
        member.enum_values,
        'is_array_buffer_or_view_type':
        member.is_array_buffer_or_view,
        'is_array_buffer_view_or_typed_array':
        member.is_array_buffer_view_or_typed_array,
        'is_traceable':
        member.is_traceable,
        'rvalue_cpp_type':
        member.cpp_type_args(used_as_rvalue_type=True),
        'specific_type_enum':
        'k' + member.name,
        'type_name':
        type_name,
        'v8_value_to_local_cpp_value':
        member.v8_value_to_local_cpp_value({},
                                           v8_value_name,
                                           'cpp_value',
                                           isolate='isolate',
                                           use_exception_state=True)
    }
示例#16
0
def include_path(idl_filename, implemented_as=None):
    """Returns relative path to header file in POSIX format; used in includes.

    POSIX format is used for consistency of output, so reference tests are
    platform-independent.
    """
    if idl_filename.startswith(gen_path):
        relative_dir = relative_dir_posix(idl_filename, gen_path)
    else:
        relative_dir = relative_dir_posix(idl_filename, source_path)

    # IDL file basename is used even if only a partial interface file
    output_file_basename = implemented_as or idl_filename_to_basename(
        idl_filename)
    output_file_basename = to_snake_case(output_file_basename)
    return posixpath.join(relative_dir, output_file_basename + '.h')
示例#17
0
 def _generate_container_code(self, union_type):
     includes.clear()
     union_type = union_type.resolve_typedefs(self.typedefs)
     header_template = self.jinja_env.get_template('union_container.h.tmpl')
     cpp_template = self.jinja_env.get_template('union_container.cc.tmpl')
     template_context = v8_union.container_context(union_type, self.info_provider)
     template_context['header_includes'].append(
         self.info_provider.include_path_for_export)
     template_context['exported'] = self.info_provider.specifier_for_export
     snake_base_name = to_snake_case(shorten_union_name(union_type))
     header_path = posixpath.join(self.output_dir, '%s.h' % snake_base_name)
     cpp_path = posixpath.join(self.output_dir, '%s.cc' % snake_base_name)
     this_include_header_path = self.normalize_this_header_path(header_path)
     template_context['this_include_header_path'] = this_include_header_path
     template_context['header_guard'] = to_header_guard(this_include_header_path)
     header_text, cpp_text = self.render_templates(
         [], header_template, cpp_template, template_context)
     return (
         (header_path, header_text),
         (cpp_path, cpp_text),
     )
def member_context(member, info_provider):
    _update_includes_and_forward_decls(member, info_provider)
    if member.is_nullable:
        member = member.inner_type
    type_name = (member.inner_type
                 if member.is_annotated_type else member).name
    return {
        'cpp_name':
        to_snake_case(v8_utilities.cpp_name(member)),
        'cpp_type':
        member.cpp_type_args(used_in_cpp_sequence=True),
        'cpp_local_type':
        member.cpp_type,
        'cpp_value_to_v8_value':
        member.cpp_value_to_v8_value(cpp_value='impl.GetAs%s()' % type_name,
                                     isolate='isolate',
                                     creation_context='creationContext'),
        'enum_type':
        member.enum_type,
        'enum_values':
        member.enum_values,
        'is_array_buffer_or_view_type':
        member.is_array_buffer_or_view,
        'is_array_buffer_view_or_typed_array':
        member.is_array_buffer_view_or_typed_array,
        'is_traceable':
        member.is_traceable,
        'rvalue_cpp_type':
        member.cpp_type_args(used_as_rvalue_type=True),
        'specific_type_enum':
        'k' + member.name,
        'type_name':
        type_name,
        'v8_value_to_local_cpp_value':
        member.v8_value_to_local_cpp_value({},
                                           'v8_value',
                                           'cpp_value',
                                           isolate='isolate',
                                           use_exception_state=True)
    }
def include_path(idl_filename, implemented_as=None):
    """Returns relative path to header file in POSIX format; used in includes.

    POSIX format is used for consistency of output, so reference tests are
    platform-independent.
    """
    if idl_filename.startswith(gen_path):
        relative_dir = relative_dir_posix(idl_filename, gen_path)
    else:
        relative_dir = relative_dir_posix(idl_filename, source_path)

    # The generated relative include path might be wrong if the relative path
    # points to a parent directory in case of shadow build. To avoid jumbled
    # relative paths use absolute path instead.
    if relative_dir.startswith(".."):
        relative_dir = abs(os.path.dirname(idl_filename))
        relative_dir = relative_dir.replace(os.path.sep, posixpath.sep)

    # IDL file basename is used even if only a partial interface file
    output_file_basename = implemented_as or idl_filename_to_basename(
        idl_filename)
    output_file_basename = to_snake_case(output_file_basename)
    return posixpath.join(relative_dir, output_file_basename + '.h')
示例#20
0
 def generate_code_internal(self, callback_function, path):
     self.typedef_resolver.resolve(callback_function, callback_function.name)
     header_template = self.jinja_env.get_template('callback_function.h.tmpl')
     cpp_template = self.jinja_env.get_template('callback_function.cpp.tmpl')
     template_context = v8_callback_function.callback_function_context(
         callback_function)
     if not is_testing_target(path):
         template_context['exported'] = self.info_provider.specifier_for_export
         template_context['header_includes'].append(
             self.info_provider.include_path_for_export)
     template_context['header_includes'] = normalize_and_sort_includes(
         template_context['header_includes'], self.snake_case_generated_files)
     template_context['cpp_includes'] = normalize_and_sort_includes(
         template_context['cpp_includes'], self.snake_case_generated_files)
     template_context['code_generator'] = MODULE_PYNAME
     header_text = render_template(header_template, template_context)
     cpp_text = render_template(cpp_template, template_context)
     snake_base_name = to_snake_case('V8%s' % callback_function.name)
     header_path = posixpath.join(self.output_dir, '%s.h' % snake_base_name)
     cpp_path = posixpath.join(self.output_dir, '%s.cc' % snake_base_name)
     return (
         (header_path, header_text),
         (cpp_path, cpp_text),
     )
示例#21
0
def bindings_tests(output_directory, verbose, suppress_diff):
    executive = Executive()

    def list_files(directory):
        if not os.path.isdir(directory):
            return []

        files = []
        for component in os.listdir(directory):
            if component not in COMPONENT_DIRECTORY:
                continue
            directory_with_component = os.path.join(directory, component)
            for filename in os.listdir(directory_with_component):
                files.append(os.path.join(directory_with_component, filename))
        return files

    def diff(filename1, filename2):
        with open(filename1) as file1:
            file1_lines = file1.readlines()
        with open(filename2) as file2:
            file2_lines = file2.readlines()

        # Use Python's difflib module so that diffing works across platforms
        return ''.join(difflib.context_diff(file1_lines, file2_lines))

    def is_cache_file(filename):
        return filename.endswith('.cache')

    def delete_cache_files():
        # FIXME: Instead of deleting cache files, don't generate them.
        cache_files = [
            path for path in list_files(output_directory)
            if is_cache_file(os.path.basename(path))
        ]
        for cache_file in cache_files:
            os.remove(cache_file)

    def identical_file(reference_filename, output_filename):
        reference_basename = os.path.basename(reference_filename)

        if not os.path.isfile(reference_filename):
            print 'Missing reference file!'
            print '(if adding new test, update reference files)'
            print reference_basename
            print
            return False

        if not filecmp.cmp(reference_filename, output_filename):
            # cmp is much faster than diff, and usual case is "no difference",
            # so only run diff if cmp detects a difference
            print 'FAIL: %s' % reference_basename
            if not suppress_diff:
                print diff(reference_filename, output_filename)
            return False

        if verbose:
            print 'PASS: %s' % reference_basename
        return True

    def identical_output_files(output_files):
        reference_files = [
            os.path.join(REFERENCE_DIRECTORY,
                         os.path.relpath(path, output_directory))
            for path in output_files
        ]
        return all([
            identical_file(reference_filename, output_filename)
            for (reference_filename,
                 output_filename) in zip(reference_files, output_files)
        ])

    def no_excess_files(output_files):
        generated_files = set(
            [os.path.relpath(path, output_directory) for path in output_files])
        excess_files = []
        for path in list_files(REFERENCE_DIRECTORY):
            relpath = os.path.relpath(path, REFERENCE_DIRECTORY)
            # Ignore backup files made by a VCS.
            if os.path.splitext(relpath)[1] == '.orig':
                continue
            if relpath not in generated_files:
                excess_files.append(relpath)
        if excess_files:
            print(
                'Excess reference files! '
                '(probably cruft from renaming or deleting):\n' +
                '\n'.join(excess_files))
            return False
        return True

    def make_runtime_features_dict():
        input_filename = os.path.join(TEST_INPUT_DIRECTORY,
                                      'runtime_enabled_features.json5')
        json5_file = Json5File.load_from_files([input_filename])
        features_map = {}
        for feature in json5_file.name_dictionaries:
            features_map[str(feature['name'])] = {
                'in_origin_trial': feature['in_origin_trial']
            }
        return features_map

    try:
        generate_interface_dependencies(make_runtime_features_dict())
        for component in COMPONENT_DIRECTORY:
            output_dir = os.path.join(output_directory, component)
            if not os.path.exists(output_dir):
                os.makedirs(output_dir)

            options = IdlCompilerOptions(output_directory=output_dir,
                                         impl_output_directory=output_dir,
                                         cache_directory=None,
                                         target_component=component)

            if component == 'core':
                partial_interface_output_dir = os.path.join(
                    output_directory, 'modules')
                if not os.path.exists(partial_interface_output_dir):
                    os.makedirs(partial_interface_output_dir)
                partial_interface_options = IdlCompilerOptions(
                    output_directory=partial_interface_output_dir,
                    impl_output_directory=None,
                    cache_directory=None,
                    target_component='modules')

            idl_filenames = []
            dictionary_impl_filenames = []
            partial_interface_filenames = []
            input_directory = os.path.join(TEST_INPUT_DIRECTORY, component)
            for filename in os.listdir(input_directory):
                if (filename.endswith('.idl') and
                        # Dependencies aren't built
                        # (they are used by the dependent)
                        filename not in DEPENDENCY_IDL_FILES):
                    idl_path = os.path.realpath(
                        os.path.join(input_directory, filename))
                    idl_filenames.append(idl_path)
                    idl_basename = os.path.basename(idl_path)
                    name_from_basename, _ = os.path.splitext(idl_basename)
                    definition_name = get_first_interface_name_from_idl(
                        get_file_contents(idl_path))
                    is_partial_interface_idl = to_snake_case(
                        definition_name) != name_from_basename
                    if not is_partial_interface_idl:
                        interface_info = interfaces_info[definition_name]
                        if interface_info['is_dictionary']:
                            dictionary_impl_filenames.append(idl_path)
                        if component == 'core' and interface_info[
                                'dependencies_other_component_full_paths']:
                            partial_interface_filenames.append(idl_path)

            info_provider = component_info_providers[component]
            partial_interface_info_provider = component_info_providers[
                'modules']

            generate_union_type_containers(CodeGeneratorUnionType,
                                           info_provider, options)
            generate_callback_function_impl(CodeGeneratorCallbackFunction,
                                            info_provider, options)
            generate_bindings(CodeGeneratorV8, info_provider, options,
                              idl_filenames)
            generate_bindings(CodeGeneratorV8, partial_interface_info_provider,
                              partial_interface_options,
                              partial_interface_filenames)
            generate_dictionary_impl(CodeGeneratorDictionaryImpl,
                                     info_provider, options,
                                     dictionary_impl_filenames)
            generate_origin_trial_features(info_provider, options, [
                filename for filename in idl_filenames
                if filename not in dictionary_impl_filenames
            ])

    finally:
        delete_cache_files()

    # Detect all changes
    output_files = list_files(output_directory)
    passed = identical_output_files(output_files)
    passed &= no_excess_files(output_files)

    if passed:
        if verbose:
            print
            print PASS_MESSAGE
        return 0
    print
    print FAIL_MESSAGE
    return 1
示例#22
0
def build_basename(name, prefix=None):
    basename = to_snake_case(name)
    if prefix:
        basename = prefix + basename
    return basename
示例#23
0
def member_impl_context(member, interfaces_info, header_includes,
                        header_forward_decls):
    idl_type = unwrap_nullable_if_needed(member.idl_type)
    cpp_name = to_snake_case(v8_utilities.cpp_name(member))

    # In most cases, we don't have to distinguish `null` and `not present`,
    # and use null-states (e.g. nullptr, foo.IsUndefinedOrNull()) to show such
    # states for some types for memory usage and performance.
    # For types whose |has_explicit_presence| is True, we provide explicit
    # states of presence.
    has_explicit_presence = (member.idl_type.is_nullable
                             and member.idl_type.inner_type.is_interface_type)

    nullable_indicator_name = None
    if not idl_type.cpp_type_has_null_value or has_explicit_presence:
        nullable_indicator_name = 'has_' + cpp_name + '_'

    def has_method_expression():
        if nullable_indicator_name:
            return nullable_indicator_name
        if idl_type.is_union_type or idl_type.is_enum or idl_type.is_string_type:
            return '!%s_.IsNull()' % cpp_name
        if idl_type.name == 'Any':
            return '!({0}_.IsEmpty() || {0}_.IsUndefined())'.format(cpp_name)
        if idl_type.name == 'Object':
            return '!({0}_.IsEmpty() || {0}_.IsNull() || {0}_.IsUndefined())'.format(
                cpp_name)
        if idl_type.name == 'Dictionary':
            return '!%s_.IsUndefinedOrNull()' % cpp_name
        return '%s_' % cpp_name

    cpp_default_value = None
    if member.default_value:
        if not member.default_value.is_null or has_explicit_presence:
            cpp_default_value = idl_type.literal_cpp_value(
                member.default_value)

    forward_decl_name = idl_type.impl_forward_declaration_name
    if forward_decl_name:
        includes.update(idl_type.impl_includes_for_type(interfaces_info))
        header_forward_decls.add(forward_decl_name)
    else:
        header_includes.update(
            idl_type.impl_includes_for_type(interfaces_info))

    setter_value = 'value'
    if idl_type.is_array_buffer_view_or_typed_array:
        setter_value += '.View()'

    non_null_type = idl_type.inner_type if idl_type.is_nullable else idl_type
    setter_inline = 'inline ' if (non_null_type.is_basic_type
                                  or non_null_type.is_enum
                                  or non_null_type.is_wrapper_type) else ''

    return {
        'cpp_default_value': cpp_default_value,
        'cpp_name': cpp_name,
        'has_explicit_presence': has_explicit_presence,
        'getter_expression': cpp_name + '_',
        'getter_name': getter_name_for_dictionary_member(member),
        'has_method_expression': has_method_expression(),
        'has_method_name': has_method_name_for_dictionary_member(member),
        'is_nullable': idl_type.is_nullable,
        'is_traceable': idl_type.is_traceable,
        'member_cpp_type': idl_type.cpp_type_args(used_in_cpp_sequence=True),
        'null_setter_name': null_setter_name_for_dictionary_member(member),
        'nullable_indicator_name': nullable_indicator_name,
        'rvalue_cpp_type': idl_type.cpp_type_args(used_as_rvalue_type=True),
        'setter_inline': setter_inline,
        'setter_name': setter_name_for_dictionary_member(member),
        'setter_value': setter_value,
    }
示例#24
0
def member_context(dictionary, member):
    extended_attributes = member.extended_attributes
    idl_type = member.idl_type
    idl_type.add_includes_for_type(extended_attributes)
    unwrapped_idl_type = unwrap_nullable_if_needed(idl_type)

    if member.is_required and member.default_value:
        raise Exception('Required member %s must not have a default value.' %
                        member.name)

    # In most cases, we don't have to distinguish `null` and `not present`,
    # and use null-states (e.g. nullptr, foo.IsUndefinedOrNull()) to show such
    # states for some types for memory usage and performance.
    # For types whose |has_explicit_presence| is True, we provide explicit
    # states of presence.
    has_explicit_presence = (idl_type.is_nullable
                             and idl_type.inner_type.is_interface_type)

    def default_values():
        if not member.default_value:
            return None, None
        if member.default_value.is_null:
            return None, 'v8::Null(isolate)'
        cpp_default_value = unwrapped_idl_type.literal_cpp_value(
            member.default_value)
        v8_default_value = unwrapped_idl_type.cpp_value_to_v8_value(
            cpp_value=cpp_default_value,
            isolate='isolate',
            creation_context='creationContext')
        return cpp_default_value, v8_default_value

    cpp_default_value, v8_default_value = default_values()
    snake_case_name = to_snake_case(member.name)
    cpp_value = snake_case_name + "_cpp_value"
    v8_value = snake_case_name + "_value"
    has_value_or_default = snake_case_name + "_has_value_or_default"
    getter_name = getter_name_for_dictionary_member(member)
    is_deprecated_dictionary = unwrapped_idl_type.name == 'Dictionary'

    return {
        'cpp_default_value':
        cpp_default_value,
        'cpp_type':
        unwrapped_idl_type.cpp_type,
        'cpp_value':
        cpp_value,
        'cpp_value_to_v8_value':
        unwrapped_idl_type.cpp_value_to_v8_value(
            cpp_value='impl.%s()' % getter_name,
            isolate='isolate',
            creation_context='creationContext',
            extended_attributes=extended_attributes),
        'deprecate_as':
        v8_utilities.deprecate_as(member),
        'enum_type':
        idl_type.enum_type,
        'enum_values':
        idl_type.enum_values,
        'getter_name':
        getter_name,
        'has_explicit_presence':
        has_explicit_presence,
        'has_method_name':
        has_method_name_for_dictionary_member(member),
        'idl_type':
        idl_type.base_type,
        'is_interface_type':
        idl_type.is_interface_type and not is_deprecated_dictionary,
        'is_nullable':
        idl_type.is_nullable,
        'is_object':
        unwrapped_idl_type.name == 'Object' or is_deprecated_dictionary,
        'is_string_type':
        idl_type.preprocessed_type.is_string_type,
        'is_required':
        member.is_required,
        'name':
        member.name,
        'origin_trial_feature_name':
        v8_utilities.origin_trial_feature_name(member),  # [OriginTrialEnabled]
        'runtime_enabled_feature_name':
        v8_utilities.runtime_enabled_feature_name(member),  # [RuntimeEnabled]
        'setter_name':
        setter_name_for_dictionary_member(member),
        'has_value_or_default':
        has_value_or_default,
        'null_setter_name':
        null_setter_name_for_dictionary_member(member),
        'v8_default_value':
        v8_default_value,
        'v8_value':
        v8_value,
        'v8_value_to_local_cpp_value':
        idl_type.v8_value_to_local_cpp_value(extended_attributes,
                                             v8_value,
                                             cpp_value,
                                             isolate='isolate',
                                             use_exception_state=True),
    }
示例#25
0
def bindings_tests(output_directory, verbose, suppress_diff):
    executive = Executive()

    def list_files(directory):
        files = []
        for component in os.listdir(directory):
            if component not in COMPONENT_DIRECTORY:
                continue
            directory_with_component = os.path.join(directory, component)
            for filename in os.listdir(directory_with_component):
                files.append(os.path.join(directory_with_component, filename))
        return files

    def diff(filename1, filename2):
        # Python's difflib module is too slow, especially on long output, so
        # run external diff(1) command
        cmd = [
            'diff',
            '-u',  # unified format
            '-N',  # treat absent files as empty
            filename1,
            filename2
        ]
        # Return output and don't raise exception, even though diff(1) has
        # non-zero exit if files differ.
        return executive.run_command(cmd, error_handler=lambda x: None)

    def is_cache_file(filename):
        return filename.endswith('.cache')

    def delete_cache_files():
        # FIXME: Instead of deleting cache files, don't generate them.
        cache_files = [
            path for path in list_files(output_directory)
            if is_cache_file(os.path.basename(path))
        ]
        for cache_file in cache_files:
            os.remove(cache_file)

    def identical_file(reference_filename, output_filename):
        reference_basename = os.path.basename(reference_filename)

        if not os.path.isfile(reference_filename):
            print 'Missing reference file!'
            print '(if adding new test, update reference files)'
            print reference_basename
            print
            return False

        if not filecmp.cmp(reference_filename, output_filename):
            # cmp is much faster than diff, and usual case is "no difference",
            # so only run diff if cmp detects a difference
            print 'FAIL: %s' % reference_basename
            if not suppress_diff:
                print diff(reference_filename, output_filename)
            return False

        if verbose:
            print 'PASS: %s' % reference_basename
        return True

    def identical_output_files(output_files):
        reference_files = [
            os.path.join(REFERENCE_DIRECTORY,
                         os.path.relpath(path, output_directory))
            for path in output_files
        ]
        return all([
            identical_file(reference_filename, output_filename)
            for (reference_filename,
                 output_filename) in zip(reference_files, output_files)
        ])

    def no_excess_files(output_files):
        generated_files = set(
            [os.path.relpath(path, output_directory) for path in output_files])
        excess_files = []
        for path in list_files(REFERENCE_DIRECTORY):
            relpath = os.path.relpath(path, REFERENCE_DIRECTORY)
            # Ignore backup files made by a VCS.
            if os.path.splitext(relpath)[1] == '.orig':
                continue
            if relpath not in generated_files:
                excess_files.append(relpath)
        if excess_files:
            print(
                'Excess reference files! '
                '(probably cruft from renaming or deleting):\n' +
                '\n'.join(excess_files))
            return False
        return True

    try:
        generate_interface_dependencies()
        for component in COMPONENT_DIRECTORY:
            output_dir = os.path.join(output_directory, component)
            if not os.path.exists(output_dir):
                os.makedirs(output_dir)

            options = IdlCompilerOptions(output_directory=output_dir,
                                         impl_output_directory=output_dir,
                                         cache_directory=None,
                                         target_component=component)

            if component == 'core':
                partial_interface_output_dir = os.path.join(
                    output_directory, 'modules')
                if not os.path.exists(partial_interface_output_dir):
                    os.makedirs(partial_interface_output_dir)
                partial_interface_options = IdlCompilerOptions(
                    output_directory=partial_interface_output_dir,
                    impl_output_directory=None,
                    cache_directory=None,
                    target_component='modules')

            idl_filenames = []
            dictionary_impl_filenames = []
            partial_interface_filenames = []
            input_directory = os.path.join(TEST_INPUT_DIRECTORY, component)
            for filename in os.listdir(input_directory):
                if (filename.endswith('.idl') and
                        # Dependencies aren't built
                        # (they are used by the dependent)
                        filename not in DEPENDENCY_IDL_FILES):
                    idl_path = os.path.realpath(
                        os.path.join(input_directory, filename))
                    idl_filenames.append(idl_path)
                    idl_basename = os.path.basename(idl_path)
                    name_from_basename, _ = os.path.splitext(idl_basename)
                    definition_name = get_first_interface_name_from_idl(
                        get_file_contents(idl_path))
                    is_partial_interface_idl = to_snake_case(
                        definition_name) != name_from_basename
                    if not is_partial_interface_idl:
                        interface_info = interfaces_info[definition_name]
                        if interface_info['is_dictionary']:
                            dictionary_impl_filenames.append(idl_path)
                        if component == 'core' and interface_info[
                                'dependencies_other_component_full_paths']:
                            partial_interface_filenames.append(idl_path)

            info_provider = component_info_providers[component]
            partial_interface_info_provider = component_info_providers[
                'modules']

            generate_union_type_containers(CodeGeneratorUnionType,
                                           info_provider, options)
            generate_callback_function_impl(CodeGeneratorCallbackFunction,
                                            info_provider, options)
            generate_bindings(CodeGeneratorV8, info_provider, options,
                              idl_filenames)
            generate_bindings(CodeGeneratorWebAgentAPI, info_provider, options,
                              idl_filenames)
            generate_bindings(CodeGeneratorV8, partial_interface_info_provider,
                              partial_interface_options,
                              partial_interface_filenames)
            generate_dictionary_impl(CodeGeneratorDictionaryImpl,
                                     info_provider, options,
                                     dictionary_impl_filenames)
            generate_origin_trial_features(info_provider, options, [
                filename for filename in idl_filenames
                if filename not in dictionary_impl_filenames
            ])

    finally:
        delete_cache_files()

    # Detect all changes
    output_files = list_files(output_directory)
    passed = identical_output_files(output_files)
    passed &= no_excess_files(output_files)

    if passed:
        if verbose:
            print
            print PASS_MESSAGE
        return 0
    print
    print FAIL_MESSAGE
    return 1