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

Side by Side Diff: sdk/lib/html/scripts/systemnative.py

Issue 11691009: Moved most of html lib generating scripts into tools. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 11 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
« no previous file with comments | « sdk/lib/html/scripts/systemhtml.py ('k') | sdk/lib/html/scripts/templateloader.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 #!/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 from generator import *
12 from htmldartgenerator import *
13
14 class DartiumBackend(HtmlDartGenerator):
15 """Generates Dart implementation for one DOM IDL interface."""
16
17 def __init__(self, interface, cpp_library_emitter, options):
18 super(DartiumBackend, self).__init__(interface, options)
19
20 self._interface = interface
21 self._cpp_library_emitter = cpp_library_emitter
22 self._database = options.database
23 self._template_loader = options.templates
24 self._type_registry = options.type_registry
25 self._interface_type_info = self._type_registry.TypeInfo(self._interface.id)
26
27 def ImplementsMergedMembers(self):
28 # We could not add merged functions to implementation class because
29 # underlying c++ object doesn't implement them. Merged functions are
30 # generated on merged interface implementation instead.
31 return False
32
33 def CustomJSMembers(self):
34 return {}
35
36 def GenerateCallback(self, info):
37 if IsPureInterface(self._interface.id):
38 return
39
40 cpp_impl_includes = set()
41 cpp_header_handlers_emitter = emitter.Emitter()
42 cpp_impl_handlers_emitter = emitter.Emitter()
43 class_name = 'Dart%s' % self._interface.id
44 for operation in self._interface.operations:
45 parameters = []
46 arguments = []
47 conversion_includes = []
48 for argument in operation.arguments:
49 argument_type_info = self._TypeInfo(argument.type.id)
50 parameters.append('%s %s' % (argument_type_info.parameter_type(),
51 argument.id))
52 arguments.append(argument_type_info.to_dart_conversion(argument.id))
53 conversion_includes.extend(argument_type_info.conversion_includes())
54
55 cpp_header_handlers_emitter.Emit(
56 '\n'
57 ' virtual bool handleEvent($PARAMETERS);\n',
58 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 'bool $CLASS_NAME::handleEvent($PARAMETERS)\n'
70 '{\n'
71 ' if (!m_callback.isIsolateAlive())\n'
72 ' return false;\n'
73 ' DartIsolateScope scope(m_callback.isolate());\n'
74 ' DartApiScope apiScope;\n'
75 ' $ARGUMENTS_DECLARATION;\n'
76 ' return m_callback.handleEvent($ARGUMENT_COUNT, arguments);\n'
77 '}\n',
78 CLASS_NAME=class_name,
79 PARAMETERS=', '.join(parameters),
80 ARGUMENTS_DECLARATION=arguments_declaration,
81 ARGUMENT_COUNT=len(arguments))
82
83 cpp_header_emitter = self._cpp_library_emitter.CreateHeaderEmitter(
84 self._interface.id,
85 self._renamer.GetLibraryName(self._interface),
86 True)
87 cpp_header_emitter.Emit(
88 self._template_loader.Load('cpp_callback_header.template'),
89 INTERFACE=self._interface.id,
90 HANDLERS=cpp_header_handlers_emitter.Fragments())
91
92 cpp_impl_emitter = self._cpp_library_emitter.CreateSourceEmitter(self._inter face.id)
93 cpp_impl_emitter.Emit(
94 self._template_loader.Load('cpp_callback_implementation.template'),
95 INCLUDES=self._GenerateCPPIncludes(cpp_impl_includes),
96 INTERFACE=self._interface.id,
97 HANDLERS=cpp_impl_handlers_emitter.Fragments())
98
99 def ImplementationTemplate(self):
100 template = None
101 interface_name = self._interface.doc_js_name
102 if interface_name == self._interface.id or not self._database.HasInterface(i nterface_name):
103 template_file = 'impl_%s.darttemplate' % interface_name
104 template = self._template_loader.TryLoad(template_file)
105 if not template:
106 template = self._template_loader.Load('dart_implementation.darttemplate')
107 return template
108
109 def RootClassName(self):
110 return 'NativeFieldWrapperClass1'
111
112 def NativeSpec(self):
113 return ''
114
115 def StartInterface(self, memebers_emitter):
116 # Create emitters for c++ implementation.
117 if not IsPureInterface(self._interface.id):
118 self._cpp_header_emitter = self._cpp_library_emitter.CreateHeaderEmitter(
119 self._interface.id,
120 self._renamer.GetLibraryName(self._interface))
121 self._cpp_impl_emitter = self._cpp_library_emitter.CreateSourceEmitter(sel f._interface.id)
122 else:
123 self._cpp_header_emitter = emitter.Emitter()
124 self._cpp_impl_emitter = emitter.Emitter()
125
126 self._interface_type_info = self._TypeInfo(self._interface.id)
127 self._members_emitter = memebers_emitter
128 self._cpp_declarations_emitter = emitter.Emitter()
129 self._cpp_impl_includes = set()
130 self._cpp_definitions_emitter = emitter.Emitter()
131 self._cpp_resolver_emitter = emitter.Emitter()
132
133 # We need to revisit our treatment of typed arrays, right now
134 # it is full of hacks.
135 if self._interface.ext_attrs.get('ConstructorTemplate') == 'TypedArray':
136 self._cpp_resolver_emitter.Emit(
137 ' if (name == "$(INTERFACE_NAME)_constructor_Callback")\n'
138 ' return Dart$(INTERFACE_NAME)Internal::constructorCallback;\n' ,
139 INTERFACE_NAME=self._interface.id)
140
141 self._cpp_impl_includes.add('"DartArrayBufferViewCustom.h"');
142 self._cpp_definitions_emitter.Emit(
143 '\n'
144 'static void constructorCallback(Dart_NativeArguments args)\n'
145 '{\n'
146 ' WebCore::DartArrayBufferViewInternal::constructWebGLArray<Dart$(INT ERFACE_NAME)>(args);\n'
147 '}\n',
148 INTERFACE_NAME=self._interface.id);
149
150 def EmitHelpers(self, base_class):
151 # Emit internal constructor which is necessary for Dartium bindings
152 # to construct wrappers from C++. Eventually it should go away
153 # once it is possible to construct such an instance directly.
154 super_constructor = ''
155 if base_class and base_class != 'NativeFieldWrapperClass1':
156 super_constructor = ' : super.internal()'
157 self._members_emitter.Emit(
158 ' $CLASSNAME.internal()$SUPERCONSTRUCTOR;\n',
159 CLASSNAME=self._interface_type_info.implementation_name(),
160 SUPERCONSTRUCTOR=super_constructor)
161
162 def EmitStaticFactory(self, constructor_info):
163 constructor_callback_id = self._interface.id + '_constructor_Callback'
164
165 self._members_emitter.Emit(
166 ' static $INTERFACE_NAME _create($PARAMETERS_DECLARATION) '
167 'native "$CONSTRUCTOR_CALLBACK_ID";\n',
168 INTERFACE_NAME=self._interface_type_info.interface_name(),
169 PARAMETERS_DECLARATION=constructor_info.ParametersDeclaration(
170 self._DartType),
171 CONSTRUCTOR_CALLBACK_ID=constructor_callback_id)
172
173 # TODO(antonm): currently we don't have information about number of argument s expected by
174 # the constructor, so name only dispatch.
175 self._cpp_resolver_emitter.Emit(
176 ' if (name == "$CONSTRUCTOR_CALLBACK_ID")\n'
177 ' return Dart$(WEBKIT_INTERFACE_NAME)Internal::constructorCallbac k;\n',
178 CONSTRUCTOR_CALLBACK_ID=constructor_callback_id,
179 WEBKIT_INTERFACE_NAME=self._interface.id)
180
181 ext_attrs = self._interface.ext_attrs
182
183 if 'CustomConstructor' in ext_attrs:
184 # We have a custom implementation for it.
185 self._cpp_declarations_emitter.Emit(
186 '\n'
187 'void constructorCallback(Dart_NativeArguments);\n')
188 return
189
190 create_function = 'create'
191 if 'NamedConstructor' in ext_attrs:
192 create_function = 'createForJSConstructor'
193 function_expression = '%s::%s' % (self._interface_type_info.native_type(), c reate_function)
194 self._GenerateNativeCallback(
195 'constructorCallback',
196 False,
197 function_expression,
198 self._interface,
199 constructor_info.idl_args,
200 self._interface.id,
201 'ConstructorRaisesException' in ext_attrs)
202
203 def FinishInterface(self):
204 self._GenerateCPPHeader()
205
206 self._cpp_impl_emitter.Emit(
207 self._template_loader.Load('cpp_implementation.template'),
208 INTERFACE=self._interface.id,
209 INCLUDES=self._GenerateCPPIncludes(self._cpp_impl_includes),
210 CALLBACKS=self._cpp_definitions_emitter.Fragments(),
211 RESOLVER=self._cpp_resolver_emitter.Fragments(),
212 DART_IMPLEMENTATION_CLASS=self._interface_type_info.implementation_name( ),
213 DART_IMPLEMENTATION_LIBRARY='dart:%s' % self._renamer.GetLibraryName(sel f._interface))
214
215 def _GenerateCPPHeader(self):
216 to_native_emitter = emitter.Emitter()
217 if self._interface_type_info.custom_to_native():
218 to_native_emitter.Emit(
219 ' static PassRefPtr<NativeType> toNative(Dart_Handle handle, Dart_H andle& exception);\n')
220 else:
221 to_native_emitter.Emit(
222 ' static NativeType* toNative(Dart_Handle handle, Dart_Handle& exce ption)\n'
223 ' {\n'
224 ' return DartDOMWrapper::unwrapDartWrapper<Dart$INTERFACE>(hand le, exception);\n'
225 ' }\n',
226 INTERFACE=self._interface.id)
227
228 to_dart_emitter = emitter.Emitter()
229
230 ext_attrs = self._interface.ext_attrs
231
232 if ('CustomToJS' in ext_attrs or
233 ('CustomToJSObject' in ext_attrs and 'TypedArray' not in ext_attrs) or
234 'PureInterface' in ext_attrs or
235 'CPPPureInterface' in ext_attrs or
236 self._interface_type_info.custom_to_dart()):
237 to_dart_emitter.Emit(
238 ' static Dart_Handle toDart(NativeType* value);\n')
239 else:
240 to_dart_emitter.Emit(
241 ' static Dart_Handle toDart(NativeType* value)\n'
242 ' {\n'
243 ' return DartDOMWrapper::toDart<Dart$(INTERFACE)>(value);\n'
244 ' }\n',
245 INTERFACE=self._interface.id)
246
247 webcore_includes = self._GenerateCPPIncludes(
248 self._interface_type_info.webcore_includes())
249
250 is_node_test = lambda interface: interface.id == 'Node'
251 is_active_test = lambda interface: 'ActiveDOMObject' in interface.ext_attrs
252 is_event_target_test = lambda interface: 'EventTarget' in interface.ext_attr s
253 def TypeCheckHelper(test):
254 return 'true' if any(map(test, self._database.Hierarchy(self._interface))) else 'false'
255
256 self._cpp_header_emitter.Emit(
257 self._template_loader.Load('cpp_header.template'),
258 INTERFACE=self._interface.id,
259 WEBCORE_INCLUDES=webcore_includes,
260 WEBCORE_CLASS_NAME=self._interface_type_info.native_type(),
261 DECLARATIONS=self._cpp_declarations_emitter.Fragments(),
262 IS_NODE=TypeCheckHelper(is_node_test),
263 IS_ACTIVE=TypeCheckHelper(is_active_test),
264 IS_EVENT_TARGET=TypeCheckHelper(is_event_target_test),
265 TO_NATIVE=to_native_emitter.Fragments(),
266 TO_DART=to_dart_emitter.Fragments())
267
268 def EmitAttribute(self, attribute, html_name, read_only):
269 self._AddGetter(attribute, html_name)
270 if not read_only:
271 self._AddSetter(attribute, html_name)
272
273 def _AddGetter(self, attr, html_name):
274 type_info = self._TypeInfo(attr.type.id)
275 dart_declaration = '%s get %s' % (
276 self.SecureOutputType(attr.type.id), html_name)
277 is_custom = 'Custom' in attr.ext_attrs or 'CustomGetter' in attr.ext_attrs
278 cpp_callback_name = self._GenerateNativeBinding(attr.id, 1,
279 dart_declaration, 'Getter', is_custom)
280 if is_custom:
281 return
282
283 if 'Reflect' in attr.ext_attrs:
284 webcore_function_name = self._TypeInfo(attr.type.id).webcore_getter_name()
285 if 'URL' in attr.ext_attrs:
286 if 'NonEmpty' in attr.ext_attrs:
287 webcore_function_name = 'getNonEmptyURLAttribute'
288 else:
289 webcore_function_name = 'getURLAttribute'
290 elif 'ImplementedAs' in attr.ext_attrs:
291 webcore_function_name = attr.ext_attrs['ImplementedAs']
292 else:
293 if attr.id == 'operator':
294 webcore_function_name = '_operator'
295 elif attr.id == 'target' and attr.type.id == 'SVGAnimatedString':
296 webcore_function_name = 'svgTarget'
297 else:
298 webcore_function_name = self._ToWebKitName(attr.id)
299 if attr.type.id.startswith('SVGAnimated'):
300 webcore_function_name += 'Animated'
301
302 function_expression = self._GenerateWebCoreFunctionExpression(webcore_functi on_name, attr)
303 self._GenerateNativeCallback(
304 cpp_callback_name,
305 True,
306 function_expression,
307 attr,
308 [],
309 attr.type.id,
310 attr.get_raises)
311
312 def _AddSetter(self, attr, html_name):
313 type_info = self._TypeInfo(attr.type.id)
314 dart_declaration = 'void set %s(%s value)' % (html_name, self._DartType(attr .type.id))
315 is_custom = set(['Custom', 'CustomSetter', 'V8CustomSetter']) & set(attr.ext _attrs)
316 cpp_callback_name = self._GenerateNativeBinding(attr.id, 2,
317 dart_declaration, 'Setter', is_custom)
318 if is_custom:
319 return
320
321 if 'Reflect' in attr.ext_attrs:
322 webcore_function_name = self._TypeInfo(attr.type.id).webcore_setter_name()
323 else:
324 webcore_function_name = re.sub(r'^(xml(?=[A-Z])|\w)',
325 lambda s: s.group(1).upper(),
326 attr.id)
327 webcore_function_name = 'set%s' % webcore_function_name
328 if attr.type.id.startswith('SVGAnimated'):
329 webcore_function_name += 'Animated'
330
331 function_expression = self._GenerateWebCoreFunctionExpression(webcore_functi on_name, attr)
332 self._GenerateNativeCallback(
333 cpp_callback_name,
334 True,
335 function_expression,
336 attr,
337 [attr],
338 'void',
339 attr.set_raises)
340
341 def AddIndexer(self, element_type):
342 """Adds all the methods required to complete implementation of List."""
343 # We would like to simply inherit the implementation of everything except
344 # length, [], and maybe []=. It is possible to extend from a base
345 # array implementation class only when there is no other implementation
346 # inheritance. There might be no implementation inheritance other than
347 # DOMBaseWrapper for many classes, but there might be some where the
348 # array-ness is introduced by a non-root interface:
349 #
350 # interface Y extends X, List<T> ...
351 #
352 # In the non-root case we have to choose between:
353 #
354 # class YImpl extends XImpl { add List<T> methods; }
355 #
356 # and
357 #
358 # class YImpl extends ListBase<T> { copies of transitive XImpl methods; }
359 #
360 dart_element_type = self._DartType(element_type)
361 if self._HasNativeIndexGetter():
362 self._EmitNativeIndexGetter(dart_element_type)
363 else:
364 self._members_emitter.Emit(
365 '\n'
366 ' $TYPE operator[](int index) native "$(INTERFACE)_item_Callback";\n' ,
367 TYPE=self.SecureOutputType(element_type),
368 INTERFACE=self._interface.id)
369
370 if self._HasNativeIndexSetter():
371 self._EmitNativeIndexSetter(dart_element_type)
372 else:
373 self._members_emitter.Emit(
374 '\n'
375 ' void operator[]=(int index, $TYPE value) {\n'
376 ' throw new UnsupportedError("Cannot assign element of immutable Li st.");\n'
377 ' }\n',
378 TYPE=dart_element_type)
379
380 self.EmitListMixin(dart_element_type)
381
382 def AmendIndexer(self, element_type):
383 # If interface is marked as having native indexed
384 # getter or setter, we must emit overrides as it's not
385 # guaranteed that the corresponding methods in C++ would be
386 # virtual. For example, as of time of writing, even though
387 # Uint8ClampedArray inherits from Uint8Array, ::set method
388 # is not virtual and accessing it through Uint8Array pointer
389 # would lead to wrong semantics (modulo vs. clamping.)
390 dart_element_type = self._DartType(element_type)
391
392 if self._HasNativeIndexGetter():
393 self._EmitNativeIndexGetter(dart_element_type)
394 if self._HasNativeIndexSetter():
395 self._EmitNativeIndexSetter(dart_element_type)
396
397 def _HasNativeIndexGetter(self):
398 ext_attrs = self._interface.ext_attrs
399 return ('CustomIndexedGetter' in ext_attrs or
400 'NumericIndexedGetter' in ext_attrs)
401
402 def _EmitNativeIndexGetter(self, element_type):
403 dart_declaration = '%s operator[](int index)' % \
404 self.SecureOutputType(element_type, True)
405 self._GenerateNativeBinding('numericIndexGetter', 2, dart_declaration,
406 'Callback', True)
407
408 def _HasNativeIndexSetter(self):
409 return 'CustomIndexedSetter' in self._interface.ext_attrs
410
411 def _EmitNativeIndexSetter(self, element_type):
412 dart_declaration = 'void operator[]=(int index, %s value)' % element_type
413 self._GenerateNativeBinding('numericIndexSetter', 3, dart_declaration,
414 'Callback', True)
415
416 def EmitOperation(self, info, html_name):
417 """
418 Arguments:
419 info: An OperationInfo object.
420 """
421
422 operation = info.operations[0]
423
424 is_custom = 'Custom' in operation.ext_attrs
425 has_optional_arguments = any(self._IsArgumentOptionalInWebCore(operation, ar gument) for argument in operation.arguments)
426 needs_dispatcher = not is_custom and (len(info.operations) > 1 or has_option al_arguments)
427
428 dart_declaration = '%s%s %s(%s)' % (
429 'static ' if info.IsStatic() else '',
430 self.SecureOutputType(info.type_name),
431 html_name,
432 info.ParametersDeclaration(
433 (lambda x: 'dynamic') if needs_dispatcher else self._DartType))
434
435 if not needs_dispatcher:
436 # Bind directly to native implementation
437 argument_count = (0 if info.IsStatic() else 1) + len(info.param_infos)
438 cpp_callback_name = self._GenerateNativeBinding(
439 info.name, argument_count, dart_declaration, 'Callback', is_custom)
440 if not is_custom:
441 self._GenerateOperationNativeCallback(operation, operation.arguments, cp p_callback_name)
442 else:
443 self._GenerateDispatcher(info.operations, dart_declaration, [info.name for info in info.param_infos])
444
445 def _GenerateDispatcher(self, operations, dart_declaration, argument_names):
446
447 body = self._members_emitter.Emit(
448 '\n'
449 ' $DECLARATION {\n'
450 '$!BODY'
451 ' }\n',
452 DECLARATION=dart_declaration)
453
454 version = [1]
455 def GenerateCall(operation, argument_count, checks):
456 if checks:
457 if operation.type.id != 'void':
458 template = ' if ($CHECKS) {\n return $CALL;\n }\n'
459 else:
460 template = ' if ($CHECKS) {\n $CALL;\n return;\n }\n'
461 else:
462 if operation.type.id != 'void':
463 template = ' return $CALL;\n'
464 else:
465 template = ' $CALL;\n'
466
467 overload_name = '%s_%s' % (operation.id, version[0])
468 version[0] += 1
469 argument_list = ', '.join(argument_names[:argument_count])
470 call = '_%s(%s)' % (overload_name, argument_list)
471 body.Emit(template, CHECKS=' && '.join(checks), CALL=call)
472
473 dart_declaration = '%s%s _%s(%s)' % (
474 'static ' if operation.is_static else '',
475 self.SecureOutputType(operation.type.id),
476 overload_name, argument_list)
477 cpp_callback_name = self._GenerateNativeBinding(
478 overload_name, (0 if operation.is_static else 1) + argument_count,
479 dart_declaration, 'Callback', False)
480 self._GenerateOperationNativeCallback(operation, operation.arguments[:argu ment_count], cpp_callback_name)
481
482 def GenerateChecksAndCall(operation, argument_count):
483 checks = []
484 for i in range(0, argument_count):
485 argument = operation.arguments[i]
486 argument_name = argument_names[i]
487 type = self._DartType(argument.type.id)
488 if type not in ['dynamic', 'Object']:
489 checks.append('(%s is %s || %s == null)' % (argument_name, type, argum ent_name))
490 checks.extend(['!?%s' % name for name in argument_names[argument_count:]])
491 GenerateCall(operation, argument_count, checks)
492
493 # TODO: Optimize the dispatch to avoid repeated checks.
494 if len(operations) > 1:
495 for operation in operations:
496 for position, argument in enumerate(operation.arguments):
497 if self._IsArgumentOptionalInWebCore(operation, argument):
498 GenerateChecksAndCall(operation, position)
499 GenerateChecksAndCall(operation, len(operation.arguments))
500 body.Emit(' throw "Incorrect number or type of arguments";\n');
501 else:
502 operation = operations[0]
503 argument_count = len(operation.arguments)
504 for position, argument in list(enumerate(operation.arguments))[::-1]:
505 if self._IsArgumentOptionalInWebCore(operation, argument):
506 check = '?%s' % argument_names[position]
507 # argument_count instead of position + 1 is used here to cover one
508 # complicated case with the effectively optional argument in the middl e.
509 # Consider foo(x, [Optional] y, [Optional=DefaultIsNullString] z)
510 # (as of now it's modelled after HTMLMediaElement.webkitAddKey).
511 # y is optional in WebCore, while z is not.
512 # In this case, if y was actually passed, we'd like to emit foo(x, y, z) invocation,
513 # not foo(x, y).
514 GenerateCall(operation, argument_count, [check])
515 argument_count = position
516 GenerateCall(operation, argument_count, [])
517
518 def SecondaryContext(self, interface):
519 pass
520
521 def _GenerateOperationNativeCallback(self, operation, arguments, cpp_callback_ name):
522 webcore_function_name = operation.ext_attrs.get('ImplementedAs', operation.i d)
523 function_expression = self._GenerateWebCoreFunctionExpression(webcore_functi on_name, operation)
524 self._GenerateNativeCallback(
525 cpp_callback_name,
526 not operation.is_static,
527 function_expression,
528 operation,
529 arguments,
530 operation.type.id,
531 operation.raises)
532
533 def _GenerateNativeCallback(self,
534 callback_name,
535 needs_receiver,
536 function_expression,
537 node,
538 arguments,
539 return_type,
540 raises_dom_exception):
541 ext_attrs = node.ext_attrs
542
543 cpp_arguments = []
544 requires_v8_scope = \
545 any((self._TypeInfo(argument.type.id).requires_v8_scope() for argument i n arguments)) or\
546 self._interface.id.startswith('IDB')
547 runtime_check = None
548 raises_exceptions = raises_dom_exception or arguments
549
550 # TODO(antonm): unify with ScriptState below.
551 requires_stack_info = ext_attrs.get('CallWith') == 'ScriptArguments|ScriptSt ate'
552 if requires_stack_info:
553 raises_exceptions = True
554 requires_v8_scope = True
555 cpp_arguments = ['&state', 'scriptArguments.release()']
556 # WebKit uses scriptArguments to reconstruct last argument, so
557 # it's not needed and should be just removed.
558 arguments = arguments[:-1]
559
560 # TODO(antonm): unify with ScriptState below.
561 requires_script_arguments = ext_attrs.get('CallWith') == 'ScriptArguments'
562 if requires_script_arguments:
563 raises_exceptions = True
564 requires_v8_scope = True
565 cpp_arguments = ['scriptArguments.release()']
566 # WebKit uses scriptArguments to reconstruct last argument, so
567 # it's not needed and should be just removed.
568 arguments = arguments[:-1]
569
570 requires_script_execution_context = ext_attrs.get('CallWith') == 'ScriptExec utionContext'
571 if requires_script_execution_context:
572 raises_exceptions = True
573 cpp_arguments = ['context']
574
575 requires_script_state = ext_attrs.get('CallWith') == 'ScriptState'
576 if requires_script_state:
577 raises_exceptions = True
578 cpp_arguments = ['&state']
579
580 requires_dom_window = 'NamedConstructor' in ext_attrs
581 if requires_dom_window:
582 raises_exceptions = True
583 cpp_arguments = ['document']
584
585 if 'ImplementedBy' in ext_attrs:
586 assert needs_receiver
587 self._cpp_impl_includes.add('"%s.h"' % ext_attrs['ImplementedBy'])
588 cpp_arguments.append('receiver')
589
590 if 'Reflect' in ext_attrs:
591 cpp_arguments = [self._GenerateWebCoreReflectionAttributeName(node)]
592
593 v8EnabledPerContext = ext_attrs.get('synthesizedV8EnabledPerContext', ext_at trs.get('V8EnabledPerContext'))
594 v8EnabledAtRuntime = ext_attrs.get('synthesizedV8EnabledAtRuntime', ext_attr s.get('V8EnabledAtRuntime'))
595 assert(not (v8EnabledPerContext and v8EnabledAtRuntime))
596
597 if v8EnabledPerContext:
598 raises_exceptions = True
599 self._cpp_impl_includes.add('"ContextFeatures.h"')
600 self._cpp_impl_includes.add('"DOMWindow.h"')
601 runtime_check = emitter.Format(
602 ' if (!ContextFeatures::$(FEATURE)Enabled(DartUtilities::domWin dowForCurrentIsolate()->document())) {\n'
603 ' exception = Dart_NewStringFromCString("Feature $FEATURE i s not enabled");\n'
604 ' goto fail;\n'
605 ' }',
606 FEATURE=v8EnabledPerContext)
607
608 if v8EnabledAtRuntime:
609 raises_exceptions = True
610 self._cpp_impl_includes.add('"RuntimeEnabledFeatures.h"')
611 runtime_check = emitter.Format(
612 ' if (!RuntimeEnabledFeatures::$(FEATURE)Enabled()) {\n'
613 ' exception = Dart_NewStringFromCString("Feature $FEATURE i s not enabled");\n'
614 ' goto fail;\n'
615 ' }',
616 FEATURE=self._ToWebKitName(v8EnabledAtRuntime))
617
618 body_emitter = self._cpp_definitions_emitter.Emit(
619 '\n'
620 'static void $CALLBACK_NAME(Dart_NativeArguments args)\n'
621 '{\n'
622 ' DartApiScope dartApiScope;\n'
623 '$!BODY'
624 '}\n',
625 CALLBACK_NAME=callback_name)
626
627 if raises_exceptions:
628 body_emitter = body_emitter.Emit(
629 ' Dart_Handle exception = 0;\n'
630 '$!BODY'
631 '\n'
632 'fail:\n'
633 ' Dart_ThrowException(exception);\n'
634 ' ASSERT_NOT_REACHED();\n')
635
636 body_emitter = body_emitter.Emit(
637 ' {\n'
638 '$!BODY'
639 ' return;\n'
640 ' }\n')
641
642 if requires_v8_scope:
643 body_emitter.Emit(
644 ' V8Scope v8scope;\n\n')
645
646 if runtime_check:
647 body_emitter.Emit(
648 '$RUNTIME_CHECK\n',
649 RUNTIME_CHECK=runtime_check)
650
651 if requires_script_execution_context:
652 body_emitter.Emit(
653 ' ScriptExecutionContext* context = DartUtilities::scriptExecut ionContext();\n'
654 ' if (!context) {\n'
655 ' exception = Dart_NewStringFromCString("Failed to retrieve a context");\n'
656 ' goto fail;\n'
657 ' }\n\n')
658
659 if requires_script_state:
660 body_emitter.Emit(
661 ' ScriptState* currentState = ScriptState::current();\n'
662 ' if (!currentState) {\n'
663 ' exception = Dart_NewStringFromCString("Failed to retrieve a script state");\n'
664 ' goto fail;\n'
665 ' }\n'
666 ' ScriptState& state = *currentState;\n\n')
667
668 if requires_dom_window:
669 self._cpp_impl_includes.add('"DOMWindow.h"')
670 body_emitter.Emit(
671 ' DOMWindow* domWindow = DartUtilities::domWindowForCurrentIsol ate();\n'
672 ' if (!domWindow) {\n'
673 ' exception = Dart_NewStringFromCString("Failed to fetch do mWindow");\n'
674 ' goto fail;\n'
675 ' }\n'
676 ' Document* document = domWindow->document();\n')
677
678 if needs_receiver:
679 body_emitter.Emit(
680 ' $WEBCORE_CLASS_NAME* receiver = DartDOMWrapper::receiver< $WE BCORE_CLASS_NAME >(args);\n',
681 WEBCORE_CLASS_NAME=self._interface_type_info.native_type())
682
683 if requires_stack_info:
684 self._cpp_impl_includes.add('"ScriptArguments.h"')
685 body_emitter.Emit(
686 '\n'
687 ' ScriptState* currentState = ScriptState::current();\n'
688 ' if (!currentState) {\n'
689 ' exception = Dart_NewStringFromCString("Failed to retrieve a script state");\n'
690 ' goto fail;\n'
691 ' }\n'
692 ' ScriptState& state = *currentState;\n'
693 '\n'
694 ' Dart_Handle customArgument = Dart_GetNativeArgument(args, $IN DEX);\n'
695 ' RefPtr<ScriptArguments> scriptArguments(DartUtilities::create ScriptArguments(customArgument, exception));\n'
696 ' if (!scriptArguments)\n'
697 ' goto fail;\n'
698 ' RefPtr<ScriptCallStack> scriptCallStack(DartUtilities::create ScriptCallStack());\n'
699 ' if (!scriptCallStack->size())\n'
700 ' return;\n',
701 INDEX=len(arguments) + 1)
702
703 if requires_script_arguments:
704 self._cpp_impl_includes.add('"ScriptArguments.h"')
705 body_emitter.Emit(
706 '\n'
707 ' Dart_Handle customArgument = Dart_GetNativeArgument(args, $IN DEX);\n'
708 ' RefPtr<ScriptArguments> scriptArguments(DartUtilities::create ScriptArguments(customArgument, exception));\n'
709 ' if (!scriptArguments)\n'
710 ' goto fail;\n'
711 ' RefPtr<ScriptCallStack> scriptCallStack(DartUtilities::create ScriptCallStack());\n'
712 ' if (!scriptCallStack->size())\n'
713 ' return;\n',
714 INDEX=len(arguments) + 1)
715
716 # Emit arguments.
717 start_index = 1 if needs_receiver else 0
718 for i, argument in enumerate(arguments):
719 type_info = self._TypeInfo(argument.type.id)
720 argument_expression_template, type, cls, function = \
721 type_info.to_native_info(argument, self._interface.id)
722
723 if ((IsOptional(argument) and not self._IsArgumentOptionalInWebCore(node, argument)) or
724 (argument.ext_attrs.get('Optional') == 'DefaultIsNullString')):
725 function += 'WithNullCheck'
726
727 argument_name = DartDomNameOfAttribute(argument)
728 if type_info.pass_native_by_ref():
729 invocation_template =\
730 ' $TYPE $ARGUMENT_NAME;\n'\
731 ' $CLS::$FUNCTION(Dart_GetNativeArgument(args, $INDEX), $ARGU MENT_NAME, exception);\n'
732 else:
733 invocation_template =\
734 ' $TYPE $ARGUMENT_NAME = $CLS::$FUNCTION(Dart_GetNativeArgume nt(args, $INDEX), exception);\n'
735 body_emitter.Emit(
736 '\n' +
737 invocation_template +
738 ' if (exception)\n'
739 ' goto fail;\n',
740 TYPE=type,
741 ARGUMENT_NAME=argument_name,
742 CLS=cls,
743 FUNCTION=function,
744 INDEX=start_index + i)
745 self._cpp_impl_includes.add('"%s.h"' % cls)
746 cpp_arguments.append(argument_expression_template % argument_name)
747
748 body_emitter.Emit('\n')
749
750 if 'NeedsUserGestureCheck' in ext_attrs:
751 cpp_arguments.append('DartUtilities::processingUserGesture')
752
753 invocation_emitter = body_emitter
754 if raises_dom_exception:
755 cpp_arguments.append('ec')
756 invocation_emitter = body_emitter.Emit(
757 ' ExceptionCode ec = 0;\n'
758 '$!INVOCATION'
759 ' if (UNLIKELY(ec)) {\n'
760 ' exception = DartDOMWrapper::exceptionCodeToDartException(ec );\n'
761 ' goto fail;\n'
762 ' }\n')
763
764 function_call = '%s(%s)' % (function_expression, ', '.join(cpp_arguments))
765 if return_type == 'void':
766 invocation_emitter.Emit(
767 ' $FUNCTION_CALL;\n',
768 FUNCTION_CALL=function_call)
769 else:
770 return_type_info = self._TypeInfo(return_type)
771 self._cpp_impl_includes |= set(return_type_info.conversion_includes())
772
773 # Generate to Dart conversion of C++ value.
774 to_dart_conversion = return_type_info.to_dart_conversion(function_call, se lf._interface.id, ext_attrs)
775 invocation_emitter.Emit(
776 ' Dart_Handle returnValue = $TO_DART_CONVERSION;\n'
777 ' if (returnValue)\n'
778 ' Dart_SetReturnValue(args, returnValue);\n',
779 TO_DART_CONVERSION=to_dart_conversion)
780
781 def _GenerateNativeBinding(self, idl_name, argument_count, dart_declaration,
782 native_suffix, is_custom):
783 annotations = FindCommonAnnotations(self._interface.id, idl_name)
784 if annotations:
785 annotation_str = '\n ' + '\n '.join(annotations)
786 else:
787 annotation_str = ''
788
789 native_binding = '%s_%s_%s' % (self._interface.id, idl_name, native_suffix)
790 self._members_emitter.Emit(
791 '\n'
792 '\n /** @domName $DOMINTERFACE.$DOMNAME */'
793 '$ANNOTATIONS'
794 '\n $DART_DECLARATION native "$NATIVE_BINDING";\n',
795 DOMINTERFACE=self._interface.id,
796 DOMNAME=idl_name,
797 ANNOTATIONS=annotation_str,
798 DART_DECLARATION=dart_declaration,
799 NATIVE_BINDING=native_binding)
800
801 cpp_callback_name = '%s%s' % (idl_name, native_suffix)
802 self._cpp_resolver_emitter.Emit(
803 ' if (argumentCount == $ARGC && name == "$NATIVE_BINDING")\n'
804 ' return Dart$(INTERFACE_NAME)Internal::$CPP_CALLBACK_NAME;\n',
805 ARGC=argument_count,
806 NATIVE_BINDING=native_binding,
807 INTERFACE_NAME=self._interface.id,
808 CPP_CALLBACK_NAME=cpp_callback_name)
809
810 if is_custom:
811 self._cpp_declarations_emitter.Emit(
812 '\n'
813 'void $CPP_CALLBACK_NAME(Dart_NativeArguments);\n',
814 CPP_CALLBACK_NAME=cpp_callback_name)
815
816 return cpp_callback_name
817
818 def _GenerateWebCoreReflectionAttributeName(self, attr):
819 namespace = 'HTMLNames'
820 svg_exceptions = ['class', 'id', 'onabort', 'onclick', 'onerror', 'onload',
821 'onmousedown', 'onmousemove', 'onmouseout', 'onmouseover',
822 'onmouseup', 'onresize', 'onscroll', 'onunload']
823 if self._interface.id.startswith('SVG') and not attr.id in svg_exceptions:
824 namespace = 'SVGNames'
825 self._cpp_impl_includes.add('"%s.h"' % namespace)
826
827 attribute_name = attr.ext_attrs['Reflect'] or attr.id.lower()
828 return 'WebCore::%s::%sAttr' % (namespace, attribute_name)
829
830 def _GenerateWebCoreFunctionExpression(self, function_name, idl_node):
831 if 'ImplementedBy' in idl_node.ext_attrs:
832 return '%s::%s' % (idl_node.ext_attrs['ImplementedBy'], function_name)
833 if idl_node.is_static:
834 return '%s::%s' % (self._interface_type_info.idl_type(), function_name)
835 return '%s%s' % (self._interface_type_info.receiver(), function_name)
836
837 def _IsArgumentOptionalInWebCore(self, operation, argument):
838 if not IsOptional(argument):
839 return False
840 if 'Callback' in argument.ext_attrs:
841 return False
842 if operation.id in ['addEventListener', 'removeEventListener'] and argument. id == 'useCapture':
843 return False
844 # Another option would be to adjust in IDLs, but let's keep it here for now
845 # as it's a single instance.
846 if self._interface.id == 'CSSStyleDeclaration' and operation.id == 'setPrope rty' and argument.id == 'priority':
847 return False
848 if argument.type.id == 'Dictionary':
849 return False
850 return True
851
852 def _GenerateCPPIncludes(self, includes):
853 return ''.join(['#include %s\n' % include for include in sorted(includes)])
854
855 def _ToWebKitName(self, name):
856 name = name[0].lower() + name[1:]
857 name = re.sub(r'^(hTML|uRL|jS|xML|xSLT)', lambda s: s.group(1).lower(),
858 name)
859 return re.sub(r'^(create|exclusive)',
860 lambda s: 'is' + s.group(1).capitalize(),
861 name)
862
863 def _TypeInfo(self, type_name):
864 return self._type_registry.TypeInfo(type_name)
865
866 def _DartType(self, type_name):
867 return self._type_registry.DartType(type_name)
868
869
870 class CPPLibraryEmitter():
871 def __init__(self, emitters, cpp_sources_dir):
872 self._emitters = emitters
873 self._cpp_sources_dir = cpp_sources_dir
874 self._library_headers = {}
875 self._sources_list = []
876
877 def CreateHeaderEmitter(self, interface_name, library_name, is_callback=False) :
878 path = os.path.join(self._cpp_sources_dir, 'Dart%s.h' % interface_name)
879 if not is_callback:
880 if not library_name in self._library_headers:
881 self._library_headers[library_name] = []
882 self._library_headers[library_name].append(path)
883 return self._emitters.FileEmitter(path)
884
885 def CreateSourceEmitter(self, interface_name):
886 path = os.path.join(self._cpp_sources_dir, 'Dart%s.cpp' % interface_name)
887 self._sources_list.append(path)
888 return self._emitters.FileEmitter(path)
889
890 def EmitDerivedSources(self, template, output_dir):
891 partitions = 20 # FIXME: this should be configurable.
892 sources_count = len(self._sources_list)
893 for i in range(0, partitions):
894 file_path = os.path.join(output_dir, 'DartDerivedSources%02i.cpp' % (i + 1 ))
895 includes_emitter = self._emitters.FileEmitter(file_path).Emit(template)
896 for source_file in self._sources_list[i::partitions]:
897 path = os.path.relpath(source_file, output_dir)
898 includes_emitter.Emit('#include "$PATH"\n', PATH=path)
899
900 def EmitResolver(self, template, output_dir):
901 for library_name in self._library_headers.keys():
902 file_path = os.path.join(output_dir, '%s_DartResolver.cpp' % library_name)
903 includes_emitter, body_emitter = self._emitters.FileEmitter(file_path).Emi t(
904 template,
905 LIBRARY_NAME=library_name)
906
907 headers = self._library_headers[library_name]
908 for header_file in headers:
909 path = os.path.relpath(header_file, output_dir)
910 includes_emitter.Emit('#include "$PATH"\n', PATH=path)
911 body_emitter.Emit(
912 ' if (Dart_NativeFunction func = $CLASS_NAME::resolver(name, argu mentCount))\n'
913 ' return func;\n',
914 CLASS_NAME=os.path.splitext(os.path.basename(path))[0])
OLDNEW
« no previous file with comments | « sdk/lib/html/scripts/systemhtml.py ('k') | sdk/lib/html/scripts/templateloader.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698