• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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"""Functions shared by various parts of the code generator.
30
31FIXME: Not currently used in build.
32This is a rewrite of the Perl IDL compiler in Python, but is not complete.
33Once it is complete, we will switch all IDL files over to Python at once.
34Until then, please work on the Perl IDL compiler.
35For details, see bug http://crbug.com/239771
36"""
37
38# FIXME: eliminate this file if possible
39
40import re
41
42from v8_globals import includes
43import v8_types
44
45ACRONYMS = ['CSS', 'HTML', 'IME', 'JS', 'SVG', 'URL', 'WOFF', 'XML', 'XSLT']
46
47
48# Extended attributes
49def extended_attribute_value_contains(extended_attribute_value, value):
50    return (extended_attribute_value and
51            value in re.split('[|&]', extended_attribute_value))
52
53
54def has_extended_attribute(definition_or_member, extended_attribute_list):
55    return any(extended_attribute in definition_or_member.extended_attributes
56               for extended_attribute in extended_attribute_list)
57
58
59def has_extended_attribute_value(definition_or_member, name, value):
60    extended_attributes = definition_or_member.extended_attributes
61    return (name in extended_attributes and
62            extended_attribute_value_contains(extended_attributes[name], value))
63
64
65# String handling
66def capitalize(name):
67    """Capitalize first letter or initial acronym (used in setter names)."""
68    for acronym in ACRONYMS:
69        if name.startswith(acronym.lower()):
70            return name.replace(acronym.lower(), acronym)
71    return name[0].upper() + name[1:]
72
73
74def strip_suffix(string, suffix):
75    if not suffix or not string.endswith(suffix):
76        return string
77    return string[:-len(suffix)]
78
79
80def uncapitalize(name):
81    """Uncapitalizes first letter or initial acronym (used in method names).
82
83    E.g., 'SetURL' becomes 'setURL', but 'URLFoo' becomes 'urlFoo'.
84    """
85    for acronym in ACRONYMS:
86        if name.startswith(acronym):
87            name.replace(acronym, acronym.lower())
88            return name
89    return name[0].lower() + name[1:]
90
91
92# C++
93def enum_validation_expression(idl_type):
94    if not v8_types.is_enum_type(idl_type):
95        return None
96    return ' || '.join(['string == "%s"' % enum_value
97                        for enum_value in v8_types.enum_values(idl_type)])
98
99
100def scoped_name(interface, definition, base_name):
101    if definition.is_static:
102        return '%s::%s' % (interface.name, base_name)
103    return 'imp->%s' % base_name
104
105
106def v8_class_name(interface):
107    return v8_types.v8_type(interface.name)
108
109
110# [ActivityLogging]
111def activity_logging_world_list(member, access_type=None):
112    """Returns a set of world suffixes for which a definition member has activity logging, for specified access type.
113
114    access_type can be 'Getter' or 'Setter' if only checking getting or setting.
115    """
116    if 'ActivityLogging' not in member.extended_attributes:
117        return set()
118    activity_logging = member.extended_attributes['ActivityLogging']
119    # [ActivityLogging=For*] (no prefix, starts with the worlds suffix) means
120    # "log for all use (method)/access (attribute)", otherwise check that value
121    # agrees with specified access_type (Getter/Setter).
122    has_logging = (activity_logging.startswith('For') or
123                   (access_type and activity_logging.startswith(access_type)))
124    if not has_logging:
125        return set()
126    includes.add('bindings/v8/V8DOMActivityLogger.h')
127    if activity_logging.endswith('ForIsolatedWorlds'):
128        return set([''])
129    return set(['', 'ForMainWorld'])  # endswith('ForAllWorlds')
130
131
132# [CallWith]
133CALL_WITH_ARGUMENTS = {
134    'ScriptState': '&state',
135    'ExecutionContext': 'scriptContext',
136    'ScriptArguments': 'scriptArguments.release()',
137    'ActiveWindow': 'activeDOMWindow()',
138    'FirstWindow': 'firstDOMWindow()',
139}
140# List because key order matters, as we want arguments in deterministic order
141CALL_WITH_VALUES = [
142    'ScriptState',
143    'ExecutionContext',
144    'ScriptArguments',
145    'ActiveWindow',
146    'FirstWindow',
147]
148
149
150def call_with_arguments(member, call_with_values=None):
151    # Optional parameter so setter can override with [SetterCallWith]
152    call_with_values = call_with_values or member.extended_attributes.get('CallWith')
153    if not call_with_values:
154        return []
155    return [CALL_WITH_ARGUMENTS[value]
156            for value in CALL_WITH_VALUES
157            if extended_attribute_value_contains(call_with_values, value)]
158
159
160# [Conditional]
161def conditional_string(definition_or_member):
162    extended_attributes = definition_or_member.extended_attributes
163    if 'Conditional' not in extended_attributes:
164        return None
165    conditional = extended_attributes['Conditional']
166    for operator in '&|':
167        if operator in conditional:
168            conditions = conditional.split(operator)
169            operator_separator = ' %s%s ' % (operator, operator)
170            return operator_separator.join('ENABLE(%s)' % expression for expression in sorted(conditions))
171    return 'ENABLE(%s)' % conditional
172
173
174# [DeprecateAs]
175def deprecate_as(member):
176    extended_attributes = member.extended_attributes
177    if 'DeprecateAs' not in extended_attributes:
178        return None
179    includes.add('core/frame/UseCounter.h')
180    return extended_attributes['DeprecateAs']
181
182
183# [ImplementedAs]
184def cpp_name(definition_or_member):
185    extended_attributes = definition_or_member.extended_attributes
186    if 'ImplementedAs' not in extended_attributes:
187        return definition_or_member.name
188    return extended_attributes['ImplementedAs']
189
190
191# [MeasureAs]
192def measure_as(definition_or_member):
193    extended_attributes = definition_or_member.extended_attributes
194    if 'MeasureAs' not in extended_attributes:
195        return None
196    includes.add('core/frame/UseCounter.h')
197    return extended_attributes['MeasureAs']
198
199
200# [PerContextEnabled]
201def per_context_enabled_function_name(definition_or_member):
202    extended_attributes = definition_or_member.extended_attributes
203    if 'PerContextEnabled' not in extended_attributes:
204        return None
205    feature_name = extended_attributes['PerContextEnabled']
206    return 'ContextFeatures::%sEnabled' % uncapitalize(feature_name)
207
208
209# [RuntimeEnabled]
210def runtime_enabled_function_name(definition_or_member):
211    """Returns the name of the RuntimeEnabledFeatures function.
212
213    The returned function checks if a method/attribute is enabled.
214    Given extended attribute RuntimeEnabled=FeatureName, return:
215        RuntimeEnabledFeatures::{featureName}Enabled
216    """
217    extended_attributes = definition_or_member.extended_attributes
218    if 'RuntimeEnabled' not in extended_attributes:
219        return None
220    feature_name = extended_attributes['RuntimeEnabled']
221    return 'RuntimeEnabledFeatures::%sEnabled' % uncapitalize(feature_name)
222