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

Side by Side Diff: lib/dom/scripts/systemnative.py

Issue 10913125: Remove lib/dom directory! (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 3 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 #!/usr/bin/python
2 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
3 # for details. All rights reserved. Use of this source code is governed by a
4 # BSD-style license that can be found in the LICENSE file.
5
6 """This module provides shared functionality for the systems to generate
7 native binding from the IDL database."""
8
9 import emitter
10 import os
11 import systembase
12 from generator import *
13
14
15 class NativeImplementationSystem(systembase.System):
16
17 def __init__(self, options, auxiliary_dir):
18 super(NativeImplementationSystem, self).__init__(options)
19 self._auxiliary_dir = auxiliary_dir
20 self._cpp_header_files = []
21 self._cpp_impl_files = []
22
23 def ImplementationGenerator(self, interface):
24 return NativeImplementationGenerator(self, interface)
25
26 def ProcessCallback(self, interface, info):
27 self._interface = interface
28
29 if IsPureInterface(self._interface.id):
30 return None
31
32 cpp_impl_includes = set()
33 cpp_header_handlers_emitter = emitter.Emitter()
34 cpp_impl_handlers_emitter = emitter.Emitter()
35 class_name = 'Dart%s' % self._interface.id
36 for operation in interface.operations:
37 if operation.type.id == 'void':
38 return_prefix = ''
39 error_return = ''
40 else:
41 return_prefix = 'return '
42 error_return = ' false'
43
44 parameters = []
45 arguments = []
46 conversion_includes = []
47 for argument in operation.arguments:
48 argument_type_info = self._type_registry.TypeInfo(argument.type.id)
49 parameters.append('%s %s' % (argument_type_info.parameter_type(),
50 argument.id))
51 arguments.append(argument_type_info.to_dart_conversion(argument.id))
52 conversion_includes.extend(argument_type_info.conversion_includes())
53
54 native_return_type = self._type_registry.TypeInfo(operation.type.id).nativ e_type()
55 cpp_header_handlers_emitter.Emit(
56 '\n'
57 ' virtual $TYPE handleEvent($PARAMETERS);\n',
58 TYPE=native_return_type, PARAMETERS=', '.join(parameters))
59
60 if 'Custom' in operation.ext_attrs:
61 continue
62
63 cpp_impl_includes |= set(conversion_includes)
64 arguments_declaration = 'Dart_Handle arguments[] = { %s }' % ', '.join(arg uments)
65 if not len(arguments):
66 arguments_declaration = 'Dart_Handle* arguments = 0'
67 cpp_impl_handlers_emitter.Emit(
68 '\n'
69 '$TYPE $CLASS_NAME::handleEvent($PARAMETERS)\n'
70 '{\n'
71 ' if (!m_callback.isolate()->isAlive())\n'
72 ' return$ERROR_RETURN;\n'
73 ' DartIsolate::Scope scope(m_callback.isolate());\n'
74 ' DartApiScope apiScope;\n'
75 ' $ARGUMENTS_DECLARATION;\n'
76 ' $(RETURN_PREFIX)m_callback.handleEvent($ARGUMENT_COUNT, arguments );\n'
77 '}\n',
78 TYPE=native_return_type,
79 CLASS_NAME=class_name,
80 PARAMETERS=', '.join(parameters),
81 ERROR_RETURN=error_return,
82 RETURN_PREFIX=return_prefix,
83 ARGUMENTS_DECLARATION=arguments_declaration,
84 ARGUMENT_COUNT=len(arguments))
85
86 cpp_header_path = self._FilePathForCppHeader(self._interface.id)
87 cpp_header_emitter = self._emitters.FileEmitter(cpp_header_path)
88 cpp_header_emitter.Emit(
89 self._templates.Load('cpp_callback_header.template'),
90 INTERFACE=self._interface.id,
91 HANDLERS=cpp_header_handlers_emitter.Fragments())
92
93 cpp_impl_path = self._FilePathForCppImplementation(self._interface.id)
94 self._cpp_impl_files.append(cpp_impl_path)
95 cpp_impl_emitter = self._emitters.FileEmitter(cpp_impl_path)
96 cpp_impl_emitter.Emit(
97 self._templates.Load('cpp_callback_implementation.template'),
98 INCLUDES=_GenerateCPPIncludes(cpp_impl_includes),
99 INTERFACE=self._interface.id,
100 HANDLERS=cpp_impl_handlers_emitter.Fragments())
101
102 def GenerateLibraries(self, interface_files):
103 # Generate dart:html library.
104 auxiliary_dir = os.path.relpath(self._auxiliary_dir, self._output_dir)
105 self._GenerateLibFile(
106 'html_dartium.darttemplate',
107 os.path.join(self._output_dir, 'html_dartium.dart'),
108 interface_files,
109 AUXILIARY_DIR=systembase.MassagePath(auxiliary_dir))
110
111 # Generate DartDerivedSourcesXX.cpp.
112 partitions = 20 # FIXME: this should be configurable.
113 sources_count = len(self._cpp_impl_files)
114 for i in range(0, partitions):
115 derived_sources_path = os.path.join(self._output_dir,
116 'DartDerivedSources%02i.cpp' % (i + 1))
117
118 includes_emitter = emitter.Emitter()
119 for impl_file in self._cpp_impl_files[i::partitions]:
120 path = os.path.relpath(impl_file, os.path.dirname(derived_sources_path ))
121 includes_emitter.Emit('#include "$PATH"\n', PATH=path)
122
123 derived_sources_emitter = self._emitters.FileEmitter(derived_sources_path)
124 derived_sources_emitter.Emit(
125 self._templates.Load('cpp_derived_sources.template'),
126 INCLUDES=includes_emitter.Fragments())
127
128 # Generate DartResolver.cpp.
129 cpp_resolver_path = os.path.join(self._output_dir, 'DartResolver.cpp')
130
131 includes_emitter = emitter.Emitter()
132 resolver_body_emitter = emitter.Emitter()
133 for file in self._cpp_header_files:
134 path = os.path.relpath(file, os.path.dirname(cpp_resolver_path))
135 includes_emitter.Emit('#include "$PATH"\n', PATH=path)
136 resolver_body_emitter.Emit(
137 ' if (Dart_NativeFunction func = $CLASS_NAME::resolver(name, argu mentCount))\n'
138 ' return func;\n',
139 CLASS_NAME=os.path.splitext(os.path.basename(path))[0])
140
141 cpp_resolver_emitter = self._emitters.FileEmitter(cpp_resolver_path)
142 cpp_resolver_emitter.Emit(
143 self._templates.Load('cpp_resolver.template'),
144 INCLUDES=includes_emitter.Fragments(),
145 RESOLVER_BODY=resolver_body_emitter.Fragments())
146
147 def Finish(self):
148 pass
149
150 def _FilePathForCppHeader(self, interface_name):
151 return os.path.join(self._output_dir, 'cpp', 'Dart%s.h' % interface_name)
152
153 def _FilePathForCppImplementation(self, interface_name):
154 return os.path.join(self._output_dir, 'cpp', 'Dart%s.cpp' % interface_name)
155
156
157 class NativeImplementationGenerator(systembase.BaseGenerator):
158 """Generates Dart implementation for one DOM IDL interface."""
159
160 def __init__(self, system, interface):
161 """Generates Dart and C++ code for the given interface.
162
163 Args:
164 system: The NativeImplementationSystem.
165 interface: an IDLInterface instance. It is assumed that all types have
166 been converted to Dart types (e.g. int, String), unless they are in
167 the same package as the interface.
168 """
169 super(NativeImplementationGenerator, self).__init__(
170 system._database, interface)
171 self._system = system
172 self._current_secondary_parent = None
173 self._html_interface_name = system._renamer.RenameInterface(self._interface)
174
175 def HasImplementation(self):
176 return not IsPureInterface(self._interface.id)
177
178 def ImplementationClassName(self):
179 return self._ImplClassName(self._interface.id)
180
181 def FilePathForDartImplementation(self):
182 return os.path.join(self._system._output_dir, 'dart',
183 '%sImplementation.dart' % self._interface.id)
184
185 def FilePathForDartFactoryProviderImplementation(self):
186 file_name = '%sFactoryProviderImplementation.dart' % self._interface.id
187 return os.path.join(self._system._output_dir, 'dart', file_name)
188
189 def FilePathForDartElementsFactoryProviderImplementation(self):
190 return os.path.join(self._system._output_dir, 'dart',
191 '_ElementsFactoryProviderImplementation.dart')
192
193 def SetImplementationEmitter(self, implementation_emitter):
194 self._dart_impl_emitter = implementation_emitter
195
196 def ImplementsMergedMembers(self):
197 # We could not add merged functions to implementation class because
198 # underlying c++ object doesn't implement them. Merged functions are
199 # generated on merged interface implementation instead.
200 return False
201
202 def StartInterface(self):
203 # Create emitters for c++ implementation.
204 if self.HasImplementation():
205 cpp_header_path = self._system._FilePathForCppHeader(self._interface.id)
206 self._system._cpp_header_files.append(cpp_header_path)
207 self._cpp_header_emitter = self._system._emitters.FileEmitter(cpp_header_p ath)
208 cpp_impl_path = self._system._FilePathForCppImplementation(self._interface .id)
209 self._system._cpp_impl_files.append(cpp_impl_path)
210 self._cpp_impl_emitter = self._system._emitters.FileEmitter(cpp_impl_path)
211 else:
212 self._cpp_header_emitter = emitter.Emitter()
213 self._cpp_impl_emitter = emitter.Emitter()
214
215 self._interface_type_info = self._TypeInfo(self._interface.id)
216 self._members_emitter = emitter.Emitter()
217 self._cpp_declarations_emitter = emitter.Emitter()
218 self._cpp_impl_includes = set()
219 self._cpp_definitions_emitter = emitter.Emitter()
220 self._cpp_resolver_emitter = emitter.Emitter()
221
222 self._GenerateConstructors()
223 return self._members_emitter
224
225 def _GenerateConstructors(self):
226 if not self._IsConstructable():
227 return
228
229 # TODO(antonm): currently we don't have information about number of argument s expected by
230 # the constructor, so name only dispatch.
231 self._cpp_resolver_emitter.Emit(
232 ' if (name == "$(INTERFACE_NAME)_constructor_Callback")\n'
233 ' return Dart$(INTERFACE_NAME)Internal::constructorCallback;\n',
234 INTERFACE_NAME=self._interface.id)
235
236
237 constructor_info = AnalyzeConstructor(self._interface)
238
239 ext_attrs = self._interface.ext_attrs
240
241 if 'CustomConstructor' in ext_attrs:
242 # We have a custom implementation for it.
243 self._cpp_declarations_emitter.Emit(
244 '\n'
245 'void constructorCallback(Dart_NativeArguments);\n')
246 return
247
248 if ext_attrs.get('ConstructorTemplate') == 'TypedArray':
249 self._cpp_impl_includes.add('"DartArrayBufferViewCustom.h"');
250 self._cpp_definitions_emitter.Emit(
251 '\n'
252 'static void constructorCallback(Dart_NativeArguments args)\n'
253 '{\n'
254 ' WebCore::DartArrayBufferViewInternal::constructWebGLArray<Dart$(INT ERFACE_NAME)>(args);\n'
255 '}\n',
256 INTERFACE_NAME=self._interface.id);
257 return
258
259 create_function = 'create'
260 if 'NamedConstructor' in ext_attrs:
261 create_function = 'createForJSConstructor'
262 function_expression = '%s::%s' % (self._interface_type_info.native_type(), c reate_function)
263 self._GenerateNativeCallback(
264 'constructorCallback',
265 False,
266 function_expression,
267 self._interface,
268 constructor_info.idl_args,
269 self._interface.id,
270 'ConstructorRaisesException' in ext_attrs)
271
272 def _ImplClassName(self, interface_name):
273 return '_%sImpl' % interface_name
274
275 def _BaseClassName(self):
276 root_class = 'NativeFieldWrapperClass1'
277
278 if not self._interface.parents:
279 return root_class
280
281 supertype = self._interface.parents[0].type.id
282
283 if IsPureInterface(supertype): # The class is a root.
284 return root_class
285
286 # FIXME: We're currently injecting List<..> and EventTarget as
287 # supertypes in dart.idl. We should annotate/preserve as
288 # attributes instead. For now, this hack lets the self._interfaces
289 # inherit, but not the classes.
290 # List methods are injected in AddIndexer.
291 if IsDartListType(supertype) or IsDartCollectionType(supertype):
292 return root_class
293
294 return self._ImplClassName(supertype)
295
296 ATTRIBUTES_OF_CONSTRUCTABLE = set([
297 'CustomConstructor',
298 'V8CustomConstructor',
299 'Constructor',
300 'NamedConstructor'])
301
302 def _IsConstructable(self):
303 ext_attrs = self._interface.ext_attrs
304
305 if self.ATTRIBUTES_OF_CONSTRUCTABLE & set(ext_attrs):
306 return True
307
308 # FIXME: support other types of ConstructorTemplate.
309 if ext_attrs.get('ConstructorTemplate') == 'TypedArray':
310 return True
311
312 return False
313
314 def EmitFactoryProvider(self, constructor_info, factory_provider, emitter):
315 template_file = 'factoryprovider_%s.darttemplate' % self._html_interface_nam e
316 template = self._system._templates.TryLoad(template_file)
317 if not template:
318 template = self._system._templates.Load('factoryprovider.darttemplate')
319
320 native_binding = '%s_constructor_Callback' % self._interface.id
321 emitter.Emit(
322 template,
323 FACTORYPROVIDER=factory_provider,
324 INTERFACE=self._html_interface_name,
325 PARAMETERS=constructor_info.ParametersImplementationDeclaration(self._Da rtType),
326 ARGUMENTS=constructor_info.ParametersAsArgumentList(),
327 NATIVE_NAME=native_binding)
328
329 def FinishInterface(self):
330 template = None
331 if self._html_interface_name == self._interface.id or not self._database.Has Interface(self._html_interface_name):
332 template_file = 'impl_%s.darttemplate' % self._html_interface_name
333 template = self._system._templates.TryLoad(template_file)
334 if not template:
335 template = self._system._templates.Load('dart_implementation.darttemplate' )
336
337 class_name = self._ImplClassName(self._interface.id)
338 members_emitter = self._dart_impl_emitter.Emit(
339 template,
340 CLASSNAME=class_name,
341 EXTENDS=' extends ' + self._BaseClassName(),
342 IMPLEMENTS=' implements ' + self._html_interface_name,
343 NATIVESPEC='')
344 members_emitter.Emit(''.join(self._members_emitter.Fragments()))
345
346 self._GenerateCppHeader()
347
348 self._cpp_impl_emitter.Emit(
349 self._system._templates.Load('cpp_implementation.template'),
350 INTERFACE=self._interface.id,
351 INCLUDES=_GenerateCPPIncludes(self._cpp_impl_includes),
352 CALLBACKS=self._cpp_definitions_emitter.Fragments(),
353 RESOLVER=self._cpp_resolver_emitter.Fragments(),
354 DART_IMPLEMENTATION_CLASS=class_name)
355
356 def _GenerateCppHeader(self):
357 to_native_emitter = emitter.Emitter()
358 if self._interface_type_info.custom_to_native():
359 to_native_emitter.Emit(
360 ' static PassRefPtr<NativeType> toNative(Dart_Handle handle, Dart_H andle& exception);\n')
361 else:
362 to_native_emitter.Emit(
363 ' static NativeType* toNative(Dart_Handle handle, Dart_Handle& exce ption)\n'
364 ' {\n'
365 ' return DartDOMWrapper::unwrapDartWrapper<Dart$INTERFACE>(hand le, exception);\n'
366 ' }\n',
367 INTERFACE=self._interface.id)
368
369 to_dart_emitter = emitter.Emitter()
370
371 ext_attrs = self._interface.ext_attrs
372
373 if ('CustomToJS' in ext_attrs or
374 ('CustomToJSObject' in ext_attrs and 'TypedArray' not in ext_attrs) or
375 'PureInterface' in ext_attrs or
376 'CPPPureInterface' in ext_attrs or
377 self._interface_type_info.custom_to_dart()):
378 to_dart_emitter.Emit(
379 ' static Dart_Handle toDart(NativeType* value);\n')
380 else:
381 to_dart_emitter.Emit(
382 ' static Dart_Handle toDart(NativeType* value)\n'
383 ' {\n'
384 ' return DartDOMWrapper::toDart<Dart$(INTERFACE)>(value);\n'
385 ' }\n',
386 INTERFACE=self._interface.id)
387
388 webcore_includes = _GenerateCPPIncludes(self._interface_type_info.webcore_in cludes())
389
390 is_node_test = lambda interface: interface.id == 'Node'
391 is_active_test = lambda interface: 'ActiveDOMObject' in interface.ext_attrs
392 is_event_target_test = lambda interface: 'EventTarget' in interface.ext_attr s
393 def TypeCheckHelper(test):
394 return 'true' if any(map(test, self._database.Hierarchy(self._interface))) else 'false'
395
396 self._cpp_header_emitter.Emit(
397 self._system._templates.Load('cpp_header.template'),
398 INTERFACE=self._interface.id,
399 WEBCORE_INCLUDES=webcore_includes,
400 WEBCORE_CLASS_NAME=self._interface_type_info.native_type(),
401 DECLARATIONS=self._cpp_declarations_emitter.Fragments(),
402 IS_NODE=TypeCheckHelper(is_node_test),
403 IS_ACTIVE=TypeCheckHelper(is_active_test),
404 IS_EVENT_TARGET=TypeCheckHelper(is_event_target_test),
405 TO_NATIVE=to_native_emitter.Fragments(),
406 TO_DART=to_dart_emitter.Fragments())
407
408 def AddAttribute(self, attribute, html_name, read_only):
409 if 'CheckSecurityForNode' in attribute.ext_attrs:
410 # FIXME: exclude from interface as well.
411 return
412
413 self._AddGetter(attribute, html_name)
414 if not read_only:
415 self._AddSetter(attribute, html_name)
416
417 def _AddGetter(self, attr, html_name):
418 type_info = self._TypeInfo(attr.type.id)
419 dart_declaration = '%s get %s()' % (self._DartType(attr.type.id), html_name)
420 is_custom = 'Custom' in attr.ext_attrs or 'CustomGetter' in attr.ext_attrs
421 cpp_callback_name = self._GenerateNativeBinding(attr.id, 1,
422 dart_declaration, 'Getter', is_custom)
423 if is_custom:
424 return
425
426 if 'Reflect' in attr.ext_attrs:
427 webcore_function_name = self._TypeInfo(attr.type.id).webcore_getter_name()
428 if 'URL' in attr.ext_attrs:
429 if 'NonEmpty' in attr.ext_attrs:
430 webcore_function_name = 'getNonEmptyURLAttribute'
431 else:
432 webcore_function_name = 'getURLAttribute'
433 elif 'ImplementedAs' in attr.ext_attrs:
434 webcore_function_name = attr.ext_attrs['ImplementedAs']
435 else:
436 if attr.id == 'operator':
437 webcore_function_name = '_operator'
438 elif attr.id == 'target' and attr.type.id == 'SVGAnimatedString':
439 webcore_function_name = 'svgTarget'
440 else:
441 webcore_function_name = _ToWebKitName(attr.id)
442 if attr.type.id.startswith('SVGAnimated'):
443 webcore_function_name += 'Animated'
444
445 function_expression = self._GenerateWebCoreFunctionExpression(webcore_functi on_name, attr)
446 self._GenerateNativeCallback(
447 cpp_callback_name,
448 True,
449 function_expression,
450 attr,
451 [],
452 attr.type.id,
453 attr.get_raises)
454
455 def _AddSetter(self, attr, html_name):
456 type_info = self._TypeInfo(attr.type.id)
457 dart_declaration = 'void set %s(%s)' % (html_name, self._DartType(attr.type. id))
458 is_custom = set(['Custom', 'CustomSetter', 'V8CustomSetter']) & set(attr.ext _attrs)
459 cpp_callback_name = self._GenerateNativeBinding(attr.id, 2,
460 dart_declaration, 'Setter', is_custom)
461 if is_custom:
462 return
463
464 if 'Reflect' in attr.ext_attrs:
465 webcore_function_name = self._TypeInfo(attr.type.id).webcore_setter_name()
466 else:
467 webcore_function_name = re.sub(r'^(xml(?=[A-Z])|\w)',
468 lambda s: s.group(1).upper(),
469 attr.id)
470 webcore_function_name = 'set%s' % webcore_function_name
471 if attr.type.id.startswith('SVGAnimated'):
472 webcore_function_name += 'Animated'
473
474 function_expression = self._GenerateWebCoreFunctionExpression(webcore_functi on_name, attr)
475 self._GenerateNativeCallback(
476 cpp_callback_name,
477 True,
478 function_expression,
479 attr,
480 [attr],
481 'void',
482 attr.set_raises)
483
484 def AddIndexer(self, element_type):
485 """Adds all the methods required to complete implementation of List."""
486 # We would like to simply inherit the implementation of everything except
487 # get length(), [], and maybe []=. It is possible to extend from a base
488 # array implementation class only when there is no other implementation
489 # inheritance. There might be no implementation inheritance other than
490 # DOMBaseWrapper for many classes, but there might be some where the
491 # array-ness is introduced by a non-root interface:
492 #
493 # interface Y extends X, List<T> ...
494 #
495 # In the non-root case we have to choose between:
496 #
497 # class YImpl extends XImpl { add List<T> methods; }
498 #
499 # and
500 #
501 # class YImpl extends ListBase<T> { copies of transitive XImpl methods; }
502 #
503 dart_element_type = self._DartType(element_type)
504 if self._HasNativeIndexGetter():
505 self._EmitNativeIndexGetter(dart_element_type)
506 else:
507 self._members_emitter.Emit(
508 '\n'
509 ' $TYPE operator[](int index) native "$(INTERFACE)_item_Callback";\n' ,
510 TYPE=dart_element_type, INTERFACE=self._interface.id)
511
512 if self._HasNativeIndexSetter():
513 self._EmitNativeIndexSetter(dart_element_type)
514 else:
515 # The HTML library implementation of NodeList has a custom indexed setter
516 # implementation that uses the parent node the NodeList is associated
517 # with if one is available.
518 if self._interface.id != 'NodeList':
519 self._members_emitter.Emit(
520 '\n'
521 ' void operator[]=(int index, $TYPE value) {\n'
522 ' throw new UnsupportedOperationException("Cannot assign element of immutable List.");\n'
523 ' }\n',
524 TYPE=dart_element_type)
525
526 # The list interface for this class is manually generated.
527 if self._interface.id == 'NodeList':
528 return
529
530 # TODO(sra): Use separate mixins for mutable implementations of List<T>.
531 # TODO(sra): Use separate mixins for typed array implementations of List<T>.
532 template_file = 'immutable_list_mixin.darttemplate'
533 template = self._system._templates.Load(template_file)
534 self._members_emitter.Emit(template, E=dart_element_type)
535
536 def AmendIndexer(self, element_type):
537 # If interface is marked as having native indexed
538 # getter or setter, we must emit overrides as it's not
539 # guaranteed that the corresponding methods in C++ would be
540 # virtual. For example, as of time of writing, even though
541 # Uint8ClampedArray inherits from Uint8Array, ::set method
542 # is not virtual and accessing it through Uint8Array pointer
543 # would lead to wrong semantics (modulo vs. clamping.)
544 dart_element_type = self._DartType(element_type)
545
546 if self._HasNativeIndexGetter():
547 self._EmitNativeIndexGetter(dart_element_type)
548 if self._HasNativeIndexSetter():
549 self._EmitNativeIndexSetter(dart_element_type)
550
551 def _HasNativeIndexGetter(self):
552 ext_attrs = self._interface.ext_attrs
553 return ('CustomIndexedGetter' in ext_attrs or
554 'NumericIndexedGetter' in ext_attrs)
555
556 def _EmitNativeIndexGetter(self, element_type):
557 dart_declaration = '%s operator[](int index)' % element_type
558 self._GenerateNativeBinding('numericIndexGetter', 2, dart_declaration,
559 'Callback', True)
560
561 def _HasNativeIndexSetter(self):
562 return 'CustomIndexedSetter' in self._interface.ext_attrs
563
564 def _EmitNativeIndexSetter(self, element_type):
565 dart_declaration = 'void operator[]=(int index, %s value)' % element_type
566 self._GenerateNativeBinding('numericIndexSetter', 3, dart_declaration,
567 'Callback', True)
568
569 def AddOperation(self, info, html_name):
570 """
571 Arguments:
572 info: An OperationInfo object.
573 """
574
575 operation = info.operations[0]
576
577 if 'CheckSecurityForNode' in operation.ext_attrs:
578 # FIXME: exclude from interface as well.
579 return
580
581 is_custom = 'Custom' in operation.ext_attrs
582 has_optional_arguments = any(self._IsArgumentOptionalInWebCore(operation, ar gument) for argument in operation.arguments)
583 needs_dispatcher = not is_custom and (len(info.operations) > 1 or has_option al_arguments)
584
585 if not needs_dispatcher:
586 type_renamer = self._DartType
587 default_value = 'null'
588 else:
589 type_renamer = lambda x: 'Dynamic'
590 default_value = '_null'
591
592 dart_declaration = '%s%s %s(%s)' % (
593 'static ' if info.IsStatic() else '',
594 self._DartType(info.type_name),
595 html_name,
596 info.ParametersImplementationDeclaration(type_renamer, default_value))
597
598 if not needs_dispatcher:
599 # Bind directly to native implementation
600 argument_count = (0 if info.IsStatic() else 1) + len(info.param_infos)
601 cpp_callback_name = self._GenerateNativeBinding(
602 info.name, argument_count, dart_declaration, 'Callback', is_custom)
603 if not is_custom:
604 self._GenerateOperationNativeCallback(operation, operation.arguments, cp p_callback_name)
605 else:
606 self._GenerateDispatcher(info.operations, dart_declaration, [info.name for info in info.param_infos])
607
608 def _GenerateDispatcher(self, operations, dart_declaration, argument_names):
609
610 body = self._members_emitter.Emit(
611 '\n'
612 ' $DECLARATION {\n'
613 '$!BODY'
614 ' }\n',
615 DECLARATION=dart_declaration)
616
617 version = [1]
618 def GenerateCall(operation, argument_count, checks):
619 if checks:
620 if operation.type.id != 'void':
621 template = ' if ($CHECKS) {\n return $CALL;\n }\n'
622 else:
623 template = ' if ($CHECKS) {\n $CALL;\n return;\n }\n'
624 else:
625 if operation.type.id != 'void':
626 template = ' return $CALL;\n'
627 else:
628 template = ' $CALL;\n'
629
630 overload_name = '%s_%s' % (operation.id, version[0])
631 version[0] += 1
632 argument_list = ', '.join(argument_names[:argument_count])
633 call = '_%s(%s)' % (overload_name, argument_list)
634 body.Emit(template, CHECKS=' && '.join(checks), CALL=call)
635
636 dart_declaration = '%s%s _%s(%s)' % (
637 'static ' if operation.is_static else '',
638 self._DartType(operation.type.id), overload_name, argument_list)
639 cpp_callback_name = self._GenerateNativeBinding(
640 overload_name, (0 if operation.is_static else 1) + argument_count,
641 dart_declaration, 'Callback', False)
642 self._GenerateOperationNativeCallback(operation, operation.arguments[:argu ment_count], cpp_callback_name)
643
644 def GenerateChecksAndCall(operation, argument_count):
645 checks = ['%s === _null' % name for name in argument_names]
646 for i in range(0, argument_count):
647 argument = operation.arguments[i]
648 argument_name = argument_names[i]
649 checks[i] = '(%s is %s || %s === null)' % (
650 argument_name, self._DartType(argument.type.id), argument_name)
651 GenerateCall(operation, argument_count, checks)
652
653 # TODO: Optimize the dispatch to avoid repeated checks.
654 if len(operations) > 1:
655 for operation in operations:
656 for position, argument in enumerate(operation.arguments):
657 if self._IsArgumentOptionalInWebCore(operation, argument):
658 GenerateChecksAndCall(operation, position)
659 GenerateChecksAndCall(operation, len(operation.arguments))
660 body.Emit(' throw "Incorrect number or type of arguments";\n');
661 else:
662 operation = operations[0]
663 argument_count = len(operation.arguments)
664 for position, argument in list(enumerate(operation.arguments))[::-1]:
665 if self._IsArgumentOptionalInWebCore(operation, argument):
666 check = '%s !== _null' % argument_names[position]
667 # argument_count instead of position + 1 is used here to cover one
668 # complicated case with the effectively optional argument in the middl e.
669 # Consider foo(x, [Optional] y, [Optional=DefaultIsNullString] z)
670 # (as of now it's modelled after HTMLMediaElement.webkitAddKey).
671 # y is optional in WebCore, while z is not.
672 # In this case, if y !== _null, we'd like to emit foo(x, y, z) invocat ion, not
673 # foo(x, y).
674 GenerateCall(operation, argument_count, [check])
675 argument_count = position
676 GenerateCall(operation, argument_count, [])
677
678 def SecondaryContext(self, interface):
679 pass
680
681 def _GenerateOperationNativeCallback(self, operation, arguments, cpp_callback_ name):
682 webcore_function_name = operation.ext_attrs.get('ImplementedAs', operation.i d)
683 function_expression = self._GenerateWebCoreFunctionExpression(webcore_functi on_name, operation)
684 self._GenerateNativeCallback(
685 cpp_callback_name,
686 not operation.is_static,
687 function_expression,
688 operation,
689 arguments,
690 operation.type.id,
691 operation.raises)
692
693 def _GenerateNativeCallback(self,
694 callback_name,
695 needs_receiver,
696 function_expression,
697 node,
698 arguments,
699 return_type,
700 raises_dom_exception):
701 ext_attrs = node.ext_attrs
702
703 cpp_arguments = []
704 requires_v8_scope = \
705 any((self._TypeInfo(argument.type.id).requires_v8_scope() for argument i n arguments))
706 runtime_check = None
707 raises_exceptions = raises_dom_exception or arguments
708
709 requires_stack_info = ext_attrs.get('CallWith') == 'ScriptArguments|CallStac k'
710 if requires_stack_info:
711 raises_exceptions = True
712 requires_v8_scope = True
713 cpp_arguments = ['scriptArguments', 'scriptCallStack']
714 # WebKit uses scriptArguments to reconstruct last argument, so
715 # it's not needed and should be just removed.
716 arguments = arguments[:-1]
717
718 requires_script_execution_context = ext_attrs.get('CallWith') == 'ScriptExec utionContext'
719 if requires_script_execution_context:
720 raises_exceptions = True
721 cpp_arguments = ['context']
722
723 requires_dom_window = 'NamedConstructor' in ext_attrs
724 if requires_dom_window:
725 raises_exceptions = True
726 cpp_arguments = ['document']
727
728 if 'ImplementedBy' in ext_attrs:
729 assert needs_receiver
730 self._cpp_impl_includes.add('"%s.h"' % ext_attrs['ImplementedBy'])
731 cpp_arguments.append('receiver')
732
733 if 'Reflect' in ext_attrs:
734 cpp_arguments = [self._GenerateWebCoreReflectionAttributeName(node)]
735
736 v8EnabledPerContext = ext_attrs.get('synthesizedV8EnabledPerContext', ext_at trs.get('V8EnabledPerContext'))
737 v8EnabledAtRuntime = ext_attrs.get('synthesizedV8EnabledAtRuntime', ext_attr s.get('V8EnabledAtRuntime'))
738 assert(not (v8EnabledPerContext and v8EnabledAtRuntime))
739
740 if v8EnabledPerContext:
741 raises_exceptions = True
742 self._cpp_impl_includes.add('"ContextFeatures.h"')
743 self._cpp_impl_includes.add('"DOMWindow.h"')
744 runtime_check = emitter.Format(
745 ' if (!ContextFeatures::$(FEATURE)Enabled(DartUtilities::domWin dowForCurrentIsolate()->document())) {\n'
746 ' exception = Dart_NewString("Feature $FEATURE is not enabl ed");\n'
747 ' goto fail;\n'
748 ' }',
749 FEATURE=v8EnabledPerContext)
750
751 if v8EnabledAtRuntime:
752 raises_exceptions = True
753 self._cpp_impl_includes.add('"RuntimeEnabledFeatures.h"')
754 runtime_check = emitter.Format(
755 ' if (!RuntimeEnabledFeatures::$(FEATURE)Enabled()) {\n'
756 ' exception = Dart_NewString("Feature $FEATURE is not enabl ed");\n'
757 ' goto fail;\n'
758 ' }',
759 FEATURE=_ToWebKitName(v8EnabledAtRuntime))
760
761 body_emitter = self._cpp_definitions_emitter.Emit(
762 '\n'
763 'static void $CALLBACK_NAME(Dart_NativeArguments args)\n'
764 '{\n'
765 ' DartApiScope dartApiScope;\n'
766 '$!BODY'
767 '}\n',
768 CALLBACK_NAME=callback_name)
769
770 if raises_exceptions:
771 body_emitter = body_emitter.Emit(
772 ' Dart_Handle exception = 0;\n'
773 '$!BODY'
774 '\n'
775 'fail:\n'
776 ' Dart_ThrowException(exception);\n'
777 ' ASSERT_NOT_REACHED();\n')
778
779 body_emitter = body_emitter.Emit(
780 ' {\n'
781 '$!BODY'
782 ' return;\n'
783 ' }\n')
784
785 if requires_v8_scope:
786 body_emitter.Emit(
787 ' V8Scope v8scope;\n\n')
788
789 if runtime_check:
790 body_emitter.Emit(
791 '$RUNTIME_CHECK\n',
792 RUNTIME_CHECK=runtime_check)
793
794 if requires_script_execution_context:
795 body_emitter.Emit(
796 ' ScriptExecutionContext* context = DartUtilities::scriptExecut ionContext();\n'
797 ' if (!context) {\n'
798 ' exception = Dart_NewString("Failed to retrieve a context" );\n'
799 ' goto fail;\n'
800 ' }\n\n')
801
802 if requires_dom_window:
803 self._cpp_impl_includes.add('"DOMWindow.h"')
804 body_emitter.Emit(
805 ' DOMWindow* domWindow = DartUtilities::domWindowForCurrentIsol ate();\n'
806 ' if (!domWindow) {\n'
807 ' exception = Dart_NewString("Failed to fetch domWindow");\ n'
808 ' goto fail;\n'
809 ' }\n'
810 ' Document* document = domWindow->document();\n')
811
812 if needs_receiver:
813 body_emitter.Emit(
814 ' $WEBCORE_CLASS_NAME* receiver = DartDOMWrapper::receiver< $WE BCORE_CLASS_NAME >(args);\n',
815 WEBCORE_CLASS_NAME=self._interface_type_info.native_type())
816
817 if requires_stack_info:
818 self._cpp_impl_includes.add('"ScriptArguments.h"')
819 self._cpp_impl_includes.add('"ScriptCallStack.h"')
820 body_emitter.Emit(
821 '\n'
822 ' Dart_Handle customArgument = Dart_GetNativeArgument(args, $IN DEX);\n'
823 ' RefPtr<ScriptArguments> scriptArguments(DartUtilities::create ScriptArguments(customArgument, exception));\n'
824 ' if (!scriptArguments)\n'
825 ' goto fail;\n'
826 ' RefPtr<ScriptCallStack> scriptCallStack(DartUtilities::create ScriptCallStack());\n'
827 ' if (!scriptCallStack->size())\n'
828 ' return;\n',
829 INDEX=len(arguments) + 1)
830
831 # Emit arguments.
832 start_index = 1 if needs_receiver else 0
833 for i, argument in enumerate(arguments):
834 argument_expression_template, type, cls, function = \
835 self._TypeInfo(argument.type.id).to_native_info(argument, self._interf ace.id)
836
837 if ((IsOptional(argument) and not self._IsArgumentOptionalInWebCore(node, argument)) or
838 (argument.ext_attrs.get('Optional') == 'DefaultIsNullString')):
839 function += 'WithNullCheck'
840
841 argument_name = DartDomNameOfAttribute(argument)
842 body_emitter.Emit(
843 '\n'
844 ' $TYPE $ARGUMENT_NAME = $CLS::$FUNCTION(Dart_GetNativeArgument (args, $INDEX), exception);\n'
845 ' if (exception)\n'
846 ' goto fail;\n',
847 TYPE=type,
848 ARGUMENT_NAME=argument_name,
849 CLS=cls,
850 FUNCTION=function,
851 INDEX=start_index + i)
852 self._cpp_impl_includes.add('"%s.h"' % cls)
853 cpp_arguments.append(argument_expression_template % argument_name)
854
855 body_emitter.Emit('\n')
856
857 if 'NeedsUserGestureCheck' in ext_attrs:
858 cpp_arguments.append('DartUtilities::processingUserGesture')
859
860 invocation_emitter = body_emitter
861 if raises_dom_exception:
862 cpp_arguments.append('ec')
863 invocation_emitter = body_emitter.Emit(
864 ' ExceptionCode ec = 0;\n'
865 '$!INVOCATION'
866 ' if (UNLIKELY(ec)) {\n'
867 ' exception = DartDOMWrapper::exceptionCodeToDartException(ec );\n'
868 ' goto fail;\n'
869 ' }\n')
870
871 function_call = '%s(%s)' % (function_expression, ', '.join(cpp_arguments))
872 if return_type == 'void':
873 invocation_emitter.Emit(
874 ' $FUNCTION_CALL;\n',
875 FUNCTION_CALL=function_call)
876 else:
877 return_type_info = self._TypeInfo(return_type)
878 self._cpp_impl_includes |= set(return_type_info.conversion_includes())
879
880 # Generate to Dart conversion of C++ value.
881 to_dart_conversion = return_type_info.to_dart_conversion(function_call, se lf._interface.id, ext_attrs)
882 invocation_emitter.Emit(
883 ' Dart_Handle returnValue = $TO_DART_CONVERSION;\n'
884 ' if (returnValue)\n'
885 ' Dart_SetReturnValue(args, returnValue);\n',
886 TO_DART_CONVERSION=to_dart_conversion)
887
888 def _GenerateNativeBinding(self, idl_name, argument_count, dart_declaration,
889 native_suffix, is_custom):
890 native_binding = '%s_%s_%s' % (self._interface.id, idl_name, native_suffix)
891 self._members_emitter.Emit(
892 '\n'
893 ' $DART_DECLARATION native "$NATIVE_BINDING";\n',
894 DART_DECLARATION=dart_declaration, NATIVE_BINDING=native_binding)
895
896 cpp_callback_name = '%s%s' % (idl_name, native_suffix)
897 self._cpp_resolver_emitter.Emit(
898 ' if (argumentCount == $ARGC && name == "$NATIVE_BINDING")\n'
899 ' return Dart$(INTERFACE_NAME)Internal::$CPP_CALLBACK_NAME;\n',
900 ARGC=argument_count,
901 NATIVE_BINDING=native_binding,
902 INTERFACE_NAME=self._interface.id,
903 CPP_CALLBACK_NAME=cpp_callback_name)
904
905 if is_custom:
906 self._cpp_declarations_emitter.Emit(
907 '\n'
908 'void $CPP_CALLBACK_NAME(Dart_NativeArguments);\n',
909 CPP_CALLBACK_NAME=cpp_callback_name)
910
911 return cpp_callback_name
912
913 def _GenerateWebCoreReflectionAttributeName(self, attr):
914 namespace = 'HTMLNames'
915 svg_exceptions = ['class', 'id', 'onabort', 'onclick', 'onerror', 'onload',
916 'onmousedown', 'onmousemove', 'onmouseout', 'onmouseover',
917 'onmouseup', 'onresize', 'onscroll', 'onunload']
918 if self._interface.id.startswith('SVG') and not attr.id in svg_exceptions:
919 namespace = 'SVGNames'
920 self._cpp_impl_includes.add('"%s.h"' % namespace)
921
922 attribute_name = attr.ext_attrs['Reflect'] or attr.id.lower()
923 return 'WebCore::%s::%sAttr' % (namespace, attribute_name)
924
925 def _GenerateWebCoreFunctionExpression(self, function_name, idl_node):
926 if 'ImplementedBy' in idl_node.ext_attrs:
927 return '%s::%s' % (idl_node.ext_attrs['ImplementedBy'], function_name)
928 if idl_node.is_static:
929 return '%s::%s' % (self._interface_type_info.idl_type(), function_name)
930 return '%s%s' % (self._interface_type_info.receiver(), function_name)
931
932 def _TypeInfo(self, type_name):
933 return self._system._type_registry.TypeInfo(type_name)
934
935 def _IsArgumentOptionalInWebCore(self, operation, argument):
936 if not IsOptional(argument):
937 return False
938 if 'Callback' in argument.ext_attrs:
939 return False
940 if operation.id in ['addEventListener', 'removeEventListener'] and argument. id == 'useCapture':
941 return False
942 # Another option would be to adjust in IDLs, but let's keep it here for now
943 # as it's a single instance.
944 if self._interface.id == 'CSSStyleDeclaration' and operation.id == 'setPrope rty' and argument.id == 'priority':
945 return False
946 return True
947
948
949 def _GenerateCPPIncludes(includes):
950 return ''.join(['#include %s\n' % include for include in sorted(includes)])
951
952 def _FindInHierarchy(database, interface, test):
953 if test(interface):
954 return interface
955 for parent in interface.parents:
956 parent_name = parent.type.id
957 if not database.HasInterface(parent.type.id):
958 continue
959 parent_interface = database.GetInterface(parent.type.id)
960 parent_interface = _FindInHierarchy(database, parent_interface, test)
961 if parent_interface:
962 return parent_interface
963
964 def _ToWebKitName(name):
965 name = name[0].lower() + name[1:]
966 name = re.sub(r'^(hTML|uRL|jS|xML|xSLT)', lambda s: s.group(1).lower(),
967 name)
968 return re.sub(r'^(create|exclusive)', lambda s: 'is' + s.group(1).capitalize() ,
969 name)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698