OLD | NEW |
(Empty) | |
| 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 |
| 30 import struct |
| 31 |
| 32 from v8_utilities import generate_conditional_string, runtime_enable_function_na
me |
| 33 |
| 34 # WIP |
| 35 from code_generator_idl_reader import base_interface_name, inherits_interface, i
nterface_inherits_extended_attribute |
| 36 # from v8_includes import includes_for_type |
| 37 from v8_includes import * |
| 38 import v8_attributes |
| 39 import v8_functions |
| 40 import v8_constructors |
| 41 from v8_utilities import get_function_mandatory_parameters, get_feature_observat
ion_parameter, get_deprecation_notification_parameter |
| 42 import v8_special_accessors |
| 43 import v8_types |
| 44 # from v8_types import cpp_type, v8_type |
| 45 from v8_types import * |
| 46 from v8_utilities import implemented_as_cpp_name |
| 47 |
| 48 |
| 49 ################################################################################ |
| 50 # BRANCH |
| 51 ################################################################################ |
| 52 |
| 53 |
| 54 def generate_constants(interface): |
| 55 return [generate_constant(constant) for constant in interface.constants] |
| 56 |
| 57 |
| 58 def generate_constant(constant): |
| 59 # Extended Attributes: Conditional, DeprecateAs, EnabledAtRuntime, Reflect |
| 60 # FIXME: Conditional and DeprecateAs are only used in tests, so remove |
| 61 name = constant.extended_attributes.get('Reflect', constant.name) |
| 62 value_raw = constant.value |
| 63 # If the value we're dealing with is a hex literal, statically cast it to a |
| 64 # signed integer here, rather than dynamically casting via |
| 65 # static_cast<signed int> in the generated code. |
| 66 # FIXME: why are we casting to signed? |
| 67 # NodeFilter has unsigned 0xFFFFFFFF, which is converted to -1. |
| 68 # FIXME: is this necessary? Hex literals are valid C. |
| 69 # (only semantic difference is casting to signed) |
| 70 # FIXME: what about octal? decimal? |
| 71 # FIXME: what if we have a negative literal? |
| 72 # FIXME: BUG: Perl only checks '0x', not '0X', |
| 73 # but we have a test case using 0X. |
| 74 if value_raw.startswith('0x'): |
| 75 value = struct.unpack('i', struct.pack('I', int(value_raw, 16)))[0] |
| 76 else: |
| 77 value = value_raw |
| 78 |
| 79 constant_parameter = { |
| 80 'name': constant.name, |
| 81 'name_reflect': name, # FIXME: use name_reflect as correct 'name' |
| 82 'value': value, |
| 83 'value_raw': value_raw, |
| 84 # FIXME: remove conditional: only used in tests |
| 85 'conditional_string': generate_conditional_string(constant), |
| 86 'enabled_at_runtime': 'EnabledAtRuntime' in constant.extended_attributes
, |
| 87 'enable_function': runtime_enable_function_name(constant), |
| 88 } |
| 89 return constant_parameter |
| 90 |
| 91 |
| 92 ################################################################################ |
| 93 # WIP |
| 94 ################################################################################ |
| 95 |
| 96 |
| 97 def generate_implementation(interface): |
| 98 # __IMPL__ in Perl |
| 99 cpp_class_name = implemented_as_cpp_name(interface) |
| 100 v8_class_name = get_v8_class_name(interface) |
| 101 includes = [ |
| 102 'bindings/v8/V8Binding.h', |
| 103 'bindings/v8/V8DOMWrapper.h', |
| 104 'core/dom/ContextFeatures.h', |
| 105 'core/dom/Document.h', |
| 106 'RuntimeEnabledFeatures.h', |
| 107 'wtf/UnusedParam.h', |
| 108 'bindings/v8/V8DOMConfiguration.h', |
| 109 'core/platform/chromium/TraceEvent.h', |
| 110 ] |
| 111 |
| 112 # FIXME: is this only to determine has_callbacks? |
| 113 normal_functions = [] |
| 114 enabled_per_context_functions = [] # FIXME: unused |
| 115 for operation in interface.operations: |
| 116 if not operation.name: |
| 117 continue |
| 118 if 'EnabledPerContext' in operation.extended_attributes: |
| 119 enabled_per_context_functions.append(operation) |
| 120 else: |
| 121 normal_functions.append(operation) |
| 122 has_callbacks = any([ |
| 123 # Only one table entry is needed for overloaded methods: |
| 124 operation.overload_index <= 1 and |
| 125 # Don't put any nonstandard functions into this table: |
| 126 get_is_standard_function(interface, operation) |
| 127 for operation in normal_functions]) |
| 128 |
| 129 inherits_extended_attribute_active_dom_object = interface_inherits_extended_
attribute(interface, 'ActiveDOMObject') |
| 130 inherits_event_target = inherits_interface(interface, 'EventTarget') |
| 131 # has_attributes = bool(interface.attributes) # FIXME: unused |
| 132 cpp_class_name_as_parameter = get_native_type(interface.name, used_as_parame
ter=True) |
| 133 |
| 134 includes += get_includes_for_type(interface.name) |
| 135 |
| 136 if interface.name == 'ArrayBuffer' or is_typed_array_type(interface.name): |
| 137 includes.append('bindings/v8/custom/V8ArrayBufferCustom.h') |
| 138 |
| 139 attribute_parameters, attribute_includes = v8_attributes.generate_attributes
_wip(interface) |
| 140 includes += attribute_includes |
| 141 function_parameters, function_includes = v8_functions.generate_functions(int
erface) |
| 142 includes += function_includes |
| 143 constructor_parameters, constructor_includes = v8_constructors.generate_cons
tructor_contents(interface) |
| 144 includes += constructor_includes |
| 145 special_accessors_parameter, special_accessors_includes = v8_special_accesso
rs.get_special_accessors_parameter(interface) |
| 146 includes += special_accessors_includes |
| 147 feature_observation_parameter, feature_observation_includes = get_feature_ob
servation_parameter(interface) |
| 148 includes += feature_observation_includes |
| 149 deprecation_notification_parameter, deprecation_notification_includes = get_
deprecation_notification_parameter(interface) |
| 150 includes += deprecation_notification_includes |
| 151 template_parameters_for_create_wrapper, includes_for_create_wrapper = genera
te_to_v8_converters(interface, v8_class_name, cpp_class_name) |
| 152 includes += includes_for_create_wrapper |
| 153 |
| 154 if interface.parent: |
| 155 parent_class_name = 'V8' + interface.parent |
| 156 # print 'ADD H', interface.parent |
| 157 includes.append('V8%s.h' % interface.parent) |
| 158 parent_class_template = parent_class_name + '::GetTemplate(isolate, curr
entWorldType)' |
| 159 else: |
| 160 parent_class_name = '' |
| 161 parent_class_template = 'v8::Local<v8::FunctionTemplate>()' |
| 162 |
| 163 if interface.name == 'MessagePort': |
| 164 # MessagePort is handled like an active dom object even though it doesn'
t inherit |
| 165 # from ActiveDOMObject, so don't try to cast it to ActiveDOMObject. |
| 166 active_dom_object_return_value = '0' |
| 167 else: |
| 168 active_dom_object_return_value = 'toNative(object)' |
| 169 |
| 170 interface_length = get_interface_length(interface) |
| 171 |
| 172 is_reachable_method = interface.extended_attributes.get('GenerateIsReachable
') |
| 173 generate_opaque_root_for_gc = 'CustomIsReachable' not in interface.extended_
attributes |
| 174 if generate_opaque_root_for_gc and is_reachable_method: |
| 175 includes.append('bindings/v8/V8GCController.h') |
| 176 includes.append('core/dom/Element.h') |
| 177 |
| 178 number_of_normal_attributes = len([attribute for attribute in attribute_para
meters if attribute.get('is_normal')]) |
| 179 |
| 180 includes_set = set(includes) |
| 181 includes_set.discard(v8_class_name + '.h') |
| 182 includes = sorted(includes_set) |
| 183 template_parameters = { |
| 184 'interface_name': interface.name, |
| 185 'interface_length': interface_length, |
| 186 'needs_opaque_root_for_gc': needs_opaque_root_for_gc(interface), |
| 187 'generate_opaque_root_for_gc': generate_opaque_root_for_gc, |
| 188 'is_reachable_method': is_reachable_method, |
| 189 'inherits_extended_attribute_active_dom_object': inherits_extended_attri
bute_active_dom_object, |
| 190 'active_dom_object_return_value': active_dom_object_return_value, |
| 191 'inherits_event_target': inherits_event_target, |
| 192 'namespace_for_interface': 'WTF' if is_typed_array_type(interface.name)
else 'WebCore', |
| 193 ### only DOMException isException==True. TODO support exception |
| 194 # 'wrapper_type_prototype': interface.is_exception and 'WrapperTypeE
rrorPrototype' or 'WrapperTypeObjectPrototype', |
| 195 'wrapper_type_prototype': 'WrapperTypeObjectPrototype', |
| 196 'enabled_at_runtime': 'EnabledAtRuntime' in interface.extended_attribute
s, |
| 197 'enable_function': runtime_enable_function_name(interface), |
| 198 'configure_template_batched_attribute': v8_class_name + 'Attrs' if numbe
r_of_normal_attributes else '0', |
| 199 'configure_template_attribute_count': 'WTF_ARRAY_LENGTH(%sAttrs)' % v8_c
lass_name if number_of_normal_attributes else '0', |
| 200 'configure_template_batched_method': v8_class_name + 'Methods' if has_ca
llbacks else '0', |
| 201 'configure_template_method_count': 'WTF_ARRAY_LENGTH(%sMethods)' % v8_cl
ass_name if has_callbacks else '0', |
| 202 # FIXME: replace with conditional expressions |
| 203 'to_active_dom_object': v8_class_name + '::toActiveDOMObject' if inherit
s_extended_attribute_active_dom_object else '0', |
| 204 'to_event_target': v8_class_name + '::toEventTarget' if inherits_event_t
arget else '0', |
| 205 'root_for_gc': v8_class_name + '::opaqueRootForGC' if needs_opaque_root_
for_gc(interface) else '0', |
| 206 'check_security': interface.extended_attributes.get('CheckSecurity'), |
| 207 'parent_class_info': '&%s::info' % parent_class_name if parent_class_nam
e else '0', |
| 208 'parent_class_template': parent_class_template, |
| 209 'parent': interface.parent, |
| 210 'attributes': attribute_parameters, |
| 211 'functions': function_parameters, |
| 212 'function_callbacks': len([f for f in function_parameters if f.get('crea
te_callback')]), |
| 213 'cpp_includes': includes, |
| 214 'number_of_enabled_at_runtime_attributes': len([attribute for attribute
in attribute_parameters if attribute['enabled_at_runtime']]), |
| 215 'number_of_enabled_per_context_functions': len([function for function in
function_parameters if function['is_enabled_per_context_function']]), |
| 216 'number_of_normal_functions': len([function for function in function_par
ameters if function.get('is_normal_function')]), |
| 217 'number_of_normal_attributes': number_of_normal_attributes, |
| 218 'number_of_any_attributes': len([attribute for attribute in attribute_pa
rameters if attribute.get('type') == 'any']), |
| 219 'do_not_check_constants': 'DoNotCheckConstants' in interface.extended_at
tributes, |
| 220 'special_accessors': special_accessors_parameter, |
| 221 'custom_legacy_call': 'CustomLegacyCall' in interface.extended_attribute
s, |
| 222 } |
| 223 template_parameters.update(template_parameters_for_create_wrapper) |
| 224 template_parameters.update(constructor_parameters) |
| 225 template_parameters.update(feature_observation_parameter) |
| 226 template_parameters.update(deprecation_notification_parameter) |
| 227 return template_parameters |
| 228 |
| 229 |
| 230 def get_convert_to_v8_string_resource(attribute_or_parameter, native_type, varia
ble_name, native_value): |
| 231 # FIXME: unused |
| 232 if not native_type.startswith('V8StringResource'): |
| 233 raise Exception('Wrong native type passed: %s' % native_type) |
| 234 if attribute_or_parameter.data_type == 'DOMString' or is_enum_type(attribute
_or_parameter.data_type): |
| 235 return 'V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(%s, %s, %s);' % (native_typ
e, variable_name, native_value) |
| 236 # print '[get_convert_to_V8StringResource] not DOMString nor enum', native_t
ype, get_convert_to_V8StringResource, native_value |
| 237 return '%s %s(%s, true);' % (native_type, variable_name, native_value) |
| 238 |
| 239 |
| 240 def get_interface_length(interface): |
| 241 # The Web IDL specification states that Interface objects for interfaces MUS
T have a property named |
| 242 # 'length' that returns the length of the shortest argument list of the entr
ies in the effective |
| 243 # overload set for constructors. In other words, use the lowest number of ma
ndatory arguments among |
| 244 # all constructors. |
| 245 if is_constructor_template(interface, 'Event') or is_constructor_template(in
terface, 'TypedArray'): |
| 246 return 1 |
| 247 # FIXME: once generate constructors properly, replace with: |
| 248 # if not constructors: return 0 |
| 249 if all(extended_attribute not in interface.extended_attributes |
| 250 for extended_attribute in ['Constructor', 'CustomConstructor']): |
| 251 return 0 |
| 252 constructors = interface.constructors + interface.custom_constructors |
| 253 return min([get_function_mandatory_parameters(constructor) |
| 254 for constructor in constructors]) |
| 255 |
| 256 |
| 257 def generate_to_v8_converters(interface, v8_class_name, cpp_class_name): |
| 258 # print '[]', cpp_class_name |
| 259 includes = [] |
| 260 create_wrapper = not ('DoNotGenerateWrap' in interface.extended_attributes o
r 'DoNotGenerateToV8' in interface.extended_attributes) |
| 261 if not create_wrapper: |
| 262 return {}, includes |
| 263 |
| 264 includes = [ |
| 265 'bindings/v8/ScriptController.h', |
| 266 'core/page/Frame.h', |
| 267 ] |
| 268 # TODO make attribute instead of hard code |
| 269 if ('SVG' in v8_class_name or |
| 270 any([interface_inherits_extended_attribute(interface, attribute) |
| 271 for attribute in ['ActiveDOMObject', 'DependentLifetime', 'Generate
IsReachable', 'CustomIsReachable']])): |
| 272 wrapper_configuration = 'WrapperConfiguration::Dependent' |
| 273 else: |
| 274 wrapper_configuration = 'WrapperConfiguration::Independent' |
| 275 # Used in: C++ calls function f(PassRefPtr<XXX>* impl, ...) -> can be replac
ed to get_type_as_function_parameter(native_type) |
| 276 template_parameters = { |
| 277 'create_wrapper': create_wrapper, |
| 278 'wrapper_configuration': wrapper_configuration, |
| 279 # 'create_wrapper_argument_type': get_native_type(cpp_class_name, us
ed_as_parameter=True), |
| 280 'create_wrapper_argument_type': cpp_class_name, |
| 281 'base_interface_name': base_interface_name(interface), |
| 282 'inherit_document': inherits_interface(interface, 'Document'), |
| 283 'is_typed_array_type': is_typed_array_type(interface.name), |
| 284 } |
| 285 |
| 286 return template_parameters, includes |
OLD | NEW |