OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 4 # BSD-style license that can be found in the LICENSE file. |
5 | 5 |
6 """This module provides shared functionality for the system to generate | 6 """This module provides shared functionality for the system to generate |
7 Dart:html APIs from the IDL database.""" | 7 Dart:html APIs from the IDL database.""" |
8 | 8 |
9 import emitter | 9 import emitter |
10 import os | 10 import os |
11 from generator import * | 11 from generator import * |
| 12 from htmldartgenerator import * |
12 | 13 |
13 _js_custom_members = set([ | 14 _js_custom_members = set([ |
14 'AudioBufferSourceNode.start', | 15 'AudioBufferSourceNode.start', |
15 'AudioBufferSourceNode.stop', | 16 'AudioBufferSourceNode.stop', |
16 'AudioContext.createGain', | 17 'AudioContext.createGain', |
17 'AudioContext.createScriptProcessor', | 18 'AudioContext.createScriptProcessor', |
18 'CSSStyleDeclaration.setProperty', | 19 'CSSStyleDeclaration.setProperty', |
19 'Element.insertAdjacentElement', | 20 'Element.insertAdjacentElement', |
20 'Element.insertAdjacentHTML', | 21 'Element.insertAdjacentHTML', |
21 'Element.insertAdjacentText', | 22 'Element.insertAdjacentText', |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 return infos | 182 return infos |
182 | 183 |
183 def EmitHtmlElementFactoryConstructors(emitter, infos, typename, class_name, | 184 def EmitHtmlElementFactoryConstructors(emitter, infos, typename, class_name, |
184 rename_type): | 185 rename_type): |
185 for info in infos: | 186 for info in infos: |
186 constructor_info = info.ConstructorInfo(typename) | 187 constructor_info = info.ConstructorInfo(typename) |
187 | 188 |
188 inits = emitter.Emit( | 189 inits = emitter.Emit( |
189 '\n' | 190 '\n' |
190 ' static $RETURN_TYPE $CONSTRUCTOR($PARAMS) {\n' | 191 ' static $RETURN_TYPE $CONSTRUCTOR($PARAMS) {\n' |
191 ' $CLASS _e = _document.$dom_createElement("$TAG");\n' | 192 ' $CLASS _e = document.$dom_createElement("$TAG");\n' |
192 '$!INITS' | 193 '$!INITS' |
193 ' return _e;\n' | 194 ' return _e;\n' |
194 ' }\n', | 195 ' }\n', |
195 RETURN_TYPE=rename_type(constructor_info.type_name), | 196 RETURN_TYPE=rename_type(constructor_info.type_name), |
196 CONSTRUCTOR=constructor_info.ConstructorFactoryName(rename_type), | 197 CONSTRUCTOR=constructor_info.ConstructorFactoryName(rename_type), |
197 CLASS=class_name, | 198 CLASS=class_name, |
198 TAG=info.tag, | 199 TAG=info.tag, |
199 PARAMS=constructor_info.ParametersDeclaration( | 200 PARAMS=constructor_info.ParametersDeclaration( |
200 rename_type, force_optional=True)) | 201 rename_type, force_optional=True)) |
201 for param in constructor_info.param_infos: | 202 for param in constructor_info.param_infos: |
(...skipping 30 matching lines...) Expand all Loading... |
232 code = self._library_emitter.FileEmitter(self._interface.id) | 233 code = self._library_emitter.FileEmitter(self._interface.id) |
233 code.Emit(self._template_loader.Load('callback.darttemplate')) | 234 code.Emit(self._template_loader.Load('callback.darttemplate')) |
234 code.Emit('typedef void $NAME($PARAMS);\n', | 235 code.Emit('typedef void $NAME($PARAMS);\n', |
235 NAME=self._interface.id, | 236 NAME=self._interface.id, |
236 PARAMS=info.ParametersDeclaration(self._DartType)) | 237 PARAMS=info.ParametersDeclaration(self._DartType)) |
237 self._backend.GenerateCallback(info) | 238 self._backend.GenerateCallback(info) |
238 | 239 |
239 def GenerateInterface(self): | 240 def GenerateInterface(self): |
240 interface_name = self._interface_type_info.interface_name() | 241 interface_name = self._interface_type_info.interface_name() |
241 | 242 |
242 if (self._interface_type_info.has_generated_interface() and | 243 # TODO: this is just tossing the interface, need to skip it completely. |
243 not self._interface_type_info.merged_into()): | 244 interface_emitter = emitter.Emitter() |
244 interface_emitter = self._library_emitter.FileEmitter(interface_name) | |
245 else: | |
246 interface_emitter = emitter.Emitter() | |
247 | 245 |
248 template_file = 'interface_%s.darttemplate' % interface_name | 246 template_file = 'interface_%s.darttemplate' % interface_name |
249 interface_template = (self._template_loader.TryLoad(template_file) or | 247 interface_template = (self._template_loader.TryLoad(template_file) or |
250 self._template_loader.Load('interface.darttemplate')) | 248 self._template_loader.Load('interface.darttemplate')) |
251 | 249 |
252 implements = [] | 250 implements = [] |
253 for parent in self._interface.parents: | 251 for parent in self._interface.parents: |
254 parent_type_info = self._type_registry.TypeInfo(parent.type.id) | 252 parent_type_info = self._type_registry.TypeInfo(parent.type.id) |
255 implements.append(parent_type_info.interface_name()) | 253 implements.append(parent_type_info.interface_name()) |
256 | 254 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
301 if factory_provider: | 299 if factory_provider: |
302 assert factory_provider == info.factory_provider_name | 300 assert factory_provider == info.factory_provider_name |
303 else: | 301 else: |
304 factory_provider = info.factory_provider_name | 302 factory_provider = info.factory_provider_name |
305 | 303 |
306 # TODO(vsm): Add appropriate package / namespace syntax. | 304 # TODO(vsm): Add appropriate package / namespace syntax. |
307 (self._type_comment_emitter, | 305 (self._type_comment_emitter, |
308 self._members_emitter, | 306 self._members_emitter, |
309 self._top_level_emitter) = interface_emitter.Emit( | 307 self._top_level_emitter) = interface_emitter.Emit( |
310 interface_template + '$!TOP_LEVEL', | 308 interface_template + '$!TOP_LEVEL', |
311 ID=interface_name, | 309 ID='_I%s' % interface_name, |
312 EXTENDS=implements_str) | 310 EXTENDS=implements_str) |
313 | 311 |
314 self._type_comment_emitter.Emit("/// @domName $DOMNAME", | |
315 DOMNAME=self._interface.doc_js_name) | |
316 | |
317 implementation_emitter = self._ImplementationEmitter() | 312 implementation_emitter = self._ImplementationEmitter() |
318 | 313 |
319 base_class = self._backend.RootClassName() | 314 base_type_info = None |
320 if self._interface.parents: | 315 if self._interface.parents: |
321 supertype = self._interface.parents[0].type.id | 316 supertype = self._interface.parents[0].type.id |
322 if not IsDartCollectionType(supertype) and not IsPureInterface(supertype): | 317 if not IsDartCollectionType(supertype) and not IsPureInterface(supertype): |
323 type_info = self._type_registry.TypeInfo(supertype) | 318 base_type_info = self._type_registry.TypeInfo(supertype) |
324 if type_info.merged_into() and self._backend.ImplementsMergedMembers(): | 319 if base_type_info.merged_into() \ |
325 type_info = self._type_registry.TypeInfo(type_info.merged_into()) | 320 and self._backend.ImplementsMergedMembers(): |
326 base_class = type_info.implementation_name() | 321 base_type_info = self._type_registry.TypeInfo( |
| 322 base_type_info.merged_into()) |
327 | 323 |
328 implemented_interfaces = [interface_name] +\ | 324 if base_type_info: |
329 self._backend.AdditionalImplementedInterfaces() | 325 base_class = base_type_info.implementation_name() |
| 326 else: |
| 327 base_class = self._backend.RootClassName() |
| 328 |
| 329 implements = self._backend.AdditionalImplementedInterfaces() |
| 330 for parent in self._interface.parents: |
| 331 parent_type_info = self._type_registry.TypeInfo(parent.type.id) |
| 332 if parent_type_info != base_type_info: |
| 333 implements.append(parent_type_info.interface_name()) |
| 334 |
| 335 if interface_name in _secure_base_types: |
| 336 implements.append(_secure_base_types[interface_name]) |
| 337 |
| 338 implements_str = '' |
| 339 if implements: |
| 340 implements_str = ' implements ' + ', '.join(set(implements)) |
| 341 |
330 self._implementation_members_emitter = implementation_emitter.Emit( | 342 self._implementation_members_emitter = implementation_emitter.Emit( |
331 self._backend.ImplementationTemplate(), | 343 self._backend.ImplementationTemplate(), |
332 CLASSNAME=self._interface_type_info.implementation_name(), | 344 CLASSNAME=self._interface_type_info.implementation_name(), |
333 EXTENDS=' extends %s' % base_class if base_class else '', | 345 EXTENDS=' extends %s' % base_class if base_class else '', |
334 IMPLEMENTS=' implements ' + ', '.join(implemented_interfaces), | 346 IMPLEMENTS=implements_str, |
| 347 DOMNAME=self._interface.doc_js_name, |
335 NATIVESPEC=self._backend.NativeSpec()) | 348 NATIVESPEC=self._backend.NativeSpec()) |
336 self._backend.StartInterface(self._implementation_members_emitter) | 349 self._backend.StartInterface(self._implementation_members_emitter) |
337 | 350 |
338 for constructor_info in constructors: | 351 for constructor_info in constructors: |
339 constructor_info.GenerateFactoryInvocation( | 352 constructor_info.GenerateFactoryInvocation( |
340 self._DartType, self._members_emitter, factory_provider) | 353 self._DartType, self._members_emitter, factory_provider) |
341 | 354 |
342 element_type = None | 355 self._backend.AddConstructors(constructors, factory_provider, |
| 356 self._interface_type_info.implementation_name(), |
| 357 base_class) |
| 358 |
| 359 typed_array_type = None |
343 for interface in self._database.Hierarchy(self._interface): | 360 for interface in self._database.Hierarchy(self._interface): |
344 type_info = self._type_registry.TypeInfo(interface.id) | 361 type_info = self._type_registry.TypeInfo(interface.id) |
345 if type_info.is_typed_array(): | 362 if type_info.is_typed_array(): |
346 element_type = type_info.list_item_type() | 363 typed_array_type = type_info.list_item_type() |
347 break | 364 break |
348 if element_type: | 365 if typed_array_type: |
349 self._members_emitter.Emit( | 366 self._members_emitter.Emit( |
350 '\n' | 367 '\n' |
351 ' factory $CTOR(int length) =>\n' | 368 ' factory $CTOR(int length) =>\n' |
352 ' $FACTORY.create$(CTOR)(length);\n' | 369 ' $FACTORY.create$(CTOR)(length);\n' |
353 '\n' | 370 '\n' |
354 ' factory $CTOR.fromList(List<$TYPE> list) =>\n' | 371 ' factory $CTOR.fromList(List<$TYPE> list) =>\n' |
355 ' $FACTORY.create$(CTOR)_fromList(list);\n' | 372 ' $FACTORY.create$(CTOR)_fromList(list);\n' |
356 '\n' | 373 '\n' |
357 ' factory $CTOR.fromBuffer(ArrayBuffer buffer, [int byteOffset, int l
ength]) => \n' | 374 ' factory $CTOR.fromBuffer(ArrayBuffer buffer, [int byteOffset, int l
ength]) => \n' |
358 ' $FACTORY.create$(CTOR)_fromBuffer(buffer, byteOffset, length);\n'
, | 375 ' $FACTORY.create$(CTOR)_fromBuffer(buffer, byteOffset, length);\n'
, |
359 CTOR=self._interface.id, | 376 CTOR=self._interface.id, |
360 TYPE=self._DartType(element_type), | 377 TYPE=self._DartType(typed_array_type), |
361 FACTORY=factory_provider) | 378 FACTORY=factory_provider) |
362 | 379 |
363 events_interface = self._event_generator.ProcessInterface( | 380 events_interface = self._event_generator.ProcessInterface( |
364 self._interface, interface_name, | 381 self._interface, interface_name, |
365 self._backend.CustomJSMembers(), | 382 self._backend.CustomJSMembers(), |
366 interface_emitter, implementation_emitter) | 383 interface_emitter, implementation_emitter) |
367 if events_interface: | 384 if events_interface: |
368 self._EmitEventGetter(events_interface, '_%sImpl' % events_interface) | 385 self._EmitEventGetter(events_interface, events_interface) |
369 | 386 |
370 old_backend = self._backend | 387 old_backend = self._backend |
371 if not self._backend.ImplementsMergedMembers(): | 388 if not self._backend.ImplementsMergedMembers(): |
372 self._backend = HtmlGeneratorDummyBackend() | 389 self._backend = HtmlGeneratorDummyBackend() |
373 merged_interface = self._interface_type_info.merged_interface() | 390 merged_interface = self._interface_type_info.merged_interface() |
374 if merged_interface: | 391 if merged_interface: |
375 self.AddMembers(self._database.GetInterface(merged_interface)) | 392 self.AddMembers(self._database.GetInterface(merged_interface)) |
376 self._backend = old_backend | 393 self._backend = old_backend |
377 | 394 |
378 self.AddMembers(self._interface) | 395 self.AddMembers(self._interface) |
| 396 if merged_interface and not self._backend.ImplementsMergedMembers(): |
| 397 self.AddMembers(self._database.GetInterface(merged_interface), True) |
| 398 |
379 self.AddSecondaryMembers(self._interface) | 399 self.AddSecondaryMembers(self._interface) |
380 self._backend.FinishInterface() | 400 self._backend.FinishInterface() |
381 | 401 |
382 def AddMembers(self, interface): | 402 def AddMembers(self, interface, declare_only=False): |
383 for const in sorted(interface.constants, ConstantOutputOrder): | 403 for const in sorted(interface.constants, ConstantOutputOrder): |
384 self.AddConstant(const) | 404 self.AddConstant(const) |
385 | 405 |
386 for attr in sorted(interface.attributes, ConstantOutputOrder): | 406 for attr in sorted(interface.attributes, ConstantOutputOrder): |
387 if attr.type.id != 'EventListener': | 407 if attr.type.id != 'EventListener': |
388 self.AddAttribute(attr) | 408 self.AddAttribute(attr, False, declare_only) |
389 | 409 |
390 # The implementation should define an indexer if the interface directly | 410 # The implementation should define an indexer if the interface directly |
391 # extends List. | 411 # extends List. |
392 element_type = None | 412 element_type = None |
393 requires_indexer = False | 413 requires_indexer = False |
394 if self._interface_type_info.list_item_type(): | 414 if self._interface_type_info.list_item_type(): |
395 self.AddIndexer(self._interface_type_info.list_item_type()) | 415 self.AddIndexer(self._interface_type_info.list_item_type()) |
396 else: | 416 else: |
397 for parent in self._database.Hierarchy(self._interface): | 417 for parent in self._database.Hierarchy(self._interface): |
398 if parent == self._interface: | 418 if parent == self._interface: |
399 continue | 419 continue |
400 parent_type_info = self._type_registry.TypeInfo(parent.id) | 420 parent_type_info = self._type_registry.TypeInfo(parent.id) |
401 if parent_type_info.list_item_type(): | 421 if parent_type_info.list_item_type(): |
402 self.AmendIndexer(parent_type_info.list_item_type()) | 422 self.AmendIndexer(parent_type_info.list_item_type()) |
403 break | 423 break |
404 | 424 |
405 # Group overloaded operations by id | 425 # Group overloaded operations by id |
406 operationsById = {} | 426 operationsById = {} |
407 for operation in interface.operations: | 427 for operation in interface.operations: |
408 if operation.id not in operationsById: | 428 if operation.id not in operationsById: |
409 operationsById[operation.id] = [] | 429 operationsById[operation.id] = [] |
410 operationsById[operation.id].append(operation) | 430 operationsById[operation.id].append(operation) |
411 | 431 |
412 # Generate operations | 432 # Generate operations |
413 for id in sorted(operationsById.keys()): | 433 for id in sorted(operationsById.keys()): |
414 operations = operationsById[id] | 434 operations = operationsById[id] |
415 info = AnalyzeOperation(interface, operations) | 435 info = AnalyzeOperation(interface, operations) |
416 self.AddOperation(info) | 436 self.AddOperation(info, False, declare_only) |
417 | 437 |
418 def AddSecondaryMembers(self, interface): | 438 def AddSecondaryMembers(self, interface): |
419 # With multiple inheritance, attributes and operations of non-first | 439 # With multiple inheritance, attributes and operations of non-first |
420 # interfaces need to be added. Sometimes the attribute or operation is | 440 # interfaces need to be added. Sometimes the attribute or operation is |
421 # defined in the current interface as well as a parent. In that case we | 441 # defined in the current interface as well as a parent. In that case we |
422 # avoid making a duplicate definition and pray that the signatures match. | 442 # avoid making a duplicate definition and pray that the signatures match. |
423 secondary_parents = self._TransitiveSecondaryParents(interface) | 443 secondary_parents = self._TransitiveSecondaryParents(interface) |
424 for parent_interface in sorted(secondary_parents): | 444 for parent_interface in sorted(secondary_parents): |
425 if isinstance(parent_interface, str): # IsDartCollectionType(parent_inter
face) | 445 if isinstance(parent_interface, str): # IsDartCollectionType(parent_inter
face) |
426 continue | 446 continue |
(...skipping 14 matching lines...) Expand all Loading... |
441 operations = operationsById[id] | 461 operations = operationsById[id] |
442 info = AnalyzeOperation(interface, operations) | 462 info = AnalyzeOperation(interface, operations) |
443 self.AddSecondaryOperation(parent_interface, info) | 463 self.AddSecondaryOperation(parent_interface, info) |
444 | 464 |
445 def AddIndexer(self, element_type): | 465 def AddIndexer(self, element_type): |
446 self._backend.AddIndexer(element_type) | 466 self._backend.AddIndexer(element_type) |
447 | 467 |
448 def AmendIndexer(self, element_type): | 468 def AmendIndexer(self, element_type): |
449 self._backend.AmendIndexer(element_type) | 469 self._backend.AmendIndexer(element_type) |
450 | 470 |
451 def AddAttribute(self, attribute, is_secondary=False): | 471 def AddAttribute(self, attribute, is_secondary=False, declare_only=False): |
452 dom_name = DartDomNameOfAttribute(attribute) | 472 dom_name = DartDomNameOfAttribute(attribute) |
453 html_name = self._renamer.RenameMember( | 473 html_name = self._renamer.RenameMember( |
454 self._interface.id, attribute, dom_name, 'get:') | 474 self._interface.id, attribute, dom_name, 'get:') |
455 if not html_name or self._IsPrivate(html_name): | 475 if not html_name or self._IsPrivate(html_name): |
456 return | 476 return |
457 | 477 |
458 | 478 |
459 html_setter_name = self._renamer.RenameMember( | 479 html_setter_name = self._renamer.RenameMember( |
460 self._interface.id, attribute, dom_name, 'set:') | 480 self._interface.id, attribute, dom_name, 'set:') |
461 read_only = (attribute.is_read_only or 'Replaceable' in attribute.ext_attrs | 481 read_only = (attribute.is_read_only or 'Replaceable' in attribute.ext_attrs |
462 or not html_setter_name) | 482 or not html_setter_name) |
463 | 483 |
464 # We don't yet handle inconsistent renames of the getter and setter yet. | 484 # We don't yet handle inconsistent renames of the getter and setter yet. |
465 assert(not html_setter_name or html_name == html_setter_name) | 485 assert(not html_setter_name or html_name == html_setter_name) |
466 | 486 |
467 if not is_secondary: | 487 if not is_secondary: |
468 self._members_emitter.Emit('\n /** @domName $DOMINTERFACE.$DOMNAME */', | 488 self._members_emitter.Emit('\n /** @domName $DOMINTERFACE.$DOMNAME */', |
469 DOMINTERFACE=attribute.doc_js_interface_name, | 489 DOMINTERFACE=attribute.doc_js_interface_name, |
470 DOMNAME=dom_name) | 490 DOMNAME=dom_name) |
471 if read_only: | 491 if read_only: |
472 template = '\n $TYPE get $NAME;\n' | 492 template = '\n $TYPE get $NAME;\n' |
473 else: | 493 else: |
474 template = '\n $TYPE $NAME;\n' | 494 template = '\n $TYPE $NAME;\n' |
475 | 495 |
476 self._members_emitter.Emit(template, | 496 self._members_emitter.Emit(template, |
477 NAME=html_name, | 497 NAME=html_name, |
478 TYPE=SecureOutputType(self, attribute.type.id)) | 498 TYPE=SecureOutputType(self, attribute.type.id)) |
479 | 499 |
480 self._backend.AddAttribute(attribute, html_name, read_only) | 500 if declare_only: |
| 501 self._backend.DeclareAttribute(attribute, |
| 502 SecureOutputType(self, attribute.type.id), html_name, read_only) |
| 503 else: |
| 504 self._backend.AddAttribute(attribute, html_name, read_only) |
481 | 505 |
482 def AddSecondaryAttribute(self, interface, attribute): | 506 def AddSecondaryAttribute(self, interface, attribute): |
483 self._backend.SecondaryContext(interface) | 507 self._backend.SecondaryContext(interface) |
484 self.AddAttribute(attribute, True) | 508 self.AddAttribute(attribute, True) |
485 | 509 |
486 def AddOperation(self, info, skip_declaration=False): | 510 def AddOperation(self, info, skip_declaration=False, declare_only=False): |
487 """ | 511 """ |
488 Arguments: | 512 Arguments: |
489 operations - contains the overloads, one or more operations with the same | 513 operations - contains the overloads, one or more operations with the same |
490 name. | 514 name. |
491 """ | 515 """ |
492 # FIXME: When we pass in operations[0] below, we're assuming all | 516 # FIXME: When we pass in operations[0] below, we're assuming all |
493 # overloaded operations have the same security attributes. This | 517 # overloaded operations have the same security attributes. This |
494 # is currently true, but we should consider filtering earlier or | 518 # is currently true, but we should consider filtering earlier or |
495 # merging the relevant data into info itself. | 519 # merging the relevant data into info itself. |
496 html_name = self._renamer.RenameMember(self._interface.id, | 520 html_name = self._renamer.RenameMember(self._interface.id, |
(...skipping 17 matching lines...) Expand all Loading... |
514 ' static final $NAME = $IMPL_CLASS_NAME.$NAME;\n', | 538 ' static final $NAME = $IMPL_CLASS_NAME.$NAME;\n', |
515 IMPL_CLASS_NAME=self._interface_type_info.implementation_name(), | 539 IMPL_CLASS_NAME=self._interface_type_info.implementation_name(), |
516 NAME=html_name) | 540 NAME=html_name) |
517 else: | 541 else: |
518 self._members_emitter.Emit( | 542 self._members_emitter.Emit( |
519 '\n' | 543 '\n' |
520 ' $TYPE $NAME($PARAMS);\n', | 544 ' $TYPE $NAME($PARAMS);\n', |
521 TYPE=SecureOutputType(self, info.type_name), | 545 TYPE=SecureOutputType(self, info.type_name), |
522 NAME=html_name, | 546 NAME=html_name, |
523 PARAMS=info.ParametersDeclaration(self._DartType)) | 547 PARAMS=info.ParametersDeclaration(self._DartType)) |
524 self._backend.AddOperation(info, html_name) | 548 if declare_only: |
| 549 self._backend.DeclareOperation(info, |
| 550 SecureOutputType(self, info.type_name), html_name) |
| 551 else: |
| 552 self._backend.AddOperation(info, html_name) |
525 | 553 |
526 def AddSecondaryOperation(self, interface, info): | 554 def AddSecondaryOperation(self, interface, info): |
527 self._backend.SecondaryContext(interface) | 555 self._backend.SecondaryContext(interface) |
528 self.AddOperation(info, True) | 556 self.AddOperation(info) |
529 | 557 |
530 def AddConstant(self, constant): | 558 def AddConstant(self, constant): |
531 type = TypeOrNothing(self._DartType(constant.type.id), constant.type.id) | 559 type = TypeOrNothing(self._DartType(constant.type.id), constant.type.id) |
532 self._members_emitter.Emit('\n static const $TYPE$NAME = $VALUE;\n', | 560 self._members_emitter.Emit('\n static const $TYPE$NAME = $VALUE;\n', |
533 NAME=constant.id, | 561 NAME=constant.id, |
534 TYPE=type, | 562 TYPE=type, |
535 VALUE=constant.value) | 563 VALUE=constant.value) |
536 | 564 |
| 565 self._backend.AddConstant(constant) |
| 566 |
537 def _ImplementationEmitter(self): | 567 def _ImplementationEmitter(self): |
538 if IsPureInterface(self._interface.id): | |
539 return emitter.Emitter() | |
540 basename = self._interface_type_info.implementation_name() | 568 basename = self._interface_type_info.implementation_name() |
541 if (self._interface_type_info.merged_into() and | 569 if (self._interface_type_info.merged_into() and |
542 self._backend.ImplementsMergedMembers()): | 570 self._backend.ImplementsMergedMembers()): |
543 # Merged members are implemented in target interface implementation. | 571 # Merged members are implemented in target interface implementation. |
544 return emitter.Emitter() | 572 return emitter.Emitter() |
545 return self._library_emitter.FileEmitter(basename.lstrip('_')) | 573 return self._library_emitter.FileEmitter(basename) |
546 | 574 |
547 def _EmitEventGetter(self, events_interface, events_class): | 575 def _EmitEventGetter(self, events_interface, events_class): |
548 self._members_emitter.Emit( | 576 self._members_emitter.Emit( |
549 '\n /**' | 577 '\n /**' |
550 '\n * @domName EventTarget.addEventListener, ' | 578 '\n * @domName EventTarget.addEventListener, ' |
551 'EventTarget.removeEventListener, EventTarget.dispatchEvent' | 579 'EventTarget.removeEventListener, EventTarget.dispatchEvent' |
552 '\n */' | 580 '\n */' |
553 '\n $TYPE get on;\n', | 581 '\n $TYPE get on;\n', |
554 TYPE=events_interface) | 582 TYPE=events_interface) |
555 | 583 |
556 self._implementation_members_emitter.Emit( | 584 self._implementation_members_emitter.Emit( |
| 585 '\n /**' |
| 586 '\n * @domName EventTarget.addEventListener, ' |
| 587 'EventTarget.removeEventListener, EventTarget.dispatchEvent' |
| 588 '\n */' |
557 '\n $TYPE get on =>\n new $TYPE(this);\n', | 589 '\n $TYPE get on =>\n new $TYPE(this);\n', |
558 TYPE=events_class) | 590 TYPE=events_class) |
559 | 591 |
560 def _TransitiveSecondaryParents(self, interface): | 592 def _TransitiveSecondaryParents(self, interface): |
561 """Returns a list of all non-primary parents. | 593 """Returns a list of all non-primary parents. |
562 | 594 |
563 The list contains the interface objects for interfaces defined in the | 595 The list contains the interface objects for interfaces defined in the |
564 database, and the name for undefined interfaces. | 596 database, and the name for undefined interfaces. |
565 """ | 597 """ |
566 def walk(parents): | 598 def walk(parents): |
(...skipping 30 matching lines...) Expand all Loading... |
597 class HtmlGeneratorDummyBackend(object): | 629 class HtmlGeneratorDummyBackend(object): |
598 def AddAttribute(self, attribute, html_name, read_only): | 630 def AddAttribute(self, attribute, html_name, read_only): |
599 pass | 631 pass |
600 | 632 |
601 def AddOperation(self, info, html_name): | 633 def AddOperation(self, info, html_name): |
602 pass | 634 pass |
603 | 635 |
604 | 636 |
605 # ------------------------------------------------------------------------------ | 637 # ------------------------------------------------------------------------------ |
606 | 638 |
607 class Dart2JSBackend(object): | 639 class Dart2JSBackend(HtmlDartGenerator): |
608 """Generates a dart2js class for the dart:html library from a DOM IDL | 640 """Generates a dart2js class for the dart:html library from a DOM IDL |
609 interface. | 641 interface. |
610 """ | 642 """ |
611 | 643 |
612 def __init__(self, interface, options): | 644 def __init__(self, interface, options): |
613 self._interface = interface | 645 super(Dart2JSBackend, self).__init__(interface, options) |
| 646 |
614 self._database = options.database | 647 self._database = options.database |
615 self._template_loader = options.templates | 648 self._template_loader = options.templates |
616 self._type_registry = options.type_registry | 649 self._type_registry = options.type_registry |
| 650 self._renamer = options.renamer |
617 self._interface_type_info = self._type_registry.TypeInfo(self._interface.id) | 651 self._interface_type_info = self._type_registry.TypeInfo(self._interface.id) |
618 self._current_secondary_parent = None | 652 self._current_secondary_parent = None |
619 | 653 |
620 def ImplementsMergedMembers(self): | 654 def ImplementsMergedMembers(self): |
621 return True | 655 return True |
622 | 656 |
623 def GenerateCallback(self, info): | 657 def GenerateCallback(self, info): |
624 pass | 658 pass |
625 | 659 |
626 def RootClassName(self): | 660 def RootClassName(self): |
627 return None | 661 return None |
628 | 662 |
629 def AdditionalImplementedInterfaces(self): | 663 def AdditionalImplementedInterfaces(self): |
630 # TODO: Include all implemented interfaces, including other Lists. | 664 implements = super(Dart2JSBackend, self).AdditionalImplementedInterfaces() |
631 implements = [] | |
632 if self._interface_type_info.is_typed_array(): | |
633 element_type = self._interface_type_info.list_item_type() | |
634 implements.append('List<%s>' % self._DartType(element_type)) | |
635 if self._interface_type_info.list_item_type(): | 665 if self._interface_type_info.list_item_type(): |
636 implements.append('JavaScriptIndexingBehavior') | 666 implements.append('JavaScriptIndexingBehavior') |
637 return implements | 667 return implements |
638 | 668 |
639 def NativeSpec(self): | 669 def NativeSpec(self): |
640 native_spec = MakeNativeSpec(self._interface.javascript_binding_name) | 670 native_spec = MakeNativeSpec(self._interface.javascript_binding_name) |
641 return ' native "%s"' % native_spec | 671 return ' native "%s"' % native_spec |
642 | 672 |
643 def ImplementationTemplate(self): | 673 def ImplementationTemplate(self): |
| 674 if IsPureInterface(self._interface.id): |
| 675 return self._template_loader.Load('pure_interface.darttemplate') |
| 676 |
644 template_file = ('impl_%s.darttemplate' % | 677 template_file = ('impl_%s.darttemplate' % |
645 self._interface_type_info.interface_name()) | 678 self._interface_type_info.interface_name()) |
646 return (self._template_loader.TryLoad(template_file) or | 679 return (self._template_loader.TryLoad(template_file) or |
647 self._template_loader.Load('dart2js_impl.darttemplate')) | 680 self._template_loader.Load('dart2js_impl.darttemplate')) |
648 | 681 |
649 def StartInterface(self, emitter): | 682 def StartInterface(self, emitter): |
650 self._members_emitter = emitter | 683 self._members_emitter = emitter |
651 | 684 |
652 def FinishInterface(self): | 685 def FinishInterface(self): |
653 pass | 686 pass |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
726 has_contains = any(op.id == 'contains' for op in self._interface.operation
s) | 759 has_contains = any(op.id == 'contains' for op in self._interface.operation
s) |
727 template = self._template_loader.Load( | 760 template = self._template_loader.Load( |
728 template_file, | 761 template_file, |
729 {'DEFINE_CONTAINS': not has_contains}) | 762 {'DEFINE_CONTAINS': not has_contains}) |
730 self._members_emitter.Emit(template, E=self._DartType(element_type)) | 763 self._members_emitter.Emit(template, E=self._DartType(element_type)) |
731 | 764 |
732 def AddAttribute(self, attribute, html_name, read_only): | 765 def AddAttribute(self, attribute, html_name, read_only): |
733 if self._HasCustomImplementation(attribute.id): | 766 if self._HasCustomImplementation(attribute.id): |
734 return | 767 return |
735 | 768 |
| 769 if IsPureInterface(self._interface.id): |
| 770 self._AddInterfaceAttribute(attribute) |
| 771 return |
| 772 |
736 if attribute.id != html_name: | 773 if attribute.id != html_name: |
737 self._AddAttributeUsingProperties(attribute, html_name, read_only) | 774 self._AddAttributeUsingProperties(attribute, html_name, read_only) |
738 return | 775 return |
739 | 776 |
740 # If the attribute is shadowing, we can't generate a shadowing | 777 # If the attribute is shadowing, we can't generate a shadowing |
741 # field (Issue 1633). | 778 # field (Issue 1633). |
742 # TODO(sra): _FindShadowedAttribute does not take into account the html | 779 # TODO(sra): _FindShadowedAttribute does not take into account the html |
743 # renaming. we should be looking for another attribute that has the same | 780 # renaming. we should be looking for another attribute that has the same |
744 # html_name. Two attributes with the same IDL name might not match if one | 781 # html_name. Two attributes with the same IDL name might not match if one |
745 # is renamed. | 782 # is renamed. |
(...skipping 18 matching lines...) Expand all Loading... |
764 | 801 |
765 # If the type has a conversion we need a getter or setter to contain the | 802 # If the type has a conversion we need a getter or setter to contain the |
766 # conversion code. | 803 # conversion code. |
767 if (self._OutputConversion(attribute.type.id, attribute.id) or | 804 if (self._OutputConversion(attribute.type.id, attribute.id) or |
768 self._InputConversion(attribute.type.id, attribute.id)): | 805 self._InputConversion(attribute.type.id, attribute.id)): |
769 self._AddAttributeUsingProperties(attribute, html_name, read_only) | 806 self._AddAttributeUsingProperties(attribute, html_name, read_only) |
770 return | 807 return |
771 | 808 |
772 output_type = self._NarrowOutputType(attribute.type.id) | 809 output_type = self._NarrowOutputType(attribute.type.id) |
773 input_type = self._NarrowInputType(attribute.type.id) | 810 input_type = self._NarrowInputType(attribute.type.id) |
| 811 self.EmitAttributeDocumentation(attribute) |
774 if not read_only: | 812 if not read_only: |
775 self._members_emitter.Emit( | 813 self._members_emitter.Emit( |
776 '\n $TYPE $NAME;' | 814 '\n $TYPE $NAME;' |
777 '\n', | 815 '\n', |
778 NAME=DartDomNameOfAttribute(attribute), | 816 NAME=DartDomNameOfAttribute(attribute), |
779 TYPE=output_type) | 817 TYPE=output_type) |
780 else: | 818 else: |
781 self._members_emitter.Emit( | 819 self._members_emitter.Emit( |
782 '\n final $TYPE $NAME;' | 820 '\n final $TYPE $NAME;' |
783 '\n', | 821 '\n', |
784 NAME=DartDomNameOfAttribute(attribute), | 822 NAME=DartDomNameOfAttribute(attribute), |
785 TYPE=output_type) | 823 TYPE=output_type) |
786 | 824 |
787 def _AddAttributeUsingProperties(self, attribute, html_name, read_only): | 825 def _AddAttributeUsingProperties(self, attribute, html_name, read_only): |
788 self._AddRenamingGetter(attribute, html_name) | 826 self._AddRenamingGetter(attribute, html_name) |
789 if not read_only: | 827 if not read_only: |
790 self._AddRenamingSetter(attribute, html_name) | 828 self._AddRenamingSetter(attribute, html_name) |
791 | 829 |
| 830 def _AddInterfaceAttribute(self, attribute): |
| 831 self._members_emitter.Emit( |
| 832 '\n $TYPE $NAME;' |
| 833 '\n', |
| 834 NAME=DartDomNameOfAttribute(attribute), |
| 835 TYPE=self._NarrowOutputType(attribute.type.id)) |
| 836 |
792 def _AddRenamingGetter(self, attr, html_name): | 837 def _AddRenamingGetter(self, attr, html_name): |
| 838 self.EmitAttributeDocumentation(attr) |
| 839 |
793 conversion = self._OutputConversion(attr.type.id, attr.id) | 840 conversion = self._OutputConversion(attr.type.id, attr.id) |
794 if conversion: | 841 if conversion: |
795 return self._AddConvertingGetter(attr, html_name, conversion) | 842 return self._AddConvertingGetter(attr, html_name, conversion) |
796 return_type = self._NarrowOutputType(attr.type.id) | 843 return_type = self._NarrowOutputType(attr.type.id) |
797 self._members_emitter.Emit( | 844 self._members_emitter.Emit( |
798 # TODO(sra): Use metadata to provide native name. | 845 # TODO(sra): Use metadata to provide native name. |
799 '\n $TYPE get $HTML_NAME => JS("$TYPE", "#.$NAME", this);' | 846 '\n $TYPE get $HTML_NAME => JS("$TYPE", "#.$NAME", this);' |
800 '\n', | 847 '\n', |
801 HTML_NAME=html_name, | 848 HTML_NAME=html_name, |
802 NAME=attr.id, | 849 NAME=attr.id, |
803 TYPE=return_type) | 850 TYPE=return_type) |
804 | 851 |
805 def _AddRenamingSetter(self, attr, html_name): | 852 def _AddRenamingSetter(self, attr, html_name): |
| 853 self.EmitAttributeDocumentation(attr) |
| 854 |
806 conversion = self._InputConversion(attr.type.id, attr.id) | 855 conversion = self._InputConversion(attr.type.id, attr.id) |
807 if conversion: | 856 if conversion: |
808 return self._AddConvertingSetter(attr, html_name, conversion) | 857 return self._AddConvertingSetter(attr, html_name, conversion) |
809 self._members_emitter.Emit( | 858 self._members_emitter.Emit( |
810 # TODO(sra): Use metadata to provide native name. | 859 # TODO(sra): Use metadata to provide native name. |
811 '\n void set $HTML_NAME($TYPE value) {' | 860 '\n void set $HTML_NAME($TYPE value) {' |
812 '\n JS("void", "#.$NAME = #", this, value);' | 861 '\n JS("void", "#.$NAME = #", this, value);' |
813 '\n }' | 862 '\n }' |
814 '\n', | 863 '\n', |
815 HTML_NAME=html_name, | 864 HTML_NAME=html_name, |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
849 pass | 898 pass |
850 | 899 |
851 def AddOperation(self, info, html_name): | 900 def AddOperation(self, info, html_name): |
852 """ | 901 """ |
853 Arguments: | 902 Arguments: |
854 info: An OperationInfo object. | 903 info: An OperationInfo object. |
855 """ | 904 """ |
856 if self._HasCustomImplementation(info.name): | 905 if self._HasCustomImplementation(info.name): |
857 return | 906 return |
858 | 907 |
859 # Any conversions needed? | 908 self.EmitOperationDocumentation(info) |
860 if any(self._OperationRequiresConversions(op) for op in info.overloads): | 909 |
| 910 if IsPureInterface(self._interface.id): |
| 911 self._AddInterfaceOperation(info, html_name) |
| 912 elif any(self._OperationRequiresConversions(op) for op in info.overloads): |
| 913 # Any conversions needed? |
861 self._AddOperationWithConversions(info, html_name) | 914 self._AddOperationWithConversions(info, html_name) |
862 else: | 915 else: |
863 self._AddDirectNativeOperation(info, html_name) | 916 self._AddDirectNativeOperation(info, html_name) |
864 | 917 |
865 def _AddDirectNativeOperation(self, info, html_name): | 918 def _AddDirectNativeOperation(self, info, html_name): |
866 # Do we need a native body? | 919 # Do we need a native body? |
867 if html_name != info.declared_name: | 920 if html_name != info.declared_name: |
868 return_type = self._NarrowOutputType(info.type_name) | 921 return_type = self._NarrowOutputType(info.type_name) |
869 | 922 |
870 operation_emitter = self._members_emitter.Emit('$!SCOPE', | 923 operation_emitter = self._members_emitter.Emit('$!SCOPE', |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1019 else: | 1072 else: |
1020 operation = operations[0] | 1073 operation = operations[0] |
1021 argument_count = len(operation.arguments) | 1074 argument_count = len(operation.arguments) |
1022 for position, argument in list(enumerate(operation.arguments))[::-1]: | 1075 for position, argument in list(enumerate(operation.arguments))[::-1]: |
1023 if self._IsOptional(operation, argument): | 1076 if self._IsOptional(operation, argument): |
1024 check = '?%s' % parameter_names[position] | 1077 check = '?%s' % parameter_names[position] |
1025 GenerateCall(operation, position + 1, [check]) | 1078 GenerateCall(operation, position + 1, [check]) |
1026 argument_count = position | 1079 argument_count = position |
1027 GenerateCall(operation, argument_count, []) | 1080 GenerateCall(operation, argument_count, []) |
1028 | 1081 |
| 1082 def _AddInterfaceOperation(self, info, html_name): |
| 1083 self._members_emitter.Emit( |
| 1084 '\n' |
| 1085 ' $TYPE $NAME($PARAMS);\n', |
| 1086 TYPE=self._NarrowOutputType(info.type_name), |
| 1087 NAME=info.name, |
| 1088 PARAMS=info.ParametersDeclaration(self._NarrowInputType)) |
| 1089 |
| 1090 def AddConstant(self, constant): |
| 1091 type = TypeOrNothing(self._DartType(constant.type.id), constant.type.id) |
| 1092 self._members_emitter.Emit('\n static const $TYPE$NAME = $VALUE;\n', |
| 1093 NAME=constant.id, |
| 1094 TYPE=type, |
| 1095 VALUE=constant.value) |
1029 | 1096 |
1030 def _IsOptional(self, operation, argument): | 1097 def _IsOptional(self, operation, argument): |
1031 return IsOptional(argument) | 1098 return IsOptional(argument) |
1032 | 1099 |
1033 | 1100 |
1034 def _OperationRequiresConversions(self, operation): | 1101 def _OperationRequiresConversions(self, operation): |
1035 return (self._OperationRequiresOutputConversion(operation) or | 1102 return (self._OperationRequiresOutputConversion(operation) or |
1036 self._OperationRequiresInputConversions(operation)) | 1103 self._OperationRequiresInputConversions(operation)) |
1037 | 1104 |
1038 def _OperationRequiresOutputConversion(self, operation): | 1105 def _OperationRequiresOutputConversion(self, operation): |
(...skipping 17 matching lines...) Expand all Loading... |
1056 def CustomJSMembers(self): | 1123 def CustomJSMembers(self): |
1057 return _js_custom_members | 1124 return _js_custom_members |
1058 | 1125 |
1059 def _NarrowToImplementationType(self, type_name): | 1126 def _NarrowToImplementationType(self, type_name): |
1060 return self._type_registry.TypeInfo(type_name).narrow_dart_type() | 1127 return self._type_registry.TypeInfo(type_name).narrow_dart_type() |
1061 | 1128 |
1062 def _NarrowInputType(self, type_name): | 1129 def _NarrowInputType(self, type_name): |
1063 return self._NarrowToImplementationType(type_name) | 1130 return self._NarrowToImplementationType(type_name) |
1064 | 1131 |
1065 def _NarrowOutputType(self, type_name): | 1132 def _NarrowOutputType(self, type_name): |
1066 secure_name = SecureOutputType(self, type_name, True) | 1133 return SecureOutputType(self, type_name) |
1067 return self._NarrowToImplementationType(secure_name) | |
1068 | 1134 |
1069 def _FindShadowedAttribute(self, attr): | 1135 def _FindShadowedAttribute(self, attr): |
1070 """Returns (attribute, superinterface) or (None, None).""" | 1136 """Returns (attribute, superinterface) or (None, None).""" |
1071 def FindInParent(interface): | 1137 def FindInParent(interface): |
1072 """Returns matching attribute in parent, or None.""" | 1138 """Returns matching attribute in parent, or None.""" |
1073 if interface.parents: | 1139 if interface.parents: |
1074 parent = interface.parents[0] | 1140 parent = interface.parents[0] |
1075 if IsDartCollectionType(parent.type.id): | 1141 if IsDartCollectionType(parent.type.id): |
1076 return (None, None) | 1142 return (None, None) |
1077 if IsPureInterface(parent.type.id): | 1143 if IsPureInterface(parent.type.id): |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1130 | 1196 |
1131 library_emitter = self._multiemitter.FileEmitter(library_file_path) | 1197 library_emitter = self._multiemitter.FileEmitter(library_file_path) |
1132 library_file_dir = os.path.dirname(library_file_path) | 1198 library_file_dir = os.path.dirname(library_file_path) |
1133 auxiliary_dir = os.path.relpath(auxiliary_dir, library_file_dir) | 1199 auxiliary_dir = os.path.relpath(auxiliary_dir, library_file_dir) |
1134 imports_emitter = library_emitter.Emit( | 1200 imports_emitter = library_emitter.Emit( |
1135 self._template, AUXILIARY_DIR=massage_path(auxiliary_dir)) | 1201 self._template, AUXILIARY_DIR=massage_path(auxiliary_dir)) |
1136 for path in sorted(self._path_to_emitter.keys()): | 1202 for path in sorted(self._path_to_emitter.keys()): |
1137 relpath = os.path.relpath(path, library_file_dir) | 1203 relpath = os.path.relpath(path, library_file_dir) |
1138 imports_emitter.Emit( | 1204 imports_emitter.Emit( |
1139 "part '$PATH';\n", PATH=massage_path(relpath)) | 1205 "part '$PATH';\n", PATH=massage_path(relpath)) |
OLD | NEW |