| 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 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 'SelectElement.selectedOptions', | 26 'SelectElement.selectedOptions', |
| 27 'TableElement.createTBody', | 27 'TableElement.createTBody', |
| 28 'LocalWindow.document', | 28 'LocalWindow.document', |
| 29 'LocalWindow.indexedDB', | 29 'LocalWindow.indexedDB', |
| 30 'LocalWindow.location', | 30 'LocalWindow.location', |
| 31 'LocalWindow.open', | 31 'LocalWindow.open', |
| 32 'LocalWindow.webkitCancelAnimationFrame', | 32 'LocalWindow.webkitCancelAnimationFrame', |
| 33 'LocalWindow.webkitRequestAnimationFrame', | 33 'LocalWindow.webkitRequestAnimationFrame', |
| 34 ]) | 34 ]) |
| 35 | 35 |
| 36 # This map controls merging of interfaces in dart:html library. | |
| 37 # All constants, attributes, and operations of merged interface (key) are | |
| 38 # added to target interface (value). All references to the merged interface | |
| 39 # (e.g. parameter types, return types, parent interfaces) are replaced with | |
| 40 # target interface. There are two important restrictions: | |
| 41 # 1) Merged and target interfaces shouldn't have common members, otherwise there | |
| 42 # would be duplicated declarations in generated Dart code. | |
| 43 # 2) Merged interface should be direct child of target interface, so the | |
| 44 # children of merged interface are not affected by the merge. | |
| 45 # As a consequence, target interface implementation and its direct children | |
| 46 # interface implementations should implement merged attribute accessors and | |
| 47 # operations. For example, SVGElement and Element implementation classes should | |
| 48 # implement HTMLElement.insertAdjacentElement(), HTMLElement.innerHTML, etc. | |
| 49 _merged_html_interfaces = { | |
| 50 'HTMLDocument': 'Document', | |
| 51 'HTMLElement': 'Element' | |
| 52 } | |
| 53 | 36 |
| 54 # Types that are accessible cross-frame in a limited fashion. | 37 # Types that are accessible cross-frame in a limited fashion. |
| 55 # In these cases, the base type (e.g., Window) provides restricted access | 38 # In these cases, the base type (e.g., Window) provides restricted access |
| 56 # while the subtype (e.g., LocalWindow) provides full access to the | 39 # while the subtype (e.g., LocalWindow) provides full access to the |
| 57 # corresponding objects if there are from the same frame. | 40 # corresponding objects if there are from the same frame. |
| 58 _secure_base_types = { | 41 _secure_base_types = { |
| 59 'LocalWindow': 'Window', | 42 'LocalWindow': 'Window', |
| 60 'LocalLocation': 'Location', | 43 'LocalLocation': 'Location', |
| 61 'LocalHistory': 'History', | 44 'LocalHistory': 'History', |
| 62 } | 45 } |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 212 def __init__(self, options, library_emitter, event_generator, interface, | 195 def __init__(self, options, library_emitter, event_generator, interface, |
| 213 backend): | 196 backend): |
| 214 self._renamer = options.renamer | 197 self._renamer = options.renamer |
| 215 self._database = options.database | 198 self._database = options.database |
| 216 self._template_loader = options.templates | 199 self._template_loader = options.templates |
| 217 self._type_registry = options.type_registry | 200 self._type_registry = options.type_registry |
| 218 self._library_emitter = library_emitter | 201 self._library_emitter = library_emitter |
| 219 self._event_generator = event_generator | 202 self._event_generator = event_generator |
| 220 self._interface = interface | 203 self._interface = interface |
| 221 self._backend = backend | 204 self._backend = backend |
| 205 self._interface_type_info = self._type_registry.TypeInfo(self._interface.id) |
| 222 self._html_interface_name = options.renamer.RenameInterface(self._interface) | 206 self._html_interface_name = options.renamer.RenameInterface(self._interface) |
| 223 | 207 |
| 224 def Generate(self): | 208 def Generate(self): |
| 225 if 'Callback' in self._interface.ext_attrs: | 209 if 'Callback' in self._interface.ext_attrs: |
| 226 self.GenerateCallback() | 210 self.GenerateCallback() |
| 227 else: | 211 else: |
| 228 self.GenerateInterface() | 212 self.GenerateInterface() |
| 229 | 213 |
| 230 def GenerateCallback(self): | 214 def GenerateCallback(self): |
| 231 """Generates a typedef for the callback interface.""" | 215 """Generates a typedef for the callback interface.""" |
| 232 handlers = [operation for operation in self._interface.operations | 216 handlers = [operation for operation in self._interface.operations |
| 233 if operation.id == 'handleEvent'] | 217 if operation.id == 'handleEvent'] |
| 234 info = AnalyzeOperation(self._interface, handlers) | 218 info = AnalyzeOperation(self._interface, handlers) |
| 235 code = self._library_emitter.FileEmitter(self._interface.id) | 219 code = self._library_emitter.FileEmitter(self._interface.id) |
| 236 code.Emit(self._template_loader.Load('callback.darttemplate')) | 220 code.Emit(self._template_loader.Load('callback.darttemplate')) |
| 237 code.Emit('typedef $TYPE $NAME($PARAMS);\n', | 221 code.Emit('typedef $TYPE $NAME($PARAMS);\n', |
| 238 NAME=self._interface.id, | 222 NAME=self._interface.id, |
| 239 TYPE=self._DartType(info.type_name), | 223 TYPE=self._DartType(info.type_name), |
| 240 PARAMS=info.ParametersImplementationDeclaration(self._DartType)) | 224 PARAMS=info.ParametersImplementationDeclaration(self._DartType)) |
| 241 self._backend.GenerateCallback(info) | 225 self._backend.GenerateCallback(info) |
| 242 | 226 |
| 243 def GenerateInterface(self): | 227 def GenerateInterface(self): |
| 244 interface_type_info = self._type_registry.TypeInfo(self._interface.id) | 228 if (self._interface_type_info.has_generated_interface() and |
| 245 if (not self._interface.id in _merged_html_interfaces and | 229 not self._interface_type_info.merged_into()): |
| 246 interface_type_info.has_generated_interface()): | |
| 247 interface_emitter = self._library_emitter.FileEmitter( | 230 interface_emitter = self._library_emitter.FileEmitter( |
| 248 self._html_interface_name) | 231 self._html_interface_name) |
| 249 else: | 232 else: |
| 250 interface_emitter = emitter.Emitter() | 233 interface_emitter = emitter.Emitter() |
| 251 | 234 |
| 252 template_file = 'interface_%s.darttemplate' % self._html_interface_name | 235 template_file = 'interface_%s.darttemplate' % self._html_interface_name |
| 253 interface_template = (self._template_loader.TryLoad(template_file) or | 236 interface_template = (self._template_loader.TryLoad(template_file) or |
| 254 self._template_loader.Load('interface.darttemplate')) | 237 self._template_loader.Load('interface.darttemplate')) |
| 255 | 238 |
| 256 typename = self._html_interface_name | 239 typename = self._html_interface_name |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 321 (self._type_comment_emitter, | 304 (self._type_comment_emitter, |
| 322 self._members_emitter, | 305 self._members_emitter, |
| 323 self._top_level_emitter) = interface_emitter.Emit( | 306 self._top_level_emitter) = interface_emitter.Emit( |
| 324 interface_template + '$!TOP_LEVEL', | 307 interface_template + '$!TOP_LEVEL', |
| 325 ID=typename, | 308 ID=typename, |
| 326 EXTENDS=implements_str) | 309 EXTENDS=implements_str) |
| 327 | 310 |
| 328 self._type_comment_emitter.Emit("/// @domName $DOMNAME", | 311 self._type_comment_emitter.Emit("/// @domName $DOMNAME", |
| 329 DOMNAME=self._interface.doc_js_name) | 312 DOMNAME=self._interface.doc_js_name) |
| 330 | 313 |
| 331 if self._backend.HasImplementation(): | 314 implementation_emitter = self._ImplementationEmitter() |
| 332 if not self._interface.id in _merged_html_interfaces: | |
| 333 name = self._html_interface_name | |
| 334 basename = '%sImpl' % name | |
| 335 else: | |
| 336 basename = '%sImpl_Merged' % self._html_interface_name | |
| 337 implementation_emitter = self._library_emitter.FileEmitter(basename) | |
| 338 else: | |
| 339 implementation_emitter = emitter.Emitter() | |
| 340 | |
| 341 base_class = self._backend.BaseClassName() | 315 base_class = self._backend.BaseClassName() |
| 342 interface_type_info = self._type_registry.TypeInfo(self._interface.id) | 316 interface_type_info = self._type_registry.TypeInfo(self._interface.id) |
| 343 implemented_interfaces = [interface_type_info.interface_name()] +\ | 317 implemented_interfaces = [interface_type_info.interface_name()] +\ |
| 344 self._backend.AdditionalImplementedInterfaces() | 318 self._backend.AdditionalImplementedInterfaces() |
| 345 self._implementation_members_emitter = implementation_emitter.Emit( | 319 self._implementation_members_emitter = implementation_emitter.Emit( |
| 346 self._backend.ImplementationTemplate(), | 320 self._backend.ImplementationTemplate(), |
| 347 CLASSNAME=self._backend.ImplementationClassName(), | 321 CLASSNAME=self._backend.ImplementationClassName(), |
| 348 EXTENDS=' extends %s' % base_class if base_class else '', | 322 EXTENDS=' extends %s' % base_class if base_class else '', |
| 349 IMPLEMENTS=' implements ' + ', '.join(implemented_interfaces), | 323 IMPLEMENTS=' implements ' + ', '.join(implemented_interfaces), |
| 350 NATIVESPEC=self._backend.NativeSpec()) | 324 NATIVESPEC=self._backend.NativeSpec()) |
| (...skipping 23 matching lines...) Expand all Loading... |
| 374 events_interface = self._event_generator.ProcessInterface( | 348 events_interface = self._event_generator.ProcessInterface( |
| 375 self._interface, self._html_interface_name, | 349 self._interface, self._html_interface_name, |
| 376 self._backend.CustomJSMembers(), | 350 self._backend.CustomJSMembers(), |
| 377 interface_emitter, implementation_emitter) | 351 interface_emitter, implementation_emitter) |
| 378 if events_interface: | 352 if events_interface: |
| 379 self._EmitEventGetter(events_interface, '_%sImpl' % events_interface) | 353 self._EmitEventGetter(events_interface, '_%sImpl' % events_interface) |
| 380 | 354 |
| 381 old_backend = self._backend | 355 old_backend = self._backend |
| 382 if not self._backend.ImplementsMergedMembers(): | 356 if not self._backend.ImplementsMergedMembers(): |
| 383 self._backend = HtmlGeneratorDummyBackend() | 357 self._backend = HtmlGeneratorDummyBackend() |
| 384 for merged_interface in _merged_html_interfaces: | 358 merged_interface = self._interface_type_info.merged_interface() |
| 385 if _merged_html_interfaces[merged_interface] == self._interface.id: | 359 if merged_interface: |
| 386 merged_interface = self._database.GetInterface(merged_interface) | 360 self.AddMembers(self._database.GetInterface(merged_interface)) |
| 387 self.AddMembers(merged_interface) | |
| 388 self._backend = old_backend | 361 self._backend = old_backend |
| 389 | 362 |
| 390 self.AddMembers(self._interface) | 363 self.AddMembers(self._interface) |
| 391 self.AddSecondaryMembers(self._interface) | 364 self.AddSecondaryMembers(self._interface) |
| 392 self._backend.FinishInterface() | 365 self._backend.FinishInterface() |
| 393 | 366 |
| 394 def AddMembers(self, interface): | 367 def AddMembers(self, interface): |
| 395 for const in sorted(interface.constants, ConstantOutputOrder): | 368 for const in sorted(interface.constants, ConstantOutputOrder): |
| 396 self.AddConstant(const) | 369 self.AddConstant(const) |
| 397 | 370 |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 525 self._backend.SecondaryContext(interface) | 498 self._backend.SecondaryContext(interface) |
| 526 self.AddOperation(info, True) | 499 self.AddOperation(info, True) |
| 527 | 500 |
| 528 def AddConstant(self, constant): | 501 def AddConstant(self, constant): |
| 529 type = TypeOrNothing(self._DartType(constant.type.id), constant.type.id) | 502 type = TypeOrNothing(self._DartType(constant.type.id), constant.type.id) |
| 530 self._members_emitter.Emit('\n static const $TYPE$NAME = $VALUE;\n', | 503 self._members_emitter.Emit('\n static const $TYPE$NAME = $VALUE;\n', |
| 531 NAME=constant.id, | 504 NAME=constant.id, |
| 532 TYPE=type, | 505 TYPE=type, |
| 533 VALUE=constant.value) | 506 VALUE=constant.value) |
| 534 | 507 |
| 508 def _ImplementationEmitter(self): |
| 509 if IsPureInterface(self._interface.id): |
| 510 return emitter.Emitter() |
| 511 |
| 512 if not self._interface_type_info.merged_into(): |
| 513 name = self._html_interface_name |
| 514 basename = '%sImpl' % name |
| 515 else: |
| 516 if self._backend.ImplementsMergedMembers(): |
| 517 # Merged members are implemented in target interface implementation. |
| 518 return emitter.Emitter() |
| 519 basename = '%sImpl_Merged' % self._html_interface_name |
| 520 return self._library_emitter.FileEmitter(basename) |
| 521 |
| 535 def _EmitEventGetter(self, events_interface, events_class): | 522 def _EmitEventGetter(self, events_interface, events_class): |
| 536 self._members_emitter.Emit( | 523 self._members_emitter.Emit( |
| 537 '\n /**' | 524 '\n /**' |
| 538 '\n * @domName EventTarget.addEventListener, ' | 525 '\n * @domName EventTarget.addEventListener, ' |
| 539 'EventTarget.removeEventListener, EventTarget.dispatchEvent' | 526 'EventTarget.removeEventListener, EventTarget.dispatchEvent' |
| 540 '\n */' | 527 '\n */' |
| 541 '\n $TYPE get on;\n', | 528 '\n $TYPE get on;\n', |
| 542 TYPE=events_interface) | 529 TYPE=events_interface) |
| 543 | 530 |
| 544 self._implementation_members_emitter.Emit( | 531 self._implementation_members_emitter.Emit( |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 590 class Dart2JSBackend(object): | 577 class Dart2JSBackend(object): |
| 591 """Generates a dart2js class for the dart:html library from a DOM IDL | 578 """Generates a dart2js class for the dart:html library from a DOM IDL |
| 592 interface. | 579 interface. |
| 593 """ | 580 """ |
| 594 | 581 |
| 595 def __init__(self, interface, options): | 582 def __init__(self, interface, options): |
| 596 self._interface = interface | 583 self._interface = interface |
| 597 self._database = options.database | 584 self._database = options.database |
| 598 self._template_loader = options.templates | 585 self._template_loader = options.templates |
| 599 self._type_registry = options.type_registry | 586 self._type_registry = options.type_registry |
| 587 self._interface_type_info = self._type_registry.TypeInfo(self._interface.id) |
| 600 self._html_interface_name = options.renamer.RenameInterface(self._interface) | 588 self._html_interface_name = options.renamer.RenameInterface(self._interface) |
| 601 self._current_secondary_parent = None | 589 self._current_secondary_parent = None |
| 602 | 590 |
| 603 def HasImplementation(self): | |
| 604 return not (IsPureInterface(self._interface.id) or | |
| 605 self._interface.id in _merged_html_interfaces) | |
| 606 | |
| 607 def ImplementationClassName(self): | 591 def ImplementationClassName(self): |
| 608 return self._ImplClassName(self._html_interface_name) | 592 return self._ImplClassName(self._html_interface_name) |
| 609 | 593 |
| 610 def ImplementsMergedMembers(self): | 594 def ImplementsMergedMembers(self): |
| 611 return True | 595 return True |
| 612 | 596 |
| 613 def _ImplClassName(self, type_name): | 597 def _ImplClassName(self, type_name): |
| 614 return '_%sImpl' % type_name | 598 return '_%sImpl' % type_name |
| 615 | 599 |
| 616 def GenerateCallback(self, info): | 600 def GenerateCallback(self, info): |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 728 self._AddAttributeUsingProperties(attribute, html_name, read_only) | 712 self._AddAttributeUsingProperties(attribute, html_name, read_only) |
| 729 return | 713 return |
| 730 | 714 |
| 731 # If the attribute is shadowing, we can't generate a shadowing | 715 # If the attribute is shadowing, we can't generate a shadowing |
| 732 # field (Issue 1633). | 716 # field (Issue 1633). |
| 733 # TODO(sra): _FindShadowedAttribute does not take into account the html | 717 # TODO(sra): _FindShadowedAttribute does not take into account the html |
| 734 # renaming. we should be looking for another attribute that has the same | 718 # renaming. we should be looking for another attribute that has the same |
| 735 # html_name. Two attributes with the same IDL name might not match if one | 719 # html_name. Two attributes with the same IDL name might not match if one |
| 736 # is renamed. | 720 # is renamed. |
| 737 (super_attribute, super_attribute_interface) = self._FindShadowedAttribute( | 721 (super_attribute, super_attribute_interface) = self._FindShadowedAttribute( |
| 738 attribute, _merged_html_interfaces) | 722 attribute) |
| 739 if super_attribute: | 723 if super_attribute: |
| 740 if read_only: | 724 if read_only: |
| 741 if attribute.type.id == super_attribute.type.id: | 725 if attribute.type.id == super_attribute.type.id: |
| 742 # Compatible attribute, use the superclass property. This works | 726 # Compatible attribute, use the superclass property. This works |
| 743 # because JavaScript will do its own dynamic dispatch. | 727 # because JavaScript will do its own dynamic dispatch. |
| 744 self._members_emitter.Emit( | 728 self._members_emitter.Emit( |
| 745 '\n' | 729 '\n' |
| 746 ' // Use implementation from $SUPER.\n' | 730 ' // Use implementation from $SUPER.\n' |
| 747 ' // final $TYPE $NAME;\n', | 731 ' // final $TYPE $NAME;\n', |
| 748 SUPER=super_attribute_interface, | 732 SUPER=super_attribute_interface, |
| (...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1050 return type_name | 1034 return type_name |
| 1051 return self._type_registry.TypeInfo(type_name).narrow_dart_type() | 1035 return self._type_registry.TypeInfo(type_name).narrow_dart_type() |
| 1052 | 1036 |
| 1053 def _NarrowInputType(self, type_name): | 1037 def _NarrowInputType(self, type_name): |
| 1054 return self._NarrowToImplementationType(type_name) | 1038 return self._NarrowToImplementationType(type_name) |
| 1055 | 1039 |
| 1056 def _NarrowOutputType(self, type_name): | 1040 def _NarrowOutputType(self, type_name): |
| 1057 secure_name = SecureOutputType(self, type_name, True) | 1041 secure_name = SecureOutputType(self, type_name, True) |
| 1058 return self._NarrowToImplementationType(secure_name) | 1042 return self._NarrowToImplementationType(secure_name) |
| 1059 | 1043 |
| 1060 def _FindShadowedAttribute(self, attr, merged_interfaces={}): | 1044 def _FindShadowedAttribute(self, attr): |
| 1061 """Returns (attribute, superinterface) or (None, None).""" | 1045 """Returns (attribute, superinterface) or (None, None).""" |
| 1062 def FindInParent(interface): | 1046 def FindInParent(interface): |
| 1063 """Returns matching attribute in parent, or None.""" | 1047 """Returns matching attribute in parent, or None.""" |
| 1064 if interface.parents: | 1048 if interface.parents: |
| 1065 parent = interface.parents[0] | 1049 parent = interface.parents[0] |
| 1066 if IsDartCollectionType(parent.type.id): | 1050 if IsDartCollectionType(parent.type.id): |
| 1067 return (None, None) | 1051 return (None, None) |
| 1068 if IsPureInterface(parent.type.id): | 1052 if IsPureInterface(parent.type.id): |
| 1069 return (None, None) | 1053 return (None, None) |
| 1070 if self._database.HasInterface(parent.type.id): | 1054 if self._database.HasInterface(parent.type.id): |
| 1071 interfaces_to_search_in = [] | 1055 interfaces_to_search_in = [] |
| 1072 if parent.type.id in merged_interfaces: | 1056 parent_interface_name = parent.type.id |
| 1057 interfaces_to_search_in.append(parent_interface_name) |
| 1058 parent_type_info = self._type_registry.TypeInfo(parent_interface_name) |
| 1059 if parent_type_info.merged_into(): |
| 1073 # IDL parent was merged into another interface, which became a | 1060 # IDL parent was merged into another interface, which became a |
| 1074 # parent interface in Dart. | 1061 # parent interface in Dart. |
| 1075 interfaces_to_search_in.append(parent.type.id) | 1062 parent_interface_name = parent_type_info.merged_into() |
| 1076 parent_interface_name = merged_interfaces[parent.type.id] | 1063 interfaces_to_search_in.append(parent_interface_name) |
| 1077 else: | 1064 elif parent_type_info.merged_interface(): |
| 1078 parent_interface_name = parent.type.id | 1065 # IDL parent has another interface that was merged into it. |
| 1066 interfaces_to_search_in.append(parent_type_info.merged_interface()) |
| 1079 | 1067 |
| 1080 for interface_name in merged_interfaces: | |
| 1081 if merged_interfaces[interface_name] == parent_interface_name: | |
| 1082 # IDL parent has another interface that was merged into it. | |
| 1083 interfaces_to_search_in.append(interface_name) | |
| 1084 | |
| 1085 interfaces_to_search_in.append(parent_interface_name) | |
| 1086 for interface_name in interfaces_to_search_in: | 1068 for interface_name in interfaces_to_search_in: |
| 1087 interface = self._database.GetInterface(interface_name) | 1069 interface = self._database.GetInterface(interface_name) |
| 1088 attr2 = FindMatchingAttribute(interface, attr) | 1070 attr2 = FindMatchingAttribute(interface, attr) |
| 1089 if attr2: | 1071 if attr2: |
| 1090 return (attr2, parent_interface_name) | 1072 return (attr2, parent_interface_name) |
| 1091 | 1073 |
| 1092 return FindInParent( | 1074 return FindInParent( |
| 1093 self._database.GetInterface(parent_interface_name)) | 1075 self._database.GetInterface(parent_interface_name)) |
| 1094 return (None, None) | 1076 return (None, None) |
| 1095 | 1077 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1123 | 1105 |
| 1124 library_emitter = self._multiemitter.FileEmitter(library_file_path) | 1106 library_emitter = self._multiemitter.FileEmitter(library_file_path) |
| 1125 library_file_dir = os.path.dirname(library_file_path) | 1107 library_file_dir = os.path.dirname(library_file_path) |
| 1126 auxiliary_dir = os.path.relpath(auxiliary_dir, library_file_dir) | 1108 auxiliary_dir = os.path.relpath(auxiliary_dir, library_file_dir) |
| 1127 imports_emitter = library_emitter.Emit( | 1109 imports_emitter = library_emitter.Emit( |
| 1128 self._template, AUXILIARY_DIR=massage_path(auxiliary_dir)) | 1110 self._template, AUXILIARY_DIR=massage_path(auxiliary_dir)) |
| 1129 for path in sorted(self._path_to_emitter.keys()): | 1111 for path in sorted(self._path_to_emitter.keys()): |
| 1130 relpath = os.path.relpath(path, library_file_dir) | 1112 relpath = os.path.relpath(path, library_file_dir) |
| 1131 imports_emitter.Emit( | 1113 imports_emitter.Emit( |
| 1132 "#source('$PATH');\n", PATH=massage_path(relpath)) | 1114 "#source('$PATH');\n", PATH=massage_path(relpath)) |
| OLD | NEW |