Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright (C) 2013 Google Inc. All rights reserved. | 1 # Copyright (C) 2013 Google Inc. All rights reserved. |
| 2 # | 2 # |
| 3 # Redistribution and use in source and binary forms, with or without | 3 # Redistribution and use in source and binary forms, with or without |
| 4 # modification, are permitted provided that the following conditions are | 4 # modification, are permitted provided that the following conditions are |
| 5 # met: | 5 # met: |
| 6 # | 6 # |
| 7 # * Redistributions of source code must retain the above copyright | 7 # * Redistributions of source code must retain the above copyright |
| 8 # notice, this list of conditions and the following disclaimer. | 8 # notice, this list of conditions and the following disclaimer. |
| 9 # * Redistributions in binary form must reproduce the above | 9 # * Redistributions in binary form must reproduce the above |
| 10 # copyright notice, this list of conditions and the following disclaimer | 10 # copyright notice, this list of conditions and the following disclaimer |
| 11 # in the documentation and/or other materials provided with the | 11 # in the documentation and/or other materials provided with the |
| 12 # distribution. | 12 # distribution. |
| 13 # * Neither the name of Google Inc. nor the names of its | 13 # * Neither the name of Google Inc. nor the names of its |
| 14 # contributors may be used to endorse or promote products derived from | 14 # contributors may be used to endorse or promote products derived from |
| 15 # this software without specific prior written permission. | 15 # this software without specific prior written permission. |
| 16 # | 16 # |
| 17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 18 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 28 | 28 |
| 29 """Generate Blink V8 bindings (.h and .cpp files). | 29 """ |
| 30 Generate Blink V8 bindings (.h and .cpp files). | |
| 30 | 31 |
| 31 Input: An object of class IdlDefinitions, containing an IDL interface X | 32 Input: An object of class IdlDefinitions, containing an IDL interface X |
| 32 Output: V8X.h and V8X.cpp | 33 Output: V8X.h and V8X.cpp |
| 33 | |
| 34 FIXME: Currently a stub, as part of landing the parser and code generator | |
| 35 incrementally. Only implements generation of dummy .cpp and .h files. | |
| 36 """ | 34 """ |
| 37 | 35 |
| 36 import os | |
| 38 import os.path | 37 import os.path |
|
Nils Barth (inactive)
2013/07/24 11:41:20
If you import os, you don't need to also import os
Nils Barth (inactive)
2013/07/25 03:30:54
For manipulating paths for C++ #include statements
| |
| 38 import sys | |
| 39 import re | |
| 40 | |
| 41 import idl_definitions | |
| 42 import idl_reader | |
| 43 | |
| 44 current_dir = os.path.dirname(os.path.realpath(__file__)) | |
| 45 # jinja2 is in chromium's third_party directory | |
| 46 sys.path.append(os.path.join(current_dir, *([os.pardir] * 4))) | |
|
Nils Barth (inactive)
2013/07/24 11:41:20
Slick!
Maybe a bit too slick (compared with just l
kojih
2013/07/25 09:08:37
I'll use code below from blink_idl_parser.py:
mod
| |
| 47 import jinja2 | |
| 48 | |
| 49 | |
| 50 def pathsplit(path): | |
| 51 dirs = [] | |
| 52 while True: | |
| 53 (dirname, basename) = os.path.split(path) | |
| 54 if basename == "": | |
| 55 break | |
| 56 dirs.append(basename) | |
|
do-not-use
2013/07/24 11:17:59
Or we could simply dir.insert(0, baseline) to avoi
kojih
2013/07/25 09:08:37
I'll use dir.insert(0, basename) here.
| |
| 57 path = dirname | |
| 58 dirs.reverse() | |
| 59 return dirs | |
|
do-not-use
2013/07/24 10:56:20
return reversed(dirs) ?
| |
| 60 | |
| 61 | |
| 62 def abs2rel(path, basedir): | |
|
Nils Barth (inactive)
2013/07/25 03:30:54
os.path.relpath
...or rather:
posixpath.relpath
..
kojih
2013/07/25 09:08:37
Oh thanks!
| |
| 63 path_dirs = pathsplit(os.path.abspath(path)) | |
| 64 basedir_dirs = pathsplit(os.path.abspath(basedir)) | |
| 65 common_dirs = 0 | |
| 66 for i in range(min(len(path_dirs), len(basedir_dirs))): | |
| 67 if path_dirs[i] != basedir_dirs[i]: | |
| 68 break | |
| 69 common_dirs += 1 | |
| 70 relpath = [] | |
|
Nils Barth (inactive)
2013/07/25 03:30:54
Naming-wise (if we still need this), relpath_dirs,
| |
| 71 for i in range(len(basedir_dirs) - common_dirs): | |
| 72 relpath.append("..") | |
|
Nils Barth (inactive)
2013/07/24 11:41:20
os.pardir instead of '..' ?
| |
| 73 relpath.extend(path_dirs[common_dirs:]) | |
| 74 return os.sep.join(relpath) | |
|
do-not-use
2013/07/24 10:56:20
Shouldn't this be '/'.join(relpath)? We don't want
| |
| 75 | |
| 76 | |
| 77 def get_path(dic, keys): | |
|
do-not-use
2013/07/24 10:56:20
This function is a bit obscure and does not appear
| |
| 78 node = dic | |
| 79 for key in keys: | |
| 80 if key not in node: | |
| 81 return None | |
| 82 node = node[key] | |
| 83 return node | |
| 84 | |
| 85 | |
| 86 def apply_template(path_to_template, params): | |
| 87 dirname, basename = os.path.split(path_to_template) | |
| 88 path_to_templates = os.path.join(current_dir, "templates") | |
| 89 jinja_env = jinja2.Environment(trim_blocks=True, loader=jinja2.FileSystemLoa der([dirname, path_to_templates])) | |
| 90 template = jinja_env.get_template(basename) | |
| 91 return template.render(params) | |
| 92 | |
| 93 | |
| 94 def create_arguments(arguments): | |
|
do-not-use
2013/07/24 11:17:59
something like create_arguments_string(arguments)
kojih
2013/07/25 09:08:37
ok.
| |
| 95 return ", ".join([argument for argument in arguments if argument]) | |
| 96 | |
| 97 | |
| 98 def get_v8_class_name(interface): | |
| 99 return "V8" + interface.name | |
| 100 | |
| 101 | |
| 102 def get_impl_name(interface_or_function): | |
| 103 implementedAs = interface_or_function.extended_attributes.get("ImplementedAs ") | |
| 104 if implementedAs is not None: | |
| 105 return implementedAs | |
| 106 return interface_or_function.name | |
| 107 | |
| 108 | |
| 109 def get_conditional_string(interface_or_attribute_or_operation): | |
| 110 conditional = interface_or_attribute_or_operation.extended_attributes.get("C onditional") | |
| 111 if conditional is None: | |
| 112 return "" | |
| 113 else: | |
| 114 operator = "" | |
| 115 if "&" in conditional: | |
| 116 operator = "&" | |
| 117 if "|" in conditional: | |
| 118 operator = "|" | |
| 119 if operator == "": | |
| 120 return "ENABLE(%s)" % conditional | |
| 121 else: | |
| 122 # Avoid duplicated conditions. | |
| 123 conditions = dict([(expression, True) for expression in conditional. split(operator)]) | |
|
do-not-use
2013/07/24 10:56:20
Can we use a set to avoid duplicated conditions?
kojih
2013/07/25 09:08:37
done.
| |
| 124 return (" %s%s " % (operator, operator)).join(["ENABLE(%s)" % expres sion for expression in sorted(conditions.keys())]) | |
| 125 | |
| 126 | |
| 127 def get_includes_for_type(data_type): | |
| 128 if skip_include_header(data_type): | |
| 129 return [] | |
| 130 includes = [] | |
| 131 if data_type == "EventListener": | |
| 132 includes.append("core/dom/EventListener.h") | |
| 133 elif data_type == "SerializedScriptValue": | |
| 134 includes.append("bindings/v8/SerializedScriptValue.h") | |
| 135 elif data_type == "any" or is_callback_function_type(data_type): | |
| 136 includes.append("bindings/v8/ScriptValue.h") | |
| 137 else: | |
| 138 includes.append("V8%s.h" % data_type) | |
| 139 return includes | |
| 140 | |
| 141 | |
| 142 def get_includes_for_parameter(parameter): | |
| 143 includes = [] | |
| 144 array_or_sequence_type = get_array_type(parameter.data_type) or get_sequence _type(parameter.data_type) | |
| 145 if array_or_sequence_type: | |
| 146 if is_ref_ptr_type(array_or_sequence_type): | |
| 147 includes += get_includes_for_type(array_or_sequence_type) | |
| 148 else: | |
| 149 includes += get_includes_for_type(parameter.data_type) | |
| 150 return includes | |
| 151 | |
| 152 | |
| 153 def link_overloaded_functions(interface): | |
| 154 name_to_operations = {} | |
| 155 for operation in interface.operations: | |
| 156 name = operation.name | |
| 157 if not name: | |
| 158 operation.overloads = [] | |
| 159 operation.overload_index = 0 | |
| 160 continue | |
| 161 if name not in name_to_operations: | |
|
do-not-use
2013/07/24 10:56:20
I believe you can write these 3 lines as one:
name
| |
| 162 name_to_operations[name] = [] | |
| 163 name_to_operations[name].append(operation) | |
| 164 operation.overloads = name_to_operations[name] | |
| 165 operation.overload_index = len(name_to_operations[name]) | |
|
do-not-use
2013/07/24 11:17:59
What is overload_index for? Seems it is just the l
kojih
2013/07/25 09:08:37
overload_index is identifier among set of overload
| |
| 166 | |
| 167 | |
| 168 def sort_and_remove_duplicate(includes): | |
| 169 return sorted(list(set(includes))) | |
| 170 | |
| 171 | |
| 172 def get_pass_owner_expression(data_type, expression): | |
| 173 if is_ref_ptr_type(data_type): | |
| 174 return expression + ".release()" | |
| 175 return expression | |
| 176 | |
| 177 | |
| 178 def get_convert_to_V8StringResource(attribute_or_parameter, native_type, native_ variable_name, native_value): | |
| 179 if not re.match("^V8StringResource", native_type): | |
| 180 raise Exception("Wrong native data_type passed: %s" % native_type) | |
| 181 if attribute_or_parameter.data_type == "DOMString" or is_enum_type(attribute _or_parameter.data_type): | |
| 182 return "V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(%s, %s, %s);" % (native_typ e, native_variable_name, native_value) | |
| 183 else: | |
| 184 return "%s %s(%s, true);" % (native_type, native_variable_name, native_v alue) | |
| 185 | |
| 186 # IDL data_type: [element's C++ data_type, V8 data_type] | |
| 187 typed_arrays = { | |
| 188 "ArrayBuffer": [], | |
| 189 "ArrayBufferView": [], | |
| 190 "Uint8Array": ["unsigned char", "v8::kExternalUnsignedByteArray"], | |
|
do-not-use
2013/07/24 10:56:20
Seems like we could use tuples instead of lists?
Nils Barth (inactive)
2013/07/25 03:30:54
Good point.
We could even use dictionaries or obje
kojih
2013/07/25 09:08:37
I'll use class NativeTypeAndJSType
| |
| 191 "Uint8ClampedArray": ["unsigned char", "v8::kExternalPixelArray"], | |
| 192 "Uint16Array": ["unsigned short", "v8::kExternalUnsignedShortArray"], | |
| 193 "Uint32Array": ["unsigned int", "v8::kExternalUnsignedIntArray"], | |
| 194 "Int8Array": ["signed char", "v8::kExternalByteArray"], | |
| 195 "Int16Array": ["short", "v8::kExternalShortArray"], | |
| 196 "Int32Array": ["int", "v8::kExternalIntArray"], | |
| 197 "Float32Array": ["float", "v8::kExternalFloatArray"], | |
| 198 "Float64Array": ["double", "v8::kExternalDoubleArray"], | |
| 199 } | |
| 200 | |
| 201 primitive_types = { | |
|
do-not-use
2013/07/24 10:56:20
Maybe we can use a set? We don't really need the a
kojih
2013/07/25 09:08:37
done.
| |
| 202 "boolean": True, | |
| 203 "void": True, | |
| 204 "Date": True, | |
| 205 "byte": True, | |
| 206 "octet": True, | |
| 207 "short": True, | |
| 208 "long": True, | |
| 209 "long long": True, | |
| 210 "unsigned short": True, | |
| 211 "unsigned long": True, | |
| 212 "unsigned long long": True, | |
| 213 "float": True, | |
| 214 "double": True, | |
| 215 } | |
| 216 | |
| 217 enum_types = { | |
|
Nils Barth (inactive)
2013/07/25 03:30:54
enum_types and callback_function_types
should prop
kojih
2013/07/25 09:08:37
moved to CodeGeneratorV8.
| |
| 218 } | |
| 219 | |
| 220 callback_function_types = { | |
| 221 } | |
| 222 | |
| 223 non_wrapper_types = { | |
|
do-not-use
2013/07/24 10:56:20
Ditto.
| |
| 224 "CompareHow": True, | |
| 225 "DOMTimeStamp": True, | |
| 226 "Dictionary": True, | |
| 227 "EventListener": True, | |
| 228 "MediaQueryListListener": True, | |
| 229 "NodeFilter": True, | |
| 230 "SerializedScriptValue": True, | |
| 231 "any": True, | |
| 232 } | |
| 233 | |
| 234 dom_node_types = { | |
|
do-not-use
2013/07/24 10:56:20
Ditto.
| |
| 235 "Attr": True, | |
| 236 "CDATASection": True, | |
| 237 "CharacterData": True, | |
| 238 "Comment": True, | |
| 239 "Document": True, | |
| 240 "DocumentFragment": True, | |
| 241 "DocumentType": True, | |
| 242 "Element": True, | |
| 243 "Entity": True, | |
| 244 "HTMLDocument": True, | |
| 245 "Node": True, | |
| 246 "Notation": True, | |
| 247 "ProcessingInstruction": True, | |
| 248 "ShadowRoot": True, | |
| 249 "SVGDocument": True, | |
| 250 "Text": True, | |
| 251 "TestNode": True, | |
| 252 } | |
| 253 | |
| 254 | |
| 255 def get_sequence_type(data_type): | |
| 256 matched = re.match("^sequence<([\w\d_\s]+)>.*", data_type) | |
|
do-not-use
2013/07/24 10:56:20
Why do we accept whitespace in the sequence type?
Nils Barth (inactive)
2013/07/24 11:41:20
You need to use raw strings for regexes with backs
kojih
2013/07/25 09:08:37
whitespace is necessary to deal with "sequence<uns
kojih
2013/07/25 09:08:37
done.
| |
| 257 if matched: | |
| 258 return matched.group(1) | |
| 259 return "" | |
|
do-not-use
2013/07/24 10:56:20
Why not return None?
| |
| 260 | |
| 261 | |
| 262 def get_array_type(data_type): | |
| 263 matched = re.match("^([\w\d_\s]+)\[\]", data_type) | |
|
do-not-use
2013/07/24 10:56:20
White space in array type?
| |
| 264 if matched: | |
| 265 return matched.group(1) | |
| 266 return "" | |
|
do-not-use
2013/07/24 10:56:20
Ditto.
| |
| 267 | |
| 268 | |
| 269 def is_wrapper_type(data_type): | |
| 270 if is_union_type(data_type): | |
| 271 return False | |
| 272 if get_array_type(data_type): | |
| 273 return False | |
| 274 if get_sequence_type(data_type): | |
| 275 return False | |
| 276 if is_callback_function_type(data_type): | |
| 277 return False | |
| 278 if is_enum_type(data_type): | |
| 279 return False | |
| 280 if is_primitive_type(data_type): | |
| 281 return False | |
| 282 if data_type == "DOMString": | |
| 283 return False | |
|
Nils Barth (inactive)
2013/07/24 11:41:20
This long string of if's would be clearer as a sin
kojih
2013/07/25 09:08:37
ok.
| |
| 284 return not non_wrapper_types.get(data_type) | |
| 285 | |
| 286 | |
| 287 def is_typed_array_type(data_type): | |
| 288 return data_type in typed_arrays | |
| 289 | |
| 290 | |
| 291 def is_ref_ptr_type(data_type): | |
|
Nils Barth (inactive)
2013/07/24 11:41:20
Ditto re: boolean expression
| |
| 292 if is_union_type(data_type): | |
| 293 return False | |
| 294 if data_type == "any" or data_type == "DOMString": | |
| 295 return False | |
| 296 if is_primitive_type(data_type): | |
| 297 return False | |
| 298 if get_array_type(data_type): | |
| 299 return False | |
| 300 if get_sequence_type(data_type): | |
| 301 return False | |
| 302 if is_callback_function_type(data_type): | |
| 303 return False | |
| 304 if is_enum_type(data_type): | |
| 305 return False | |
| 306 return True | |
| 307 | |
| 308 | |
| 309 def is_primitive_type(data_type): | |
| 310 if data_type in primitive_types: | |
|
Nils Barth (inactive)
2013/07/24 11:41:20
return data_type in primitive_types
| |
| 311 return True | |
| 312 return False | |
| 313 | |
| 314 | |
| 315 def is_enum_type(data_type): | |
|
Nils Barth (inactive)
2013/07/24 11:41:20
Ditto.
| |
| 316 if data_type in enum_types: | |
| 317 return True | |
| 318 return False | |
| 319 | |
| 320 | |
| 321 def is_callback_function_type(data_type): | |
|
Nils Barth (inactive)
2013/07/24 11:41:20
Ditto.
| |
| 322 if data_type in callback_function_types: | |
| 323 return True | |
| 324 return False | |
| 325 | |
| 326 | |
| 327 def is_union_type(data_type): | |
|
Nils Barth (inactive)
2013/07/24 11:41:20
Ditto.
| |
| 328 if isinstance(data_type, idl_definitions.IdlUnionType): | |
| 329 return True | |
| 330 return False | |
| 331 | |
| 332 | |
| 333 def skip_include_header(data_type): | |
|
Nils Barth (inactive)
2013/07/24 11:41:20
Ditto.
| |
| 334 if is_primitive_type(data_type): | |
| 335 return True | |
| 336 if is_enum_type(data_type): | |
| 337 return True | |
| 338 if is_callback_function_type(data_type): | |
| 339 return True | |
| 340 if data_type == "DOMString": | |
| 341 return True | |
| 342 return False | |
| 343 | |
| 344 | |
| 345 class code_generator_v8: | |
|
Nils Barth (inactive)
2013/07/25 03:30:54
Class names are in CamelCase:
http://www.chromium.
| |
| 346 def __init__(self, definitions, interface_name, output_directory, idl_direct ories, generate_h=True, generate_cpp=True, verbose=False): | |
| 347 global enum_types | |
| 348 global callback_function_types | |
| 349 self.idl_definitions = definitions | |
| 350 self.interface_name = interface_name | |
| 351 self.idl_directories = idl_directories | |
| 352 self.idl_files = {} | |
| 353 self.output_directory = output_directory | |
| 354 self.generate_h = generate_h | |
| 355 self.generate_cpp = generate_cpp | |
| 356 self.verbose = verbose | |
| 357 self.header = "" | |
| 358 self.implementation = "" | |
| 359 self.cached_interfaces = {} | |
| 360 self.common_template_parameters = {} | |
| 361 self.interface = None | |
| 362 | |
| 363 enum_types = dict([[enum.name, enum.values] for enum in self.idl_definit ions.enumerations.values()]) | |
| 364 callback_function_types = self.idl_definitions.callback_functions | |
| 365 self.prepare_idl_files() | |
| 366 | |
| 367 def prepare_idl_files(self): | |
| 368 directories = [os.getcwd() + os.sep + directory for directory in self.id l_directories] | |
| 369 directories = [path for path in directories if os.path.isdir(path)] | |
| 370 directories.append(".") | |
| 371 for directory in directories: | |
| 372 for root, _, filenames in os.walk(directory): | |
| 373 for filename in filenames: | |
| 374 basename, ext = os.path.splitext(filename) | |
| 375 if ext == ".idl": | |
| 376 fullpath = root + os.sep + filename | |
|
do-not-use
2013/07/24 10:56:20
could use os.path.join()
| |
| 377 self.idl_files[basename] = fullpath | |
| 378 | |
| 379 def idl_file_for_interface(self, interface_name): | |
| 380 return self.idl_files.get(interface_name) | |
| 381 | |
| 382 def parse_interface(self, interface_name): | |
| 383 if interface_name in self.cached_interfaces: | |
| 384 return self.cached_interfaces[interface_name] | |
| 385 | |
| 386 # Step #1: Find the IDL file associated with 'interface' | |
| 387 filename = self.idl_file_for_interface(interface_name) | |
| 388 if filename is None: | |
|
Nils Barth (inactive)
2013/07/24 11:41:20
'if not filename' is preferred
(we're not distingu
| |
| 389 raise Exception("Could NOT find IDL file for interface \"%s\"" % int erface_name) | |
| 390 | |
| 391 if self.verbose: | |
| 392 print " | |> Parsing parent IDL \"%s\" for interface \"%s\"" % (f ilename, interface_name) | |
| 393 | |
| 394 # Step #2: Parse the found IDL file (in quiet mode). | |
| 395 definitions = idl_reader.read_idl_file(filename) | |
| 396 for interface in definitions.interfaces.values(): | |
| 397 if interface.name == interface_name or interface.is_partial: | |
| 398 self.cached_interfaces[interface_name] = interface | |
| 399 return interface | |
| 400 | |
| 401 raise Exception("Could NOT find interface definition for %s in %s" % (in terface_name, filename)) | |
| 402 | |
| 403 def get_callback_parameter_declaration(self, operation): | |
| 404 parameters = ["%s %s" % (self.get_native_type(parameter.data_type, used_ as_parameter=True, called_by_webcore=True), parameter.name) for parameter in ope ration.arguments] | |
| 405 return ", ".join(parameters) | |
|
do-not-use
2013/07/24 11:17:59
You could reuse create_arguments()
| |
| 406 | |
| 407 def get_js_value_to_native_statement(self, data_type, extended_attributes, j s_value, variable_name, isolate): | |
| 408 native_type = self.get_native_type(data_type, extended_attributes=extend ed_attributes, used_to_assign_js_value=True) | |
| 409 if data_type == "unsigned long" and "IsIndex" in extended_attributes: | |
| 410 # Special-case index arguments because we need to check that they ar en't < 0. | |
| 411 native_type = "int" | |
| 412 native_value, includes = self.__get_js_value_to_native(data_type, extend ed_attributes, js_value, isolate) | |
| 413 code = "" | |
| 414 if data_type == "DOMString" or is_enum_type(data_type): | |
| 415 if not re.search("^V8StringResource", native_type): | |
| 416 raise Exception("Wrong native data_type passed: " + native_type) | |
| 417 code = "V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(%s, %s, %s);" % (native _type, variable_name, native_value) | |
| 418 elif "EnforceRange" in extended_attributes: | |
| 419 code = "V8TRYCATCH_WITH_TYPECHECK_VOID(%s, %s, %s, %s);" % (native_t ype, variable_name, native_value, isolate) | |
| 420 else: | |
| 421 code = "V8TRYCATCH_VOID(%s, %s, %s);" % (native_type, variable_name, native_value) | |
| 422 return code, includes | |
| 423 | |
| 424 def __get_js_value_to_native(self, data_type, extended_attributes, js_value, isolate): | |
| 425 """ | |
| 426 @return native_expression, additional_includes | |
| 427 """ | |
| 428 int_conversion = "EnforceRange" in extended_attributes and "EnforceRange " or "NormalConversion" | |
| 429 includes = [] | |
| 430 | |
| 431 if data_type == "boolean": | |
| 432 return "%s->BooleanValue()" % js_value, includes | |
| 433 if data_type == "float" or data_type == "double": | |
| 434 return "static_cast<%s>(%s->NumberValue())" % (data_type, js_value), includes | |
| 435 | |
| 436 arguments = [js_value] | |
| 437 if int_conversion != "NormalConversion": | |
| 438 arguments.append(int_conversion) | |
| 439 arguments.append("ok") | |
| 440 arguments_string = ", ".join(arguments) | |
|
do-not-use
2013/07/24 11:17:59
You could reuse create_arguments()
| |
| 441 | |
| 442 if data_type == "byte": | |
| 443 return "toInt8(%s)" % arguments_string, includes | |
| 444 if data_type == "octet": | |
| 445 return "toUInt8(%s)" % arguments_string, includes | |
| 446 if data_type == "long" or data_type == "short": | |
| 447 return "toInt32(%s)" % arguments_string, includes | |
| 448 if data_type == "unsigned long" or data_type == "unsigned short": | |
| 449 return "toUInt32(%s)" % arguments_string, includes | |
| 450 if data_type == "long long": | |
| 451 return "toInt64(%s)" % arguments_string, includes | |
| 452 if data_type == "unsigned long long": | |
| 453 return "toUInt64(%s)" % arguments_string, includes | |
| 454 if data_type == "CompareHow": | |
| 455 return "static_cast<Range::CompareHow>(%s->Int32Value())" % js_value , includes | |
| 456 if data_type == "Date": | |
| 457 return "toWebCoreDate(%s)" % js_value, includes | |
| 458 if data_type == "DOMStringList": | |
| 459 return "toDOMStringList(%s, %s)" % (js_value, isolate), includes | |
| 460 if data_type == "DOMString" or is_enum_type(data_type): | |
| 461 return js_value, includes | |
| 462 if data_type == "SerializedScriptValue": | |
| 463 includes.append("bindings/v8/SerializedScriptValue.h") | |
| 464 return "SerializedScriptValue::create(%s, %s)" % (js_value, isolate) , includes | |
| 465 if data_type == "Dictionary": | |
| 466 includes.append("bindings/v8/Dictionary.h") | |
| 467 return "Dictionary(%s, %s)" % (js_value, isolate), includes | |
| 468 if data_type == "any" or is_callback_function_type(data_type): | |
| 469 includes.append("bindings/v8/ScriptValue.h") | |
| 470 return "ScriptValue(%s)" % js_value, includes | |
| 471 if data_type == "NodeFilter": | |
| 472 return "toNodeFilter(%s)" % js_value, includes | |
| 473 if data_type == "MediaQueryListListener": | |
| 474 includes.append("core/css/MediaQueryListListener.h") | |
| 475 return "MediaQueryListListener::create(%s)" % js_value, includes | |
| 476 if data_type == "EventTarget": | |
| 477 return "V8DOMWrapper::isDOMWrapper(%s) ? toWrapperTypeInfo(v8::Handl e<v8::Object>::Cast(%s))->toEventTarget(v8::Handle<v8::Object>::Cast(%s)) : 0" % (js_value, js_value, js_value), includes | |
| 478 if data_type == "ArrayBuffer": | |
| 479 includes += get_includes_for_type(data_type) | |
| 480 return "$value->IsArrayBuffer() ? V8ArrayBuffer::toNative(v8::Handle <v8::ArrayBuffer>::Cast(%s)) : 0" % js_value, includes | |
| 481 if data_type == "XPathNSResolver": | |
| 482 return "toXPathNSResolver(%s, %s)" % (js_value, isolate), includes | |
| 483 | |
| 484 array_or_sequence_type = get_array_type(data_type) or get_sequence_type( data_type) | |
| 485 if array_or_sequence_type: | |
| 486 if is_ref_ptr_type(array_or_sequence_type): | |
| 487 includes.append("V8%s.h" % array_or_sequence_type) | |
| 488 return "(toRefPtrNativeArray<%s, V8%s>(%s, %s))" % (array_or_seq uence_type, array_or_sequence_type, js_value, isolate), includes | |
| 489 return "toNativeArray<%s>(%s)" % (self.get_native_type(array_or_sequ ence_type), js_value), includes | |
| 490 | |
| 491 includes += get_includes_for_type(data_type) | |
| 492 includes.append("V8%s.h" % data_type) | |
| 493 return "V8%s::HasInstance(%s, %s, worldType(%s)) ? V8%s::toNative(v8::Ha ndle<v8::Object>::Cast(%s)) : 0" % (data_type, js_value, isolate, isolate, data_ type, js_value), includes | |
| 494 | |
| 495 def get_native_to_js_value_statement(self, data_type, extended_attributes, n ative_value, \ | |
| 496 receiver="", creation_context="", isolate="", cal lback_info="", \ | |
| 497 script_wrappable="", for_main_world_suffix="", \ | |
| 498 indent="", used_as_return_value=False): | |
| 499 """ | |
| 500 Create statement which convert native(C++) value into JS value. | |
| 501 | |
| 502 @param[in] data_type IDL data_type | |
| 503 @param[in] extended_attributes | |
| 504 @param[in] native_value e.g. "imp->getImte(index)" | |
| 505 @param[in] indent | |
| 506 @param[in] receiver "%s" will be replaced with JS value. to return something, use used_as_return_value=True | |
| 507 @param[in] creation_context | |
| 508 @param[in] isolate | |
| 509 @param[in] callback_info | |
| 510 @param[in] script_wrappable | |
| 511 @param[in] for_main_world_suffix | |
| 512 @param[in] used_as_return_value | |
| 513 """ | |
| 514 def create_statement(receiver, js_value): | |
| 515 if "%s" in receiver: | |
| 516 return receiver % js_value | |
| 517 return receiver | |
| 518 | |
| 519 def create_statements(receiver, js_value): | |
| 520 if isinstance(receiver, str): | |
| 521 return create_statement(receiver, js_value) | |
| 522 if isinstance(receiver, list): | |
| 523 return "\n".join([create_statement(each_receiver, js_value) for each_receiver in receiver]) | |
| 524 raise Exception("receiver should be string or list") | |
| 525 | |
| 526 if not isolate: | |
| 527 raise Exception("An Isolate is mandatory for native value => JS valu e conversion.") | |
| 528 | |
| 529 includes = [] | |
| 530 | |
| 531 if is_union_type(data_type): | |
| 532 codes = [] | |
| 533 for i, union_member_type in enumerate(data_type.union_member_types): | |
| 534 union_member_number = i | |
| 535 union_member_variable = "%s%d" % (native_value, union_member_num ber) | |
| 536 union_member_enabled_variable = "%s%dEnabled" % (native_value, u nion_member_number) | |
| 537 union_member_native_value = get_pass_owner_expression(union_memb er_type, union_member_variable) | |
| 538 return_js_value_code, union_member_includes = self.get_native_to _js_value_statement(union_member_type, extended_attributes, union_member_native_ value, \ | |
| 539 receiver=receiver, creation_context=creation_cont ext, isolate=isolate, callback_info=callback_info, \ | |
| 540 script_wrappable=script_wrappable, for_main_world _suffix=for_main_world_suffix, \ | |
| 541 indent=indent + indent, used_as_return_value=used _as_return_value) | |
| 542 includes += union_member_includes | |
| 543 code = "" | |
| 544 if used_as_return_value: | |
| 545 code += indent + "if (%s) {\n" % union_member_enabled_variab le | |
| 546 code += indent + indent + return_js_value_code + "\n" | |
| 547 code += indent + indent + "return;\n" | |
| 548 code += indent + "}\n" | |
| 549 else: | |
| 550 code += indent + "if (%s) {\n" % union_member_enabled_variab le | |
| 551 code += return_js_value_code + "\n" | |
| 552 codes.append(code) | |
| 553 return "\n".join(codes), includes | |
| 554 | |
| 555 native_type = self.get_native_type(data_type) | |
| 556 | |
| 557 if data_type == "boolean": | |
| 558 if used_as_return_value: | |
| 559 receiver = ["%s;"] | |
| 560 return create_statements(receiver, "v8SetReturnValueBool(%s, %s) " % (callback_info, native_value)), includes | |
| 561 return create_statements(receiver, "v8Boolean(%s, %s)" % (native_val ue, isolate)), includes | |
| 562 | |
| 563 if data_type == "void": | |
| 564 if used_as_return_value: | |
| 565 return "", includes | |
| 566 return create_statements(receiver, "v8Undefined()"), includes | |
| 567 | |
| 568 # HTML5 says that unsigned reflected attributes should be in the range | |
| 569 # [0, 2^31). When a value isn't in this range, a default value (or 0) | |
| 570 # should be returned instead. | |
|
Nils Barth (inactive)
2013/07/24 11:41:20
Spec link?
kojih
2013/07/25 09:08:37
It seems:
http://www.whatwg.org/specs/web-apps/cur
| |
| 571 if "Reflect" in extended_attributes and (data_type == "unsigned long" or data_type == "unsigned short"): | |
| 572 native_value = native_value.replace("getUnsignedIntegralAttribute", "getIntegralAttribute") | |
| 573 if used_as_return_value: | |
| 574 receiver = ["%s;"] | |
| 575 return create_statements(receiver, "v8SetReturnValueUnsigned(%s, std::max(0, %s))" % (callback_info, native_value)), includes | |
| 576 return create_statements(receiver, "v8::Integer::NewFromUnsigned(std ::max(0, %s), %s);" % (native_value, isolate)), includes | |
| 577 | |
| 578 if native_type == "int": | |
| 579 if used_as_return_value: | |
| 580 receiver = ["%s;"] | |
| 581 return create_statements(receiver, "v8SetReturnValueInt(%s, %s)" % (callback_info, native_value)), includes | |
| 582 return create_statements(receiver, "v8::Integer::New(%s, %s)" % (nat ive_value, isolate)), includes | |
| 583 | |
| 584 if native_type == "unsigned": | |
| 585 if used_as_return_value: | |
| 586 receiver = ["%s;"] | |
| 587 return create_statements(receiver, "v8SetReturnValueUnsigned(%s, %s)" % (callback_info, native_value)), includes | |
| 588 return create_statements(receiver, "v8::Integer::NewFromUnsigned(%s, %s)" % (native_value, isolate)), includes | |
| 589 | |
| 590 if data_type == "Date": | |
| 591 if used_as_return_value: | |
| 592 receiver = ["v8SetReturnValue(%s, %%s);" % callback_info] | |
| 593 return create_statements(receiver, "v8DateOrNull(%s, %s)" % (native_ value, isolate)), includes | |
| 594 | |
| 595 # long long and unsigned long long are not representable in ECMAScript. | |
| 596 if data_type == "long long" or data_type == "unsigned long long" or data _type == "DOMTimeStamp": | |
| 597 if used_as_return_value: | |
| 598 receiver = ["%s;"] | |
| 599 return create_statements(receiver, "v8SetReturnValue(%s, static_ cast<double>(%s))" % (callback_info, native_value)), includes | |
| 600 return create_statements(receiver, "v8::Number::New(static_cast<doub le>(%s))" % native_value), includes | |
| 601 | |
| 602 if is_primitive_type(data_type): | |
| 603 if not (data_type == "float" or data_type == "double"): | |
| 604 raise Exception("unexpected data_type %s" % data_type) | |
| 605 if used_as_return_value: | |
| 606 receiver = ["%s;"] | |
| 607 return create_statements(receiver, "v8SetReturnValue(%s, %s)" % (callback_info, native_value)), includes | |
| 608 return create_statements(receiver, "v8::Number::New(%s)" % native_va lue), includes | |
| 609 | |
| 610 if native_type == "ScriptValue": | |
| 611 if used_as_return_value: | |
| 612 receiver = ["v8SetReturnValue(%s, %%s);" % callback_info] | |
| 613 js_value = "%s.v8Value()" % native_value | |
| 614 return create_statements(receiver, js_value), includes | |
| 615 | |
| 616 if data_type == "DOMString" or is_enum_type(data_type): | |
| 617 conversion = extended_attributes.get("TreatReturnedNullStringAs") | |
| 618 js_value = "" | |
| 619 function_suffix = "" | |
| 620 arguments = create_arguments([native_value, isolate]) | |
| 621 if conversion is None: | |
| 622 js_value = "v8String(%s)" % arguments | |
| 623 elif conversion == "Null": | |
| 624 js_value = "v8StringOrNull(%s)" % arguments | |
| 625 function_suffix = "OrNull" | |
| 626 elif conversion == "Undefined": | |
| 627 js_value = "v8StringOrUndefined(%s)" % arguments | |
| 628 function_suffix = "OrUndefined" | |
| 629 else: | |
| 630 raise Exception("Unknown value for TreatReturnedNullStringAs ext ended attribute") | |
| 631 | |
| 632 if used_as_return_value: | |
| 633 receiver = ["v8SetReturnValueString%s(%s, %%s, %s);" % (function _suffix, callback_info, isolate)] | |
| 634 return create_statements(receiver, native_value), includes | |
| 635 return create_statements(receiver, js_value), includes | |
| 636 | |
| 637 array_or_sequence_type = get_array_type(data_type) or get_sequence_type( data_type) | |
| 638 if array_or_sequence_type: | |
| 639 if is_ref_ptr_type(array_or_sequence_type): | |
| 640 includes += get_includes_for_type(array_or_sequence_type) | |
| 641 if used_as_return_value: | |
| 642 receiver = ["v8SetReturnValue(%s, %%s);" % callback_info] | |
| 643 return create_statements(receiver, "v8Array(%s, %s)" % (native_value , isolate)), includes | |
| 644 | |
| 645 includes += get_includes_for_type(data_type) | |
| 646 | |
| 647 if data_type == "SerializedScriptValue": | |
| 648 includes.append("%s.h" % data_type) | |
| 649 if used_as_return_value: | |
| 650 receiver = ["v8SetReturnValue(%s, %%s);" % callback_info] | |
| 651 js_value = "%s ? %s->deserialize() : v8::Handle<v8::Value>(v8::Null( %s))" % (native_value, native_value, isolate) | |
| 652 return create_statements(receiver, js_value), includes | |
| 653 | |
| 654 includes.append("wtf/RefPtr.h") | |
| 655 includes.append("wtf/GetPtr.h") | |
| 656 | |
| 657 if used_as_return_value: | |
| 658 receiver = ["v8SetReturnValue(%s, %%s);" % callback_info] | |
| 659 | |
| 660 if script_wrappable: | |
| 661 # FIXME: Use safe handles | |
| 662 if for_main_world_suffix == "ForMainWorld": | |
| 663 return create_statements(receiver, "toV8ForMainWorld(%s, %s.Hold er(), %s.GetIsolate())" % (native_value, callback_info, callback_info)), include s | |
| 664 return create_statements(receiver, "toV8Fast(%s, %s, %s)" % (native_ value, callback_info, script_wrappable)), includes | |
| 665 | |
| 666 # FIXME: Use safe handles | |
| 667 return create_statements(receiver, "toV8(%s, %s, %s)" % (native_value, c reation_context, isolate)), includes | |
| 668 | |
| 669 def get_native_type(self, data_type, called_by_webcore=False, used_as_parame ter=False, used_to_assign_js_value=False, extended_attributes=None): | |
| 670 """ | |
| 671 Return native data_type corresponds to IDL data_type. | |
| 672 @param[in] data_type ... IDL data_type | |
| 673 @param[in] called_by_webcore | |
| 674 @param[in] used_as_parameter | |
| 675 """ | |
| 676 if extended_attributes is None: | |
| 677 extended_attributes = {} | |
| 678 if data_type == "float": | |
| 679 return "float" | |
|
Nils Barth (inactive)
2013/07/24 11:41:20
How about:
if data_type in ['float', 'double', 'lo
kojih
2013/07/25 09:08:37
ok. later.
| |
| 680 if data_type == "double": | |
| 681 return "double" | |
| 682 if data_type == "int" or data_type == "long" or data_type == "short" or data_type == "byte": | |
| 683 return "int" | |
|
Nils Barth (inactive)
2013/07/24 11:41:20
How about:
if data_type in ['int', 'long', 'short'
| |
| 684 if data_type == "unsigned long" or data_type == "unsigned int" or data_t ype == "unsigned short" or data_type == "octet": | |
| 685 return "unsigned" | |
| 686 if data_type == "long long": | |
| 687 return "long long" | |
| 688 if data_type == "unsigned long long": | |
| 689 return "unsigned long long" | |
| 690 if data_type == "boolean": | |
| 691 return "bool" | |
| 692 if data_type == "DOMString" or is_enum_type(data_type): | |
| 693 if used_to_assign_js_value: | |
| 694 # FIXME: This implements [TreatNullAs=NullString] and [TreatUnde finedAs=NullString], | |
| 695 # but the Web IDL spec requires [TreatNullAs=EmptyString] and [T reatUndefinedAs=EmptyString]. | |
| 696 mode = "" | |
| 697 if extended_attributes.get("TreatNullAs") == "NullString" and ex tended_attributes.get("TreatUndefinedAs") == "NullString": | |
| 698 mode = "WithUndefinedOrNullCheck" | |
| 699 elif extended_attributes.get("TreatNullAs") == "NullString" or " Reflect" in extended_attributes: | |
| 700 mode = "WithNullCheck" | |
| 701 # FIXME: Add the case for 'elsif ($attributeOrParameter->extende dAttributes->{"TreatUndefinedAs"} and $attributeOrParameter->extendedAttributes- >{"TreatUndefinedAs"} eq "NullString"))'. | |
| 702 return "V8StringResource<%s>" % mode | |
| 703 if called_by_webcore: | |
| 704 return "const String&" | |
| 705 return "String" | |
| 706 | |
| 707 # FIXME: remove this | |
| 708 adhoc_rules = { | |
| 709 "CompareHow": "Range::CompareHow", | |
| 710 "DOMTimeStamp": "DOMTimeStamp", | |
| 711 "Date": "double", | |
| 712 "Dictionary": "Dictionary", | |
| 713 "DOMStringList": "RefPtr<DOMStringList>", | |
| 714 "MediaQueryListListener": "RefPtr<MediaQueryListListener>", | |
| 715 "NodeFilter": "RefPtr<NodeFilter>", | |
| 716 "SerializedScriptValue": "RefPtr<SerializedScriptValue>", | |
| 717 "XPathNSResolver": "RefPtr<XPathNSResolver>", | |
| 718 } | |
| 719 if data_type in adhoc_rules: | |
| 720 if used_as_parameter: | |
| 721 return adhoc_rules[data_type].replace("RefPtr", "PassRefPtr") | |
| 722 return adhoc_rules[data_type] | |
| 723 if data_type == "any" or is_callback_function_type(data_type): | |
| 724 return "ScriptValue" | |
| 725 | |
| 726 if is_union_type(data_type): | |
| 727 raise Exception("UnionType is not supported") | |
| 728 | |
| 729 if data_type == "ArrayBuffer": | |
| 730 if used_as_parameter: | |
| 731 return "ArrayBuffer*" | |
| 732 else: | |
| 733 return "RefPtr<ArrayBuffer>" | |
| 734 | |
| 735 # We need to check [ImplementedAs] extended attribute for wrapper types. | |
| 736 if is_wrapper_type(data_type): | |
| 737 interface = self.parse_interface(data_type) | |
| 738 data_type = get_impl_name(interface) | |
| 739 | |
| 740 array_or_sequence_type = get_array_type(data_type) or get_sequence_type( data_type) | |
| 741 if array_or_sequence_type: | |
| 742 data_type = self.get_native_type(array_or_sequence_type) | |
| 743 data_type = data_type.replace(">", "> ") | |
| 744 return "Vector<%s>" % data_type | |
| 745 | |
| 746 if called_by_webcore: | |
| 747 return data_type + "*" | |
| 748 elif used_to_assign_js_value: | |
| 749 return data_type + "*" | |
| 750 elif used_as_parameter: | |
| 751 if re.search(">$", data_type): | |
| 752 data_type += " " | |
| 753 return "PassRefPtr<%s>" % data_type | |
| 754 else: | |
| 755 return "RefPtr<%s>" % data_type | |
| 756 | |
| 757 def header_files_for_interface(self, interface_name, impl_class_name): | |
| 758 includes = [] | |
| 759 if is_typed_array_type(interface_name): | |
| 760 includes.append("wtf/%s.h" % interface_name) | |
| 761 elif not skip_include_header(interface_name): | |
| 762 idl_filename = self.idl_file_for_interface(interface_name) | |
| 763 assert idl_filename | |
|
Nils Barth (inactive)
2013/07/25 03:30:54
Assert is only for internal consistency, not catch
kojih
2013/07/25 09:08:37
ok.
| |
| 764 idlRelPath = "bindings/" + abs2rel(idl_filename, os.getcwd()) | |
| 765 includes.append(os.path.dirname(idlRelPath) + os.sep + impl_class_na me + ".h") | |
|
do-not-use
2013/07/24 11:17:59
We likely want '/' not os.sep for include paths
kojih
2013/07/25 09:08:37
done.
| |
| 766 return includes | |
| 767 | |
| 768 def generate_interface(self, interface): | |
| 769 self.interface = interface | |
| 770 link_overloaded_functions(self.interface) | |
| 771 self.common_template_parameters = { | |
| 772 "conditional_string": get_conditional_string(self.interface), | |
| 773 } | |
| 774 if self.generate_h: | |
| 775 if interface.is_callback: | |
| 776 self.generate_callback_header() | |
| 777 else: | |
| 778 self.generate_header() | |
| 779 if self.generate_cpp: | |
| 780 if interface.is_callback: | |
| 781 self.generate_callback_implementation() | |
| 782 else: | |
| 783 self.generate_implementation() | |
| 784 | |
| 785 def write_interface(self): | |
| 786 if self.interface_name in self.idl_definitions.interfaces: | |
| 787 interface = self.idl_definitions.interfaces[self.interface_name] | |
| 788 self.generate_interface(interface) | |
| 789 if self.generate_h: | |
| 790 header_filename = self.output_directory + os.sep + get_v8_class_ name(self.interface) + ".h" | |
|
do-not-use
2013/07/24 11:17:59
Could use os.path.join()
kojih
2013/07/25 09:08:37
done.
| |
| 791 with open(header_filename, "w") as f: | |
| 792 f.write(self.header) | |
| 793 if self.generate_cpp: | |
| 794 implementation_filename = self.output_directory + os.sep + get_v 8_class_name(self.interface) + ".cpp" | |
|
do-not-use
2013/07/24 11:17:59
Could use os.path.join()
| |
| 795 with open(implementation_filename, "w") as f: | |
| 796 f.write(self.implementation) | |
| 797 else: | |
| 798 raise Exception("%s not in IDL definitions" % self.interface_name) | |
| 799 | |
| 800 def generate_callback_header(self): | |
| 801 impl_class_name = get_impl_name(self.interface) | |
| 802 v8_class_name = get_v8_class_name(self.interface) | |
| 803 includes = [ | |
| 804 "bindings/v8/ActiveDOMCallback.h", | |
| 805 "bindings/v8/DOMWrapperWorld.h", | |
| 806 "bindings/v8/ScopedPersistent.h", | |
| 807 ] | |
| 808 includes += self.header_files_for_interface(self.interface.name, impl_cl ass_name) | |
| 809 includes = sort_and_remove_duplicate(includes) | |
| 810 class_public_definitions = [] | |
| 811 for operation in self.interface.operations: | |
| 812 # only bool used for callback .h | |
| 813 code = "virtual %s %s(%s);" % (self.get_native_type(operation.data_t ype), operation.name, self.get_callback_parameter_declaration(operation)) | |
| 814 class_public_definitions.append(code) | |
| 815 | |
| 816 template_parameters = self.common_template_parameters.copy() | |
| 817 template_parameters.update({ | |
| 818 "interface_name": self.interface.name, | |
| 819 "impl_class_name": impl_class_name, | |
| 820 "v8_class_name": v8_class_name, | |
| 821 "includes": includes, | |
| 822 "class_public_definitions": class_public_definitions, | |
| 823 }) | |
| 824 | |
| 825 self.header = apply_template("templates/callback.h", template_parameters ) | |
| 826 | |
| 827 def generate_callback_implementation(self): | |
| 828 impl_class_name = get_impl_name(self.interface) | |
| 829 v8_class_name = get_v8_class_name(self.interface) | |
| 830 includes = [ | |
| 831 "core/dom/ScriptExecutionContext.h", | |
| 832 "bindings/v8/V8Binding.h", | |
| 833 "bindings/v8/V8Callback.h", | |
| 834 "wtf/Assertions.h", | |
| 835 ] | |
| 836 functions = [] | |
| 837 for operation in self.interface.operations: | |
| 838 if "Custom" in operation.extended_attributes: | |
| 839 continue | |
| 840 includes += get_includes_for_type(operation.data_type) | |
| 841 for parameter in operation.arguments: | |
| 842 includes += get_includes_for_parameter(parameter) | |
| 843 if operation.data_type != "boolean": | |
| 844 raise Exception("We don't yet support callbacks that return non- boolean values.") | |
| 845 parameters = [] | |
| 846 for parameter in operation.arguments: | |
| 847 receiver = "v8::Handle<v8::Value> %sHandle = %%s;" % parameter.n ame | |
| 848 native_to_js_value_statement, additional_includes = self.get_nat ive_to_js_value_statement(parameter.data_type, parameter.extended_attributes, pa rameter.name, receiver=receiver, creation_context="v8::Handle<v8::Object>()", is olate="isolate") | |
| 849 includes += additional_includes | |
| 850 parameters.append({ | |
| 851 "name": parameter.name, | |
| 852 "native_to_js_value_statement": native_to_js_value_statement , | |
| 853 }) | |
| 854 definition = { | |
| 855 "return_type": self.get_native_type(operation.data_type), | |
| 856 "name": operation.name, | |
| 857 "parameter_declaration": self.get_callback_parameter_declaration (operation), | |
| 858 "prepare_js_parameters": "", | |
| 859 "handles": ",\n".join(["%sHandle" % parameter.name for parameter in operation.arguments]), | |
| 860 "parameters": parameters, | |
| 861 } | |
| 862 functions.append(definition) | |
| 863 | |
| 864 includes = sort_and_remove_duplicate(includes) | |
| 865 | |
| 866 template_parameters = self.common_template_parameters.copy() | |
| 867 template_parameters.update({ | |
| 868 "interface_name": self.interface.name, | |
| 869 "impl_class_name": impl_class_name, | |
| 870 "v8_class_name": v8_class_name, | |
| 871 "includes": includes, | |
| 872 "functions": functions, | |
| 873 }) | |
| 874 self.implementation = apply_template("templates/callback.cpp", template_ parameters) | |
| 875 | |
| 876 def generate_header(self): | |
| 877 # TODO: implement | |
| 878 self.header = "" | |
| 879 | |
| 880 def generate_implementation(self): | |
| 881 # TODO: implement | |
| 882 self.implementation = "" | |
| 39 | 883 |
| 40 | 884 |
| 41 def generate_dummy_header_and_cpp(target_interface_name, output_directory): | 885 def generate_dummy_header_and_cpp(target_interface_name, output_directory): |
| 42 header_basename = 'V8%s.h' % target_interface_name | 886 header_basename = 'V8%s.h' % target_interface_name |
| 43 cpp_basename = 'V8%s.cpp' % target_interface_name | 887 cpp_basename = 'V8%s.cpp' % target_interface_name |
| 44 header_fullname = os.path.join(output_directory, header_basename) | 888 header_fullname = os.path.join(output_directory, header_basename) |
| 45 cpp_fullname = os.path.join(output_directory, cpp_basename) | 889 cpp_fullname = os.path.join(output_directory, cpp_basename) |
| 46 contents = """/* | 890 contents = """/* |
| 47 This file is generated just to tell build scripts that {header_basename} and | 891 This file is generated just to tell build scripts that {header_basename} and |
| 48 {cpp_basename} are created for {target_interface_name}.idl, and thus | 892 {cpp_basename} are created for {target_interface_name}.idl, and thus |
| 49 prevent the build scripts from trying to generate {header_basename} and | 893 prevent the build scripts from trying to generate {header_basename} and |
| 50 {cpp_basename} at every build. This file must not be tried to compile. | 894 {cpp_basename} at every build. This file must not be tried to compile. |
| 51 */ | 895 */ |
| 52 """.format(**locals()) | 896 """.format(**locals()) |
| 53 with open(header_fullname, 'w') as header_file: | 897 with open(header_fullname, 'w') as header_file: |
| 54 header_file.write(contents) | 898 header_file.write(contents) |
| 55 with open(cpp_fullname, 'w') as cpp_file: | 899 with open(cpp_fullname, 'w') as cpp_file: |
| 56 cpp_file.write(contents) | 900 cpp_file.write(contents) |
| OLD | NEW |