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 |