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 31 FIXME: Not currently used in build. 32 This is a rewrite of the Perl IDL compiler in Python, but is not complete. 33 Once it is complete, we will switch all IDL files over to Python at once. 34 Until then, please work on the Perl IDL compiler. 35 For details, see bug http://crbug.com/239771 36 """ 37 38 # FIXME: eliminate this file if possible 39 40 import re 41 42 from v8_globals import includes 43 import v8_types 44 45 ACRONYMS = ['CSS', 'HTML', 'IME', 'JS', 'SVG', 'URL', 'WOFF', 'XML', 'XSLT'] 46 47 48 # Extended attributes 49 def extended_attribute_value_contains(extended_attribute_value, value): 50 return (extended_attribute_value and 51 value in re.split('[|&]', extended_attribute_value)) 52 53 54 def 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 59 def 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 66 def 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 74 def strip_suffix(string, suffix): 75 if not suffix or not string.endswith(suffix): 76 return string 77 return string[:-len(suffix)] 78 79 80 def 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++ 93 def 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 100 def 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 106 def v8_class_name(interface): 107 return v8_types.v8_type(interface.name) 108 109 110 # [ActivityLogging] 111 def 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] 133 CALL_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 141 CALL_WITH_VALUES = [ 142 'ScriptState', 143 'ExecutionContext', 144 'ScriptArguments', 145 'ActiveWindow', 146 'FirstWindow', 147 ] 148 149 150 def 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] 161 def 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] 175 def 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] 184 def 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] 192 def 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] 201 def 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] 210 def 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