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 from systemfrog import * | 9 from systemfrog import * |
10 from systeminterface import * | 10 from systeminterface import * |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
105 } | 105 } |
106 # Members and classes from the dom that should be removed completelly from | 106 # Members and classes from the dom that should be removed completelly from |
107 # dart:html. These could be expressed in the IDL instead but expressing this | 107 # dart:html. These could be expressed in the IDL instead but expressing this |
108 # as a simple table instead is more concise. | 108 # as a simple table instead is more concise. |
109 # Syntax is: ClassName.(get\.|set\.)?MemberName | 109 # Syntax is: ClassName.(get\.|set\.)?MemberName |
110 # Using get: and set: is optional and should only be used when a getter needs | 110 # Using get: and set: is optional and should only be used when a getter needs |
111 # to be suppressed but not the setter, etc. | 111 # to be suppressed but not the setter, etc. |
112 # TODO(jacobr): cleanup and augment this list. | 112 # TODO(jacobr): cleanup and augment this list. |
113 _html_library_remove = set([ | 113 _html_library_remove = set([ |
114 'Window.get:document', # Removed as we have a custom implementation. | 114 'Window.get:document', # Removed as we have a custom implementation. |
115 'Window.get:window', | |
115 'NodeList.item', | 116 'NodeList.item', |
116 "Attr.*", | 117 "Attr.*", |
117 # "BarProp.*", | 118 # "BarProp.*", |
118 # "BarInfo.*", | 119 # "BarInfo.*", |
119 # "Blob.webkitSlice", | 120 # "Blob.webkitSlice", |
120 # "CDATASection.*", | 121 # "CDATASection.*", |
121 # "Comment.*", | 122 # "Comment.*", |
122 # "DOMImplementation.*", | 123 # "DOMImplementation.*", |
123 "Document.get:forms", | 124 "Document.get:forms", |
124 # "Document.get:selectedStylesheetSet", | 125 # "Document.get:selectedStylesheetSet", |
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
429 'write': 'write', | 430 'write': 'write', |
430 'writeend': 'writeEnd', | 431 'writeend': 'writeEnd', |
431 'writestart': 'writeStart' | 432 'writestart': 'writeStart' |
432 } | 433 } |
433 | 434 |
434 # These classes require an explicit declaration for the "on" method even though | 435 # These classes require an explicit declaration for the "on" method even though |
435 # they don't declare any unique events, because the concrete class hierarchy | 436 # they don't declare any unique events, because the concrete class hierarchy |
436 # doesn't match the interface hierarchy. | 437 # doesn't match the interface hierarchy. |
437 _html_explicit_event_classes = set(['DocumentFragment']) | 438 _html_explicit_event_classes = set(['DocumentFragment']) |
438 | 439 |
440 # These types are accessible from different frames. We provide a | |
441 # wrapper to restrict cross-frame access. Ideally, we capture this | |
442 # via the IDL CheckSecurity attribute. Currently, it is sometimes | |
443 # only defined under #define V8_BINDING. | |
sra1
2012/05/10 00:12:06
What are the tuple elements?
| |
444 _cross_frame_wrapped_types = { | |
445 'Window': ('get:window', 'window'), | |
446 'Location': ('Window.get:location', 'window.location'), | |
447 'History': ('Window.get:history', 'window.history'), | |
448 } | |
449 | |
450 _wrapped_types = _cross_frame_wrapped_types.keys() | |
sra1
2012/05/10 00:12:06
Comment that this list may be extended to non-cros
| |
451 | |
452 def _WrapAndReturnObject(container_interface, return_interface, expr, getter): | |
sra1
2012/05/10 00:12:06
Just make this wrap the expression.
_WrapIfCrossFr
| |
453 if return_interface in _cross_frame_wrapped_types.keys(): | |
sra1
2012/05/10 00:12:06
You can use 'in' on dictionaries directly.
| |
454 full_name = container_interface + '.get:' + getter | |
455 if _cross_frame_wrapped_types[return_interface][0] == full_name: | |
456 return 'return %s' % expr | |
457 return 'return _%sCrossFrameImpl._createSafe(%s)' % (return_interface, expr) | |
458 return 'return %s' % expr | |
459 | |
439 def _OnAttributeToEventName(on_method): | 460 def _OnAttributeToEventName(on_method): |
440 event_name = on_method.id[2:] | 461 event_name = on_method.id[2:] |
441 if event_name in _on_attribute_to_event_name_mapping: | 462 if event_name in _on_attribute_to_event_name_mapping: |
442 return _on_attribute_to_event_name_mapping[event_name] | 463 return _on_attribute_to_event_name_mapping[event_name] |
443 else: | 464 else: |
444 return event_name | 465 return event_name |
445 | 466 |
446 def _DomToHtmlEvents(interface_id, events): | 467 def _DomToHtmlEvents(interface_id, events): |
447 event_names = set(map(_OnAttributeToEventName, events)) | 468 event_names = set(map(_OnAttributeToEventName, events)) |
448 if interface_id in _html_manual_events: | 469 if interface_id in _html_manual_events: |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
614 def GenerateLibraries(self, lib_dir): | 635 def GenerateLibraries(self, lib_dir): |
615 pass | 636 pass |
616 | 637 |
617 | 638 |
618 def _FilePathForDartInterface(self, interface_name): | 639 def _FilePathForDartInterface(self, interface_name): |
619 """Returns the file path of the Dart interface definition.""" | 640 """Returns the file path of the Dart interface definition.""" |
620 # TODO(jmesserly): is this the right path | 641 # TODO(jmesserly): is this the right path |
621 return os.path.join(self._output_dir, 'html', 'interface', | 642 return os.path.join(self._output_dir, 'html', 'interface', |
622 '%s.dart' % interface_name) | 643 '%s.dart' % interface_name) |
623 | 644 |
645 class HtmlCrossFrameSystem(HtmlSystem): | |
sra1
2012/05/10 00:12:06
I have been ordering them: System1 InterfaceGener
| |
646 | |
647 def __init__(self, templates, database, emitters, output_dir, generator): | |
648 super(HtmlCrossFrameSystem, self).__init__( | |
649 templates, database, emitters, output_dir, generator) | |
650 self._dart_cross_frame_file_paths = [] | |
651 | |
652 def InterfaceGenerator(self, | |
653 interface, | |
654 common_prefix, | |
655 super_interface_name, | |
656 source_filter): | |
657 """.""" | |
658 if interface.id not in _cross_frame_wrapped_types.keys(): | |
659 return None | |
660 template_file = 'crossframe_%s.darttemplate' % interface.id | |
661 template = self._templates.TryLoad(template_file) | |
662 if not template: | |
663 template = self._templates.Load('crossframe_impl.darttemplate') | |
664 | |
665 dart_code = self._ImplFileEmitter(interface.id) | |
666 return HtmlCrossFrameGenerator(self, interface, template, | |
667 super_interface_name, dart_code, | |
668 self._shared) | |
669 | |
670 def GenerateLibraries(self, lib_dir): | |
671 pass | |
672 | |
673 def Finish(self): | |
674 pass | |
675 | |
676 def ProcessCallback(self, interface, info): | |
677 pass | |
678 | |
679 def _ImplFileEmitter(self, name): | |
680 """Returns the file emitter of the Frog implementation file.""" | |
681 # TODO(jmesserly): is this the right path | |
682 path = os.path.join(self._output_dir, 'html', 'crossframe', | |
683 '%sCrossFrame.dart' % name) | |
684 self._dart_cross_frame_file_paths.append(path) | |
685 return self._emitters.FileEmitter(path) | |
686 | |
624 # ------------------------------------------------------------------------------ | 687 # ------------------------------------------------------------------------------ |
625 | 688 |
626 # TODO(jmesserly): inheritance is probably not the right way to factor this long | 689 # TODO(jmesserly): inheritance is probably not the right way to factor this long |
627 # term, but it makes merging better for now. | 690 # term, but it makes merging better for now. |
628 class HtmlDartInterfaceGenerator(DartInterfaceGenerator): | 691 class HtmlDartInterfaceGenerator(DartInterfaceGenerator): |
629 """Generates Dart Interface definition for one DOM IDL interface.""" | 692 """Generates Dart Interface definition for one DOM IDL interface.""" |
630 | 693 |
631 def __init__(self, interface, emitter, template, | 694 def __init__(self, interface, emitter, template, |
632 common_prefix, super_interface, source_filter, system, shared): | 695 common_prefix, super_interface, source_filter, system, shared): |
633 super(HtmlDartInterfaceGenerator, self).__init__(interface, | 696 super(HtmlDartInterfaceGenerator, self).__init__(interface, |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
706 | 769 |
707 emit_events, events = self._shared.GetEventAttributes(self._interface) | 770 emit_events, events = self._shared.GetEventAttributes(self._interface) |
708 if not emit_events: | 771 if not emit_events: |
709 return | 772 return |
710 elif events: | 773 elif events: |
711 self.AddEventAttributes(events) | 774 self.AddEventAttributes(events) |
712 else: | 775 else: |
713 self._EmitEventGetter(self._shared.GetParentEventsClass(self._interface)) | 776 self._EmitEventGetter(self._shared.GetParentEventsClass(self._interface)) |
714 | 777 |
715 def AddAttribute(self, getter, setter): | 778 def AddAttribute(self, getter, setter): |
779 if 'CheckSecurityForNode' in (getter or setter).ext_attrs: | |
sra1
2012/05/10 00:12:06
Comment on why.
| |
780 return | |
781 | |
716 dom_name = DartDomNameOfAttribute(getter) | 782 dom_name = DartDomNameOfAttribute(getter) |
717 html_getter_name = self._shared.RenameInHtmlLibrary( | 783 html_getter_name = self._shared.RenameInHtmlLibrary( |
718 self._interface, dom_name, 'get:') | 784 self._interface, dom_name, 'get:') |
719 html_setter_name = self._shared.RenameInHtmlLibrary( | 785 html_setter_name = self._shared.RenameInHtmlLibrary( |
720 self._interface, dom_name, 'set:') | 786 self._interface, dom_name, 'set:') |
721 | 787 |
722 if not html_getter_name or self._shared.IsPrivate(html_getter_name): | 788 if not html_getter_name or self._shared.IsPrivate(html_getter_name): |
723 getter = None | 789 getter = None |
724 if not html_setter_name or self._shared.IsPrivate(html_setter_name): | 790 if not html_setter_name or self._shared.IsPrivate(html_setter_name): |
725 setter = None | 791 setter = None |
(...skipping 29 matching lines...) Expand all Loading... | |
755 """ | 821 """ |
756 html_name = self._shared.RenameInHtmlLibrary( | 822 html_name = self._shared.RenameInHtmlLibrary( |
757 self._interface, info.name) | 823 self._interface, info.name) |
758 if html_name and not self._shared.IsPrivate(html_name): | 824 if html_name and not self._shared.IsPrivate(html_name): |
759 self._members_emitter.Emit('\n /** @domName $DOMINTERFACE.$DOMNAME */', | 825 self._members_emitter.Emit('\n /** @domName $DOMINTERFACE.$DOMNAME */', |
760 DOMINTERFACE=info.overloads[0].doc_js_interface_name, | 826 DOMINTERFACE=info.overloads[0].doc_js_interface_name, |
761 DOMNAME=info.name) | 827 DOMNAME=info.name) |
762 | 828 |
763 self._members_emitter.Emit('\n' | 829 self._members_emitter.Emit('\n' |
764 ' $TYPE $NAME($PARAMS);\n', | 830 ' $TYPE $NAME($PARAMS);\n', |
765 TYPE=info.type_name, | 831 TYPE=info.type_name, |
766 NAME=html_name, | 832 NAME=html_name, |
767 PARAMS=info.ParametersInterfaceDeclaration()) | 833 PARAMS=info.ParametersInterfaceDeclaration()) |
768 | 834 |
769 def FinishInterface(self): | 835 def FinishInterface(self): |
770 pass | 836 pass |
771 | 837 |
772 def AddConstant(self, constant): | 838 def AddConstant(self, constant): |
773 self._EmitConstant(self._members_emitter, constant) | 839 self._EmitConstant(self._members_emitter, constant) |
774 | 840 |
775 def AddEventAttributes(self, event_attrs): | 841 def AddEventAttributes(self, event_attrs): |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
898 # interface Y extends X, List<T> ... | 964 # interface Y extends X, List<T> ... |
899 # | 965 # |
900 # In the non-root case we have to choose between: | 966 # In the non-root case we have to choose between: |
901 # | 967 # |
902 # class YImpl extends XImpl { add List<T> methods; } | 968 # class YImpl extends XImpl { add List<T> methods; } |
903 # | 969 # |
904 # and | 970 # and |
905 # | 971 # |
906 # class YImpl extends ListBase<T> { copies of transitive XImpl methods; } | 972 # class YImpl extends ListBase<T> { copies of transitive XImpl methods; } |
907 # | 973 # |
974 | |
975 # TODO(vsm): Wrap return value if necessary. | |
908 self._members_emitter.Emit( | 976 self._members_emitter.Emit( |
909 '\n' | 977 '\n' |
910 ' $TYPE operator[](int index) native "return this[index];";\n', | 978 ' $TYPE operator[](int index) native "return this[index];";\n', |
911 TYPE=self._NarrowOutputType(element_type)) | 979 TYPE=self._NarrowOutputType(element_type)) |
912 | 980 |
913 if 'CustomIndexedSetter' in self._interface.ext_attrs: | 981 if 'CustomIndexedSetter' in self._interface.ext_attrs: |
914 self._members_emitter.Emit( | 982 self._members_emitter.Emit( |
915 '\n' | 983 '\n' |
916 ' void operator[]=(int index, $TYPE value) native "this[index] = valu e";\n', | 984 ' void operator[]=(int index, $TYPE value) native "this[index] = valu e";\n', |
917 TYPE=self._NarrowInputType(element_type)) | 985 TYPE=self._NarrowInputType(element_type)) |
(...skipping 10 matching lines...) Expand all Loading... | |
928 TYPE=self._NarrowInputType(element_type)) | 996 TYPE=self._NarrowInputType(element_type)) |
929 | 997 |
930 # TODO(sra): Use separate mixins for mutable implementations of List<T>. | 998 # TODO(sra): Use separate mixins for mutable implementations of List<T>. |
931 # TODO(sra): Use separate mixins for typed array implementations of List<T>. | 999 # TODO(sra): Use separate mixins for typed array implementations of List<T>. |
932 if self._interface.id != 'NodeList': | 1000 if self._interface.id != 'NodeList': |
933 template_file = 'immutable_list_mixin.darttemplate' | 1001 template_file = 'immutable_list_mixin.darttemplate' |
934 template = self._system._templates.Load(template_file) | 1002 template = self._system._templates.Load(template_file) |
935 self._members_emitter.Emit(template, E=DartType(element_type)) | 1003 self._members_emitter.Emit(template, E=DartType(element_type)) |
936 | 1004 |
937 def AddAttribute(self, getter, setter): | 1005 def AddAttribute(self, getter, setter): |
938 | 1006 if 'CheckSecurityForNode' in (getter or setter).ext_attrs: |
1007 return | |
939 html_getter_name = self._shared.RenameInHtmlLibrary( | 1008 html_getter_name = self._shared.RenameInHtmlLibrary( |
940 self._interface, DartDomNameOfAttribute(getter), 'get:', | 1009 self._interface, DartDomNameOfAttribute(getter), 'get:', |
941 implementation_class=True) | 1010 implementation_class=True) |
942 html_setter_name = self._shared.RenameInHtmlLibrary( | 1011 html_setter_name = self._shared.RenameInHtmlLibrary( |
943 self._interface, DartDomNameOfAttribute(getter), 'set:', | 1012 self._interface, DartDomNameOfAttribute(getter), 'set:', |
944 implementation_class=True) | 1013 implementation_class=True) |
945 | 1014 |
946 if not html_getter_name: | 1015 if not html_getter_name: |
947 getter = None | 1016 getter = None |
948 if not html_setter_name: | 1017 if not html_setter_name: |
949 setter = None | 1018 setter = None |
950 | 1019 |
951 if not getter and not setter: | 1020 if not getter and not setter: |
952 return | 1021 return |
953 | 1022 |
954 if ((getter and html_getter_name != getter.id) or | 1023 if ((getter and html_getter_name != getter.id) or |
955 (setter and html_setter_name != setter.id)): | 1024 (setter and html_setter_name != setter.id)): |
956 if getter: | 1025 if getter: |
957 self._AddRenamingGetter(getter, html_getter_name) | 1026 self._AddRenamingGetter(getter, html_getter_name) |
958 if setter: | 1027 if setter: |
959 self._AddRenamingSetter(setter, html_setter_name) | 1028 self._AddRenamingSetter(setter, html_setter_name) |
960 return | 1029 return |
961 | 1030 |
962 # If the (getter, setter) pair is shadowing, we can't generate a shadowing | 1031 # If the (getter, setter) pair is shadowing, we can't generate a shadowing |
963 # field (Issue 1633). | 1032 # field (Issue 1633). |
1033 | |
964 (super_getter, super_getter_interface) = self._FindShadowedAttribute(getter) | 1034 (super_getter, super_getter_interface) = self._FindShadowedAttribute(getter) |
965 (super_setter, super_setter_interface) = self._FindShadowedAttribute(setter) | 1035 (super_setter, super_setter_interface) = self._FindShadowedAttribute(setter) |
966 if super_getter or super_setter: | 1036 if super_getter or super_setter: |
967 if getter and not setter and super_getter and not super_setter: | 1037 if getter and not setter and super_getter and not super_setter: |
968 if DartType(getter.type.id) == DartType(super_getter.type.id): | 1038 if DartType(getter.type.id) == DartType(super_getter.type.id): |
969 # Compatible getter, use the superclass property. This works because | 1039 # Compatible getter, use the superclass property. This works because |
970 # JavaScript will do its own dynamic dispatch. | 1040 # JavaScript will do its own dynamic dispatch. |
971 output_type = getter and self._NarrowOutputType(getter.type.id) | 1041 output_type = getter and self._NarrowOutputType(getter.type.id) |
972 self._members_emitter.Emit( | 1042 self._members_emitter.Emit( |
973 '\n' | 1043 '\n' |
974 ' // Use implementation from $SUPER.\n' | 1044 ' // Use implementation from $SUPER.\n' |
975 ' // final $TYPE $NAME;\n', | 1045 ' // final $TYPE $NAME;\n', |
976 SUPER=super_getter_interface.id, | 1046 SUPER=super_getter_interface.id, |
977 NAME=DartDomNameOfAttribute(getter), | 1047 NAME=DartDomNameOfAttribute(getter), |
978 TYPE=output_type) | 1048 TYPE=output_type) |
979 return | 1049 return |
980 | 1050 |
981 self._members_emitter.Emit('\n // Shadowing definition.') | 1051 self._members_emitter.Emit('\n // Shadowing definition.') |
982 self._AddAttributeUsingProperties(getter, setter) | 1052 self._AddAttributeUsingProperties(getter, setter) |
983 return | 1053 return |
984 | 1054 |
985 output_type = getter and self._NarrowOutputType(getter.type.id) | 1055 # If the return type is wrapped, we cannot just map to a field. |
986 input_type = setter and self._NarrowInputType(setter.type.id) | 1056 if not getter or getter.type.id not in _wrapped_types: |
987 if getter and setter and input_type == output_type: | 1057 output_type = getter and self._NarrowOutputType(getter.type.id) |
988 self._members_emitter.Emit( | 1058 input_type = setter and self._NarrowInputType(setter.type.id) |
989 '\n $TYPE $NAME;\n', | 1059 if getter and setter and input_type == output_type: |
990 NAME=DartDomNameOfAttribute(getter), | 1060 self._members_emitter.Emit( |
991 TYPE=output_type) | 1061 '\n $TYPE $NAME;\n', |
992 return | 1062 NAME=DartDomNameOfAttribute(getter), |
993 if getter and not setter: | 1063 TYPE=output_type) |
994 self._members_emitter.Emit( | 1064 return |
995 '\n final $TYPE $NAME;\n', | 1065 if getter and not setter: |
996 NAME=DartDomNameOfAttribute(getter), | 1066 self._members_emitter.Emit( |
997 TYPE=output_type) | 1067 '\n final $TYPE $NAME;\n', |
998 return | 1068 NAME=DartDomNameOfAttribute(getter), |
1069 TYPE=output_type) | |
1070 return | |
999 self._AddAttributeUsingProperties(getter, setter) | 1071 self._AddAttributeUsingProperties(getter, setter) |
1000 | 1072 |
1001 def _AddAttributeUsingProperties(self, getter, setter): | 1073 def _AddAttributeUsingProperties(self, getter, setter): |
1002 if getter: | 1074 if getter: |
1003 self._AddGetter(getter) | 1075 self._AddGetter(getter) |
1004 if setter: | 1076 if setter: |
1005 self._AddSetter(setter) | 1077 self._AddSetter(setter) |
1006 | 1078 |
1007 def _AddGetter(self, attr): | 1079 def _AddGetter(self, attr): |
1008 self._AddRenamingGetter(attr, DartDomNameOfAttribute(attr)) | 1080 self._AddRenamingGetter(attr, DartDomNameOfAttribute(attr)) |
1009 | 1081 |
1010 def _AddSetter(self, attr): | 1082 def _AddSetter(self, attr): |
1011 self._AddRenamingSetter(attr, DartDomNameOfAttribute(attr)) | 1083 self._AddRenamingSetter(attr, DartDomNameOfAttribute(attr)) |
1012 | 1084 |
1013 def _AddRenamingGetter(self, attr, html_name): | 1085 def _AddRenamingGetter(self, attr, html_name): |
1086 if attr.type.id in _wrapped_types: | |
1087 getter = '_' + html_name | |
1088 else: | |
1089 getter = html_name | |
1014 return_type = self._NarrowOutputType(attr.type.id) | 1090 return_type = self._NarrowOutputType(attr.type.id) |
1015 self._members_emitter.Emit( | 1091 self._members_emitter.Emit( |
1016 '\n $TYPE get $(HTML_NAME)() native "return this.$NAME;";\n', | 1092 '\n $TYPE get $(HTML_NAME)() native "return this.$NAME;";\n', |
1017 HTML_NAME=html_name, | 1093 HTML_NAME=getter, |
1018 NAME=attr.id, | 1094 NAME=attr.id, |
1019 TYPE=return_type) | 1095 TYPE=return_type) |
1096 if attr.type.id in _wrapped_types: | |
1097 self._members_emitter.Emit( | |
1098 '\n $TYPE get $(HTML_NAME)() {' | |
sra1
2012/05/10 00:12:06
Any reason not to use => syntax?
| |
1099 '\n $BODY;' | |
1100 '\n }', | |
1101 HTML_NAME=html_name, | |
1102 BODY=_WrapAndReturnObject(self._interface.id, attr.type.id, | |
1103 getter, html_name), | |
1104 TYPE=attr.type.id) | |
1020 | 1105 |
1021 def _AddRenamingSetter(self, attr, html_name): | 1106 def _AddRenamingSetter(self, attr, html_name): |
1022 self._members_emitter.Emit( | 1107 self._members_emitter.Emit( |
1023 '\n void set $HTML_NAME($TYPE value)' | 1108 '\n void set $HTML_NAME($TYPE value)' |
1024 ' native "this.$NAME = value;";\n', | 1109 ' native "this.$NAME = value;";\n', |
1025 HTML_NAME=html_name, | 1110 HTML_NAME=html_name, |
1026 NAME=attr.id, | 1111 NAME=attr.id, |
1027 TYPE=self._NarrowInputType(attr.type.id)) | 1112 TYPE=self._NarrowInputType(attr.type.id)) |
1028 | 1113 |
1029 def AddOperation(self, info): | 1114 def AddOperation(self, info): |
1030 """ | 1115 """ |
1031 Arguments: | 1116 Arguments: |
1032 info: An OperationInfo object. | 1117 info: An OperationInfo object. |
1033 """ | 1118 """ |
1034 html_name = self._shared.RenameInHtmlLibrary( | 1119 html_name = self._shared.RenameInHtmlLibrary( |
1035 self._interface, info.name, implementation_class=True) | 1120 self._interface, info.name, implementation_class=True) |
1036 if not html_name: | 1121 if not html_name: |
1037 return | 1122 return |
1038 | 1123 |
1039 # Do we need a native body? | 1124 # Do we need a native body? |
sra1
2012/05/10 00:12:06
"Do we need a wrapper or a native body?"
| |
1040 if html_name != info.declared_name: | 1125 if info.type_name in _wrapped_types: |
1041 return_type = self._NarrowOutputType(info.type_name) | 1126 return_type = self._NarrowOutputType(info.type_name) |
1042 | 1127 |
1128 operation_emitter = self._members_emitter.Emit('$!SCOPE', | |
1129 INTERFACE=info.type_name, | |
1130 TYPE=return_type, | |
1131 HTML_NAME=html_name, | |
1132 NAME=info.declared_name, | |
1133 PARAMS=info.ParametersImplementationDeclaration( | |
1134 lambda type_name: self._NarrowInputType(type_name)), | |
1135 ARGLIST=info.ParametersAsArgumentList()) | |
1136 | |
1137 operation_emitter.Emit( | |
1138 '\n' | |
1139 ' $TYPE _$(HTML_NAME)($PARAMS) native "$NAME";\n') | |
1140 operation_emitter.Emit( | |
sra1
2012/05/10 00:12:06
Could fold this into the previous one.
| |
1141 '\n' | |
1142 ' $INTERFACE $(HTML_NAME)($PARAMS) =>' | |
1143 ' _$(INTERFACE)CrossFrameImpl._createSafe(_$HTML_NAME($ARGLIST));\n') | |
1144 | |
1145 elif html_name != info.declared_name: | |
1146 return_type = self._NarrowOutputType(info.type_name) | |
1147 | |
1043 operation_emitter = self._members_emitter.Emit('$!SCOPE', | 1148 operation_emitter = self._members_emitter.Emit('$!SCOPE', |
1044 TYPE=return_type, | 1149 TYPE=return_type, |
1045 HTML_NAME=html_name, | 1150 HTML_NAME=html_name, |
1046 NAME=info.declared_name, | 1151 NAME=info.declared_name, |
1047 PARAMS=info.ParametersImplementationDeclaration( | 1152 PARAMS=info.ParametersImplementationDeclaration( |
1048 lambda type_name: self._NarrowInputType(type_name))) | 1153 lambda type_name: self._NarrowInputType(type_name))) |
1049 | 1154 |
1050 operation_emitter.Emit( | 1155 operation_emitter.Emit( |
1051 '\n' | 1156 '\n' |
1052 ' $TYPE $(HTML_NAME)($PARAMS) native "$NAME";\n') | 1157 ' $TYPE $(HTML_NAME)($PARAMS) native "$NAME";\n') |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1118 dart_code = self._ImplFileEmitter(interface.id) | 1223 dart_code = self._ImplFileEmitter(interface.id) |
1119 return HtmlFrogClassGenerator(self, interface, template, | 1224 return HtmlFrogClassGenerator(self, interface, template, |
1120 super_interface_name, dart_code, self._shared) | 1225 super_interface_name, dart_code, self._shared) |
1121 | 1226 |
1122 def GenerateLibraries(self, lib_dir): | 1227 def GenerateLibraries(self, lib_dir): |
1123 self._GenerateLibFile( | 1228 self._GenerateLibFile( |
1124 'html_frog.darttemplate', | 1229 'html_frog.darttemplate', |
1125 os.path.join(lib_dir, 'html_frog.dart'), | 1230 os.path.join(lib_dir, 'html_frog.dart'), |
1126 (self._interface_system._dart_interface_file_paths + | 1231 (self._interface_system._dart_interface_file_paths + |
1127 self._interface_system._dart_callback_file_paths + | 1232 self._interface_system._dart_callback_file_paths + |
1233 self._cross_frame_system._dart_cross_frame_file_paths + | |
1128 self._dart_frog_file_paths)) | 1234 self._dart_frog_file_paths)) |
1129 | 1235 |
1130 def Finish(self): | 1236 def Finish(self): |
1131 pass | 1237 pass |
1132 | 1238 |
1133 def _ImplFileEmitter(self, name): | 1239 def _ImplFileEmitter(self, name): |
1134 """Returns the file emitter of the Frog implementation file.""" | 1240 """Returns the file emitter of the Frog implementation file.""" |
1135 # TODO(jmesserly): is this the right path | 1241 # TODO(jmesserly): is this the right path |
1136 path = os.path.join(self._output_dir, 'html', 'frog', '%s.dart' % name) | 1242 path = os.path.join(self._output_dir, 'html', 'frog', '%s.dart' % name) |
1137 self._dart_frog_file_paths.append(path) | 1243 self._dart_frog_file_paths.append(path) |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1182 | 1288 |
1183 def GenerateLibraries(self, lib_dir): | 1289 def GenerateLibraries(self, lib_dir): |
1184 # Library generated for implementation. | 1290 # Library generated for implementation. |
1185 auxiliary_dir = os.path.relpath(self._auxiliary_dir, self._output_dir) | 1291 auxiliary_dir = os.path.relpath(self._auxiliary_dir, self._output_dir) |
1186 | 1292 |
1187 self._GenerateLibFile( | 1293 self._GenerateLibFile( |
1188 'html_dartium.darttemplate', | 1294 'html_dartium.darttemplate', |
1189 os.path.join(lib_dir, 'html_dartium.dart'), | 1295 os.path.join(lib_dir, 'html_dartium.dart'), |
1190 (self._interface_system._dart_interface_file_paths + | 1296 (self._interface_system._dart_interface_file_paths + |
1191 self._interface_system._dart_callback_file_paths + | 1297 self._interface_system._dart_callback_file_paths + |
1298 self._cross_frame_system._dart_cross_frame_file_paths + | |
1192 self._dart_dartium_file_paths | 1299 self._dart_dartium_file_paths |
1193 ), | 1300 ), |
1194 AUXILIARY_DIR=MassagePath(auxiliary_dir), | 1301 AUXILIARY_DIR=MassagePath(auxiliary_dir), |
1195 WRAPCASES='\n'.join(self._wrap_cases)) | 1302 WRAPCASES='\n'.join(self._wrap_cases)) |
1196 | 1303 |
1197 def Finish(self): | 1304 def Finish(self): |
1198 pass | 1305 pass |
1199 | 1306 |
1200 # ------------------------------------------------------------------------------ | 1307 # ------------------------------------------------------------------------------ |
1201 | 1308 |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1379 # Constants are already defined on the interface. | 1486 # Constants are already defined on the interface. |
1380 pass | 1487 pass |
1381 | 1488 |
1382 def _MethodName(self, prefix, name): | 1489 def _MethodName(self, prefix, name): |
1383 method_name = prefix + name | 1490 method_name = prefix + name |
1384 if name in self._base_members: # Avoid illegal Dart 'static override'. | 1491 if name in self._base_members: # Avoid illegal Dart 'static override'. |
1385 method_name = method_name + '_' + self._interface.id | 1492 method_name = method_name + '_' + self._interface.id |
1386 return method_name | 1493 return method_name |
1387 | 1494 |
1388 def AddAttribute(self, getter, setter): | 1495 def AddAttribute(self, getter, setter): |
1496 if 'CheckSecurityForNode' in (getter or setter).ext_attrs: | |
1497 return | |
1389 dom_name = DartDomNameOfAttribute(getter or setter) | 1498 dom_name = DartDomNameOfAttribute(getter or setter) |
1390 html_getter_name = self._shared.RenameInHtmlLibrary( | 1499 html_getter_name = self._shared.RenameInHtmlLibrary( |
1391 self._interface, dom_name, 'get:', implementation_class=True) | 1500 self._interface, dom_name, 'get:', implementation_class=True) |
1392 html_setter_name = self._shared.RenameInHtmlLibrary( | 1501 html_setter_name = self._shared.RenameInHtmlLibrary( |
1393 self._interface, dom_name, 'set:', implementation_class=True) | 1502 self._interface, dom_name, 'set:', implementation_class=True) |
1394 | 1503 |
1395 if getter and html_getter_name: | 1504 if getter and html_getter_name: |
1396 self._AddGetter(getter, html_getter_name) | 1505 self._AddGetter(getter, html_getter_name) |
1397 if setter and html_setter_name: | 1506 if setter and html_setter_name: |
1398 self._AddSetter(setter, html_setter_name) | 1507 self._AddSetter(setter, html_setter_name) |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1700 # dispatch has removed f(X), leaving only f(Y), but there is no guarantee | 1809 # dispatch has removed f(X), leaving only f(Y), but there is no guarantee |
1701 # that Y = Z-X, so we need to check for Y. | 1810 # that Y = Z-X, so we need to check for Y. |
1702 true_code = emitter.Emit( | 1811 true_code = emitter.Emit( |
1703 '$(INDENT)if ($COND) {\n' | 1812 '$(INDENT)if ($COND) {\n' |
1704 '$!TRUE' | 1813 '$!TRUE' |
1705 '$(INDENT)}\n', | 1814 '$(INDENT)}\n', |
1706 COND=test, INDENT=indent) | 1815 COND=test, INDENT=indent) |
1707 self.GenerateDispatch( | 1816 self.GenerateDispatch( |
1708 true_code, info, indent + ' ', position + 1, positive) | 1817 true_code, info, indent + ' ', position + 1, positive) |
1709 return True | 1818 return True |
1819 | |
1820 # ------------------------------------------------------------------------------ | |
1821 | |
1822 # TODO(jacobr): there is far too much duplicated code between these bindings | |
1823 # and the Frog bindings. A larger scale refactoring needs to be performed to | |
1824 # reduce the duplicated logic. | |
1825 class HtmlCrossFrameGenerator(object): | |
1826 """Generates a cross-frame implementation of interfaces that must be | |
1827 securely exposed to other frames/isolates. The cross-frame | |
1828 implementation wraps the underlying implemation, only providing APIs | |
1829 deemded secure.""" | |
1830 | |
1831 def __init__(self, system, interface, template, super_interface, dart_code, | |
1832 shared): | |
1833 """Generates Dart cross-frame wrapper code for the given interface. | |
1834 | |
1835 Args: | |
1836 system: system that is executing this generator. | |
1837 template: template that output is generated into. | |
1838 interface: an IDLInterface instance. It is assumed that all types have | |
1839 been converted to Dart types (e.g. int, String), unless they are in | |
1840 the same package as the interface. | |
1841 super_interface: A string or None, the name of the common interface that | |
1842 this interface implements, if any. | |
1843 dart_code: an Emitter for the file containing the Dart implementation | |
1844 class. | |
1845 shared: functionaly shared across all Html generators. | |
1846 """ | |
1847 self._system = system | |
1848 self._interface = interface | |
1849 self._super_interface = super_interface | |
1850 self._dart_code = dart_code | |
1851 self._current_secondary_parent = None | |
1852 self._shared = shared | |
1853 self._template = template | |
1854 | |
1855 def NativeObjectName(self): | |
1856 return '_ptr' | |
1857 | |
1858 def StartInterface(self): | |
1859 interface = self._interface | |
1860 interface_name = interface.id | |
1861 self._class_name = self._ImplClassName(interface_name) | |
1862 | |
1863 self._members_emitter = self._dart_code.Emit(self._template, | |
1864 NAME=interface_name, | |
1865 CLASSNAME=self._class_name, | |
1866 POINTER=self.NativeObjectName(), | |
1867 LOCAL=_cross_frame_wrapped_types[interface_name][1] | |
1868 ) | |
1869 | |
1870 def _ImplClassName(self, type_name): | |
1871 return self._shared._ImplClassName(type_name) | |
1872 | |
1873 def FinishInterface(self): | |
1874 """.""" | |
1875 pass | |
1876 | |
1877 def AddConstant(self, constant): | |
1878 # Constants are already defined on the interface. | |
1879 pass | |
1880 | |
1881 def AddAttribute(self, getter, setter): | |
1882 dom_name = DartDomNameOfAttribute(getter or setter) | |
1883 html_getter_name = self._shared.RenameInHtmlLibrary( | |
1884 self._interface, dom_name, 'get:', implementation_class=True) | |
1885 html_setter_name = self._shared.RenameInHtmlLibrary( | |
1886 self._interface, dom_name, 'set:', implementation_class=True) | |
1887 | |
1888 # TODO(vsm): Generate stubs that throws an error if getter or | |
1889 # setter is suppressed. | |
1890 if (getter and html_getter_name and | |
1891 ('DoNotCheckSecurityOnGetter' in getter.ext_attrs or | |
1892 'DoNotCheckSecurity' in getter.ext_attrs)): | |
1893 self._AddGetter(getter, html_getter_name) | |
1894 if (setter and html_setter_name and | |
1895 ('DoNotCheckSecurityOnSetter' in setter.ext_attrs or | |
1896 'DoNotCheckSecurity' in setter.ext_attrs)): | |
1897 self._AddSetter(setter, html_setter_name) | |
1898 | |
1899 def _AddGetter(self, attr, html_name): | |
1900 self._members_emitter.Emit( | |
1901 '\n' | |
1902 ' $TYPE get $(NAME)() => $(THIS).$NAME;\n', | |
1903 NAME=html_name, | |
1904 TYPE=DartType(attr.type.id), | |
1905 THIS=self.NativeObjectName()) | |
1906 | |
1907 def _AddSetter(self, attr, html_name): | |
1908 self._members_emitter.Emit( | |
1909 '\n' | |
1910 ' void set $(NAME)($TYPE value) { ' | |
1911 '$(THIS).$NAME = value; }\n', | |
1912 NAME=html_name, | |
1913 TYPE=DartType(attr.type.id), | |
1914 THIS=self.NativeObjectName()) | |
1915 | |
1916 def AddSecondaryAttribute(self, interface, getter, setter): | |
1917 pass | |
1918 | |
1919 def AddSecondaryOperation(self, interface, info): | |
1920 pass | |
1921 | |
1922 def AddEventAttributes(self, event_attrs): | |
1923 pass | |
1924 | |
1925 def AddIndexer(self, element_type): | |
1926 """Adds all the methods required to complete implementation of List.""" | |
1927 raise Exception('Indexers not yet supported for cross frame types') | |
1928 | |
1929 def AddOperation(self, info): | |
1930 """ | |
1931 Arguments: | |
1932 info: An OperationInfo object. | |
1933 """ | |
1934 if 'DoNotCheckSecurity' not in info.overloads[0].ext_attrs: | |
1935 # TODO(vsm): Generate stub that throws an error. | |
1936 return | |
1937 | |
1938 html_name = self._shared.RenameInHtmlLibrary( | |
1939 self._interface, info.name, implementation_class=True) | |
1940 | |
1941 if not html_name: | |
1942 return | |
1943 | |
1944 body = self._members_emitter.Emit( | |
1945 '\n' | |
1946 ' $TYPE $NAME($PARAMS) {\n' | |
1947 '$!BODY' | |
1948 ' }\n', | |
1949 TYPE=info.type_name, | |
1950 NAME=html_name, | |
1951 PARAMS=info.ParametersImplementationDeclaration()) | |
1952 | |
1953 # Process in order of ascending number of arguments to ensure missing | |
1954 # optional arguments are processed early. | |
1955 overloads = sorted(info.overloads, | |
1956 key=lambda overload: len(overload.arguments)) | |
1957 self._native_version = 0 | |
1958 fallthrough = self.GenerateDispatch(body, info, ' ', 0, overloads) | |
1959 if fallthrough: | |
1960 body.Emit(' throw "Incorrect number or type of arguments";\n'); | |
1961 | |
1962 def GenerateSingleOperation(self, emitter, info, indent, operation): | |
sra1
2012/05/10 00:12:06
We really need to avoid another copy of the dispat
| |
1963 """Generates a call to a single operation. | |
1964 | |
1965 Arguments: | |
1966 emitter: an Emitter for the body of a block of code. | |
1967 info: the compound information about the operation and its overloads. | |
1968 indent: an indentation string for generated code. | |
1969 operation: the IDLOperation to call. | |
1970 """ | |
1971 argument_expressions = ', '.join([i.name for i in info.param_infos]) | |
1972 | |
1973 if info.type_name != 'void': | |
1974 # We could place the logic for handling Document directly in _wrap | |
1975 # but we chose to place it here so that bugs in the wrapper and | |
1976 # wrapperless implementations are more consistent. | |
1977 emitter.Emit('$(INDENT)return $(THIS).$NAME($ARGS);\n', | |
1978 INDENT=indent, | |
1979 THIS=self.NativeObjectName(), | |
1980 NAME=info.name, | |
1981 ARGS=argument_expressions) | |
1982 else: | |
1983 emitter.Emit('$(INDENT)$(THIS).$NAME($ARGS);\n' | |
1984 '$(INDENT)return;\n', | |
1985 INDENT=indent, | |
1986 THIS=self.NativeObjectName(), | |
1987 NAME=info.name, | |
1988 ARGS=argument_expressions) | |
1989 | |
1990 def GenerateDispatch(self, emitter, info, indent, position, overloads): | |
1991 """Generates a dispatch to one of the overloads. | |
1992 | |
1993 Arguments: | |
1994 emitter: an Emitter for the body of a block of code. | |
1995 info: the compound information about the operation and its overloads. | |
1996 indent: an indentation string for generated code. | |
1997 position: the index of the parameter to dispatch on. | |
1998 overloads: a list of the remaining IDLOperations to dispatch. | |
1999 | |
2000 Returns True if the dispatch can fall through on failure, False if the code | |
2001 always dispatches. | |
2002 """ | |
2003 | |
2004 def NullCheck(name): | |
2005 return '%s === null' % name | |
2006 | |
2007 def TypeCheck(name, type): | |
2008 return '%s is %s' % (name, type) | |
2009 | |
2010 if position == len(info.param_infos): | |
2011 if len(overloads) > 1: | |
2012 raise Exception('Duplicate operations ' + str(overloads)) | |
2013 operation = overloads[0] | |
2014 self.GenerateSingleOperation(emitter, info, indent, operation) | |
2015 return False | |
2016 | |
2017 # FIXME: Consider a simpler dispatch that iterates over the | |
2018 # overloads and generates an overload specific check. Revisit | |
2019 # when we move to named optional arguments. | |
2020 | |
2021 # Partition the overloads to divide and conquer on the dispatch. | |
2022 positive = [] | |
2023 negative = [] | |
2024 first_overload = overloads[0] | |
2025 param = info.param_infos[position] | |
2026 | |
2027 if position < len(first_overload.arguments): | |
2028 # FIXME: This will not work if the second overload has a more | |
2029 # precise type than the first. E.g., | |
2030 # void foo(Node x); | |
2031 # void foo(Element x); | |
2032 type = DartType(first_overload.arguments[position].type.id) | |
2033 test = TypeCheck(param.name, type) | |
2034 pred = lambda op: (len(op.arguments) > position and | |
2035 DartType(op.arguments[position].type.id) == type) | |
2036 else: | |
2037 type = None | |
2038 test = NullCheck(param.name) | |
2039 pred = lambda op: position >= len(op.arguments) | |
2040 | |
2041 for overload in overloads: | |
2042 if pred(overload): | |
2043 positive.append(overload) | |
2044 else: | |
2045 negative.append(overload) | |
2046 | |
2047 if positive and negative: | |
2048 (true_code, false_code) = emitter.Emit( | |
2049 '$(INDENT)if ($COND) {\n' | |
2050 '$!TRUE' | |
2051 '$(INDENT)} else {\n' | |
2052 '$!FALSE' | |
2053 '$(INDENT)}\n', | |
2054 COND=test, INDENT=indent) | |
2055 fallthrough1 = self.GenerateDispatch( | |
2056 true_code, info, indent + ' ', position + 1, positive) | |
2057 fallthrough2 = self.GenerateDispatch( | |
2058 false_code, info, indent + ' ', position, negative) | |
2059 return fallthrough1 or fallthrough2 | |
2060 | |
2061 if negative: | |
2062 raise Exception('Internal error, must be all positive') | |
2063 | |
2064 # All overloads require the same test. Do we bother? | |
2065 | |
2066 # If the test is the same as the method's formal parameter then checked mode | |
2067 # will have done the test already. (It could be null too but we ignore that | |
2068 # case since all the overload behave the same and we don't know which types | |
2069 # in the IDL are not nullable.) | |
2070 if type == param.dart_type: | |
2071 return self.GenerateDispatch( | |
2072 emitter, info, indent, position + 1, positive) | |
2073 | |
2074 # Otherwise the overloads have the same type but the type is a substype of | |
2075 # the method's synthesized formal parameter. e.g we have overloads f(X) and | |
2076 # f(Y), implemented by the synthesized method f(Z) where X<Z and Y<Z. The | |
2077 # dispatch has removed f(X), leaving only f(Y), but there is no guarantee | |
2078 # that Y = Z-X, so we need to check for Y. | |
2079 true_code = emitter.Emit( | |
2080 '$(INDENT)if ($COND) {\n' | |
2081 '$!TRUE' | |
2082 '$(INDENT)}\n', | |
2083 COND=test, INDENT=indent) | |
2084 self.GenerateDispatch( | |
2085 true_code, info, indent + ' ', position + 1, positive) | |
2086 return True | |
OLD | NEW |