Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(880)

Side by Side Diff: Source/bindings/scripts/v8_functions.py

Issue 17572008: WIP IDL compiler rewrite (Closed) Base URL: https://chromium.googlesource.com/chromium/blink@master
Patch Set: Branch: const + primitive type readonly attributes Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Source/bindings/scripts/v8_constructors.py ('k') | Source/bindings/scripts/v8_includes.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 # Copyright (C) 2013 Google Inc. All rights reserved.
2 #
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions are
5 # met:
6 #
7 # * Redistributions of source code must retain the above copyright
8 # notice, this list of conditions and the following disclaimer.
9 # * Redistributions in binary form must reproduce the above
10 # copyright notice, this list of conditions and the following disclaimer
11 # in the documentation and/or other materials provided with the
12 # distribution.
13 # * Neither the name of Google Inc. nor the names of its
14 # contributors may be used to endorse or promote products derived from
15 # this software without specific prior written permission.
16 #
17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 # 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29 """Generate template values for functions.
30
31 FIXME: rename "parameter/parameters":
32 "template parameters" is easily confused with "function parameters"
33 Also, "parameter*s*", not "parameter".
34 """
35
36
37 from code_generator_idl_reader import implemented_as_from_implemented_by
38 from v8_includes import *
39 from v8_types import *
40 from v8_utilities import extended_attribute_contains, generate_conditional_strin g, get_raises_exception, runtime_enable_function_name, implemented_as_cpp_name
41 from v8_values import get_js_value_to_native_statement, get_native_to_js_value_s tatement, get_pass_owner_expression
42
43 from v8_utilities import ACTIVITY_LOGGING_INCLUDES, get_call_with_parameter, get _custom_element_invocation_scope_parameter, get_deprecation_notification_paramet er, get_function_mandatory_parameters, get_feature_observation_parameter, has_ac tivity_logging
44
45
46 def generate_functions(interface):
47 # FIXME: clearer with a list comprehension + nested function to handle inclu des
48 functions = []
49 includes = []
50 for function in interface.operations:
51 function_contents, function_includes = generate_function(interface, func tion)
52 # print '[FUNC]', function_contents
53 functions.append(function_contents)
54 includes += function_includes
55 return functions, includes
56
57
58 def generate_function(interface, function):
59 includes = []
60 name = function.name
61 cpp_class_name = implemented_as_cpp_name(interface)
62 is_normal_function = function.name and 'EnabledPerContext' not in function.e xtended_attributes
63 is_standard_function = get_is_standard_function(interface, function)
64 is_custom = has_custom_implementation(function)
65
66 per_world_bindings = 'PerWorldBindings' in function.extended_attributes
67 for_main_world_suffixes = ['']
68 if per_world_bindings:
69 for_main_world_suffixes.append('ForMainWorld')
70
71 activity_logging = set()
72 setter_function_call_parameter = {}
73 for for_main_world_suffix in for_main_world_suffixes:
74 if has_activity_logging(for_main_world_suffix, function.extended_attribu tes, 'Method'):
75 activity_logging.add(for_main_world_suffix)
76 includes += ACTIVITY_LOGGING_INCLUDES
77
78 check_security_for_node = 'CheckSecurityForNode' in function.extended_attrib utes
79 if check_security_for_node:
80 includes.append('bindings/v8/BindingSecurity.h')
81
82 method_for_main_world = '0'
83 if 'PerWorldBindings' in function.extended_attributes:
84 method_for_main_world = '%sV8Internal::%sMethodCallbackForMainWorld' % ( implemented_as_cpp_name(interface), function.name)
85 mandatory_parameters = get_function_mandatory_parameters(function)
86
87 if len(function.overloads) > 1:
88 name = '%s%d' % (name, function.overload_index)
89 is_representative = function.overload_index == 1
90 conditional_runtime = ''
91 enable_function = ''
92 if 'EnabledAtRuntime' in function.extended_attributes:
93 # Only call Set()/SetAccessor() if this method should be enabled
94 enable_function = runtime_enable_function_name(function)
95 conditional_runtime = 'if (%s())\n ' % enable_function
96 if function.extended_attributes.get('EnabledPerContext'):
97 # Only call Set()/SetAccessor() if this method should be enabled
98 enable_function = get_context_enable_function(function)
99 conditional_runtime = 'if (%s(impl->document()))' % enable_function
100
101 template = 'proto'
102 if 'Unforgeable' in function.extended_attributes:
103 template = 'instance'
104 if function.is_static:
105 template = 'desc'
106
107 setter = '%sV8Internal::%sDomainSafeFunctionSetter' % (cpp_class_name, cpp_c lass_name) if 'ReadOnly' not in function.extended_attributes else '0'
108
109 signature = 'defaultSignature'
110 if 'DoNotCheckSignature' in function.extended_attributes or function.is_stat ic:
111 signature = 'v8::Local<v8::Signature>()'
112 requires_custom_signature = get_requires_custom_signature(function)
113 if requires_custom_signature:
114 signature = function.name + 'Signature'
115
116 # FIXME: simplify: additional_property_attributes_list, ' | '.join(...)
117 property_attributes = 'v8::DontDelete'
118 if 'NotEnumerable' in function.extended_attributes:
119 property_attributes += ' | v8::DontEnum'
120 if 'ReadOnly' in function.extended_attributes:
121 property_attributes += ' | v8::ReadOnly'
122
123 if property_attributes == 'v8::DontDelete':
124 property_attributes = ''
125 else:
126 property_attributes = ', static_cast<v8::PropertyAttribute>(%s)' % prope rty_attributes
127
128 custom_signatures = []
129 if requires_custom_signature:
130 for parameter in function.arguments:
131 if is_wrapper_type(parameter.data_type):
132 if parameter.data_type == 'XPathNSResolver':
133 # Special case for XPathNSResolver. All other browsers acce pts a callable,
134 # so, even though it's against IDL, accept objects here.
135 custom_signatures.append('v8::Handle<v8::FunctionTemplate>() ')
136 else:
137 array_or_sequence_type = get_array_or_sequence_type(paramete r.data_type)
138
139 if array_or_sequence_type:
140 if is_ref_ptr_type(array_or_sequence_type):
141 includes += get_includes_for_type(array_or_sequence_ type)
142 else:
143 custom_signatures.append('v8::Handle<v8::FunctionTem plate>()')
144 continue
145 else:
146 # print '[FOO]', parameter.data_type, 'AS', array_or _sequence_type
147 includes += get_includes_for_type(parameter.data_type)
148 custom_signatures.append('V8PerIsolateData::from(isolate)->r awTemplate(&V8%s::info, currentWorldType)' % parameter.data_type)
149 else:
150 custom_signatures.append('v8::Handle<v8::FunctionTemplate>()')
151 custom_signature = ', '.join(custom_signatures)
152 function_call_parameters = {}
153 raises_exception = get_raises_exception(function)
154 if any(['IsIndex' in parameter.extended_attributes
155 for parameter in function.arguments]):
156 raises_exception = True
157 feature_observation_parameter = {}
158 deprecation_notification_parameter = {}
159 custom_element_invocation_scope_parameter = {}
160 parameter_check_parameters = {}
161
162 if not is_custom and name:
163 if raises_exception:
164 includes.append('bindings/v8/ExceptionState.h')
165
166 parameter_check_parameters, parameter_check_includes, replacements = get _parameter_check_parameters(interface, function)
167 includes += parameter_check_includes
168
169 for for_main_world_suffix in for_main_world_suffixes:
170 function_call_parameter, function_call_includes = get_function_call_ parameter(interface, function, len(function.arguments), for_main_world_suffix=fo r_main_world_suffix, replacements=replacements)
171 function_call_parameters[for_main_world_suffix] = function_call_para meter
172 includes += function_call_includes
173
174 comment_info = 'Function "%s" (ExtAttr: "%s")' % (function.name, ' '.joi n(function.extended_attributes.keys()))
175
176 # if template == 'proto' and conditional_runtime == '' and signature == 'defaultSignature' and property_attributes == '':
177 # raise Exception('This shouldn't happen: Class '%s' %s' % (cpp_clas s_name, comment_info))
178
179 custom_element_invocation_scope_parameter, custom_element_invocation_sco pe_includes = get_custom_element_invocation_scope_parameter(function)
180 includes += custom_element_invocation_scope_includes
181
182 feature_observation_parameter, feature_observation_includes = get_featur e_observation_parameter(function)
183 includes += feature_observation_includes
184
185 deprecation_notification_parameter, deprecation_notification_includes = get_deprecation_notification_parameter(function)
186 includes += deprecation_notification_includes
187
188 # print
189 # print '#'*30
190 # print '[get_function_parameter] ', function.data_type, name
191 contents = {
192 'name': name,
193 'is_static': function.is_static,
194 'is_custom': is_custom,
195 'create_callback': is_representative and is_normal_function and is_stand ard_function,
196 'is_representative': is_representative,
197 'conditional_runtime': conditional_runtime,
198 'template': template,
199 'setter': setter,
200 'signature': signature,
201 'property_attributes': property_attributes,
202 'requires_custom_signature': requires_custom_signature,
203 'custom_signature': custom_signature,
204 'conditional_string': generate_conditional_string(function),
205 'mandatory_parameters': mandatory_parameters,
206 'length': get_function_mandatory_parameters(function, count_variadic=Tru e),
207 'parameters': parameter_check_parameters,
208 'function_call_parameter': function_call_parameters,
209 'method_for_main_world': method_for_main_world,
210 'is_normal_function': is_normal_function,
211 'is_standard_function': is_standard_function,
212 'is_enabled_per_context_function': function.name and 'EnabledPerContext' in function.extended_attributes,
213 'raises_exception': raises_exception,
214 'do_not_check_security': 'DoNotCheckSecurity' in function.extended_attri butes,
215 'for_main_world_suffixes': for_main_world_suffixes,
216 'cpp_name': implemented_as_cpp_name(function),
217 'check_security_for_node': check_security_for_node,
218 'enable_function': enable_function,
219 'activity_logging': activity_logging,
220 }
221 contents.update(feature_observation_parameter)
222 contents.update(deprecation_notification_parameter)
223 contents.update(custom_element_invocation_scope_parameter)
224 return contents, includes
225
226
227 def get_function_call_parameter(interface, function, number_of_parameters=None, for_main_world_suffix='', replacements=None):
228 # return parameter for function_call macro, includes
229 replacements = replacements or {}
230 if number_of_parameters is None:
231 number_of_parameters = len(function.arguments)
232
233 includes = []
234 arguments = []
235 cpp_class_name = implemented_as_cpp_name(interface)
236 implemented_by = function.extended_attributes.get('ImplementedBy')
237 ### TODO Similar to attribute. merge!
238 if implemented_by:
239 implemented_by_cpp_name = implemented_as_from_implemented_by(implemented _by)
240 includes += header_files_for_interface(implemented_by, implemented_by_cp p_name)
241 function_name = '%s::%s' % (implemented_by_cpp_name, implemented_as_cpp_ name(function))
242 if not function.is_static:
243 arguments.append('imp')
244 elif function.is_static:
245 function_name = '%s::%s' % (cpp_class_name, implemented_as_cpp_name(func tion))
246 else:
247 function_name = 'imp->%s' % implemented_as_cpp_name(function)
248
249 call_with = function.extended_attributes.get('CallWith')
250 call_with_arguments, call_with_parameter, call_with_includes = get_call_with _parameter(call_with, return_void=True, function=function)
251 includes += call_with_includes
252 arguments = call_with_arguments + arguments
253
254 parameters = []
255 for index, parameter in enumerate(function.arguments):
256 svg_tear_off_and_not_list = False
257 if index == number_of_parameters:
258 break
259 if replacements.get(parameter.name):
260 arguments.append(replacements.get(parameter.name))
261 elif parameter.data_type == 'NodeFilter' or parameter.data_type == 'XPat hNSResolver':
262 arguments.append('%s.get()' % parameter.name)
263 elif get_svg_type_needing_tear_off(parameter.data_type) and not interfac e.name.endswith('List'):
264 includes.append('core/dom/ExceptionCode.h')
265 arguments.append('%s->propertyReference()' % parameter.name)
266 svg_tear_off_and_not_list = True
267 elif parameter.data_type == 'SVGMatrix' and interface.name == 'SVGTransf ormList':
268 arguments.append('%s.get()' % parameter.name)
269 else:
270 arguments.append(parameter.name)
271 parameter = {
272 'svg_tear_off_and_not_list': svg_tear_off_and_not_list,
273 'name': parameter.name,
274 }
275 parameters.append(parameter)
276
277 if get_raises_exception(function):
278 arguments.append('es')
279
280 function_call_expression = '%s(%s)' % (function_name, ', '.join(arguments))
281 native_value_expression = get_pass_owner_expression(function.data_type, 'res ult')
282 function_call_statement = ''
283 if function.data_type == 'void':
284 function_call_statement = '%s;' % function_call_expression
285 elif extended_attribute_contains(function.extended_attributes.get('CallWith' ), 'ScriptState') or get_raises_exception(function):
286 function_call_statement = '%s result = %s;' % (get_native_type(function. data_type, extended_attributes=function.extended_attributes), function_call_expr ession)
287 else:
288 native_value_expression = function_call_expression
289
290 extended_attribute_contains_script_state = extended_attribute_contains(call_ with, 'ScriptState')
291
292 script_wrappable = is_dom_node_type(interface.name) and 'imp' or 0
293 return_js_value_statement = ''
294 return_js_value_statement, native_to_js_value_includes = get_native_to_js_va lue_statement(function.data_type, function.extended_attributes, native_value_exp ression, creation_context='args.Holder()', isolate='args.GetIsolate()', callback _info='args', script_wrappable=script_wrappable, for_main_world_suffix=for_main_ world_suffix, used_as_return_value=True)
295 includes += native_to_js_value_includes
296 # print '[----]', function.name
297
298 svg_native_type = svg_tear_off = get_svg_type_needing_tear_off(function.data _type)
299 svg_tear_off_and_not_list = svg_tear_off and not interface.name.endswith('Li st')
300 dom_node_type = is_dom_node_type(interface.name)
301 if svg_tear_off_and_not_list:
302 includes.append('V8%s.h' % function.data_type)
303 includes.append('core/svg/properties/SVGPropertyTearOff.h')
304
305 parameter = {
306 'statement': function_call_statement,
307 'raises_exception': get_raises_exception(function),
308 'return_js_value_statement': return_js_value_statement,
309 'extended_attribute_contains_script_state': extended_attribute_contains_ script_state,
310 'call_with': call_with_parameter,
311 'parameters': parameters,
312 'svg_tear_off_and_not_list': svg_tear_off_and_not_list,
313 'svg_tear_off': svg_tear_off,
314 'is_dom_node_type': dom_node_type,
315 'for_main_world_suffix': for_main_world_suffix,
316 'svg_native_type': svg_native_type,
317 'native_value_expression': native_value_expression,
318 }
319 return parameter, includes
320
321
322 def get_function_mandatory_parameters(function, count_variadic=False):
323 allow_non_optional = True
324 for parameter in function.arguments:
325 if parameter.is_optional or parameter.is_variadic:
326 allow_non_optional = False
327 else:
328 if not allow_non_optional:
329 raise Exception()
330 mandatory_parameters = 0
331 for parameter in function.arguments:
332 if parameter.is_optional:
333 break
334 if parameter.is_variadic and not count_variadic:
335 break
336 mandatory_parameters += 1
337 # print '[]', function.name, mandatory_parameters
338 return mandatory_parameters
339
340
341 def get_parameter_check_parameters(interface, function, for_main_world_suffix='' ):
342 # GenerateParametersCheck in perl
343 includes = []
344 parameters_check_parameter = []
345 for parameter_index in range(len(function.arguments)):
346 parameter_check_parameter, parameter_check_includes = get_parameter_chec k_parameter(interface, function, parameter_index)
347 parameters_check_parameter.append(parameter_check_parameter)
348 includes += parameter_check_includes
349 replacements = {} # TODO
350 return parameters_check_parameter, includes, replacements
351
352
353 def get_parameter_check_parameter(interface, function, parameter_index, for_main _world_suffix=''):
354 # corresponds to for loop in GenerateParametersCheck in perl
355 includes = ['bindings/v8/ExceptionState.h']
356 parameter = function.arguments[parameter_index]
357 is_callback_interface = is_callback_interface_etc(parameter.data_type)
358 if is_callback_interface:
359 includes.append('V8%s.h' % parameter.data_type)
360 if parameter.data_type == 'SerializedScriptValue':
361 includes.append('bindings/v8/SerializedScriptValue.h')
362 is_index = 'IsIndex' in parameter.extended_attributes
363 if is_index:
364 includes.append('core/dom/ExceptionCode.h')
365
366 native_type = get_native_type(parameter.data_type, extended_attributes=param eter.extended_attributes, used_to_assign_js_value=True)
367 native_element_type = get_native_type(parameter.data_type)
368 if native_element_type.endswith('>'):
369 native_element_type += ' '
370
371 # print '[[]]', native_type
372 default = ''
373 if 'Default' in parameter.extended_attributes:
374 default = parameter.extended_attributes.get('Default')
375
376 if parameter.is_optional and default == 'NullString':
377 js_value = 'argumentOrNull(args, %d)' % parameter_index
378 else:
379 js_value = 'args[%d]' % parameter_index
380
381 js_to_native_statement, js_value_to_native_includes = get_js_value_to_native _statement(parameter.data_type, parameter.extended_attributes, js_value, paramet er.name, 'args.GetIsolate()')
382 includes += js_value_to_native_includes
383
384 enum_values = get_enum_values(parameter.data_type)
385 enum_validation_terms = ['string == "%s"' % enum_value for enum_value in enu m_values]
386 enum_validation_expression = ' || '.join(enum_validation_terms)
387
388 # Optional arguments without [Default=...] should generate an early call wit h fewer arguments.
389 # Optional arguments with [Optional=...] should not generate the early call.
390 # Optional Dictionary arguments always considered to have default of empty d ictionary.
391 early_call = parameter.is_optional and 'Default' not in parameter.extended_a ttributes and native_type != 'Dictionary' and not is_callback_interface
392 early_call_multi_line = False
393 early_call_statements = {}
394 if early_call:
395 # TODO
396 early_call_statements, early_call_includes = get_function_call_parameter (interface, function, parameter_index, for_main_world_suffix=for_main_world_suff ix)
397 includes += early_call_includes
398 early_call_multi_line = len([c for c in early_call_statements if c == '\ n']) > 1
399
400 parameter_check_parameter = {
401 'index': parameter_index,
402 'name': parameter.name,
403 'type': parameter.data_type,
404 'early_call': early_call,
405 'early_call_statement_parameter': early_call_statements,
406 'early_call_multi_line': early_call_multi_line,
407 'is_callback_interface': is_callback_interface,
408 'is_optional': parameter.is_optional,
409 'is_variadic': parameter.is_variadic,
410 'is_index': is_index,
411 'is_wrapper_type': is_wrapper_type(parameter.data_type),
412 'clamp': parameter.extended_attributes.get('Clamp'),
413 'strict_type_checking': parameter.extended_attributes.get('StrictTypeChe cking'),
414 'enforce_range': 'EnforceRange' in parameter.extended_attributes,
415 'js_to_native_statement': js_to_native_statement,
416 'native_type': native_type,
417 'native_element_type': native_element_type,
418 'enum_validation_expression': enum_validation_expression,
419 'is_enum_type': is_enum_type(parameter.data_type),
420 }
421 return parameter_check_parameter, includes
OLDNEW
« no previous file with comments | « Source/bindings/scripts/v8_constructors.py ('k') | Source/bindings/scripts/v8_includes.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698