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

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

Issue 10456006: Wrapperless dart:html for Dartium. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 792 matching lines...) Expand 10 before | Expand all | Expand 10 after
803 def _EmitElementFactory(self, typename): 803 def _EmitElementFactory(self, typename):
804 """Returns pair (constructor_info, factory_provider_name).""" 804 """Returns pair (constructor_info, factory_provider_name)."""
805 if typename not in _html_element_constructors: 805 if typename not in _html_element_constructors:
806 return (None, None) 806 return (None, None)
807 info = _html_element_constructors[typename] 807 info = _html_element_constructors[typename]
808 if isinstance(info, str): info = ElementCtorInfo(tag=info) 808 if isinstance(info, str): info = ElementCtorInfo(tag=info)
809 constructor_info = info.ConstructorInfo(self._interface) 809 constructor_info = info.ConstructorInfo(self._interface)
810 em = self._system._EmitterForFactoryProviderBody(info.factory_provider_name) 810 em = self._system._EmitterForFactoryProviderBody(info.factory_provider_name)
811 inits = em.Emit( 811 inits = em.Emit(
812 '\n' 812 '\n'
813 ' factory $CONSTRUCTOR($PARAMS) {\n' 813 ' factory $INTERFACE($PARAMS) {\n'
814 ' $CLASSNAME _e = _document.$dom_createElement("$TAG");\n' 814 ' $INTERFACE _e = _document.$dom_createElement("$TAG");\n'
815 '$!INITS' 815 '$!INITS'
816 ' return _e;\n' 816 ' return _e;\n'
817 ' }\n', 817 ' }\n',
818 CONSTRUCTOR=typename, 818 INTERFACE=typename,
vsm 2012/05/31 05:22:20 Pavel, this change is breaking html_frog. We're g
819 CLASSNAME='_' + typename + 'Impl', # TODO: fix
820 TAG=info.tag, 819 TAG=info.tag,
821 PARAMS=constructor_info.ParametersInterfaceDeclaration()) 820 PARAMS=constructor_info.ParametersInterfaceDeclaration())
822 for param in constructor_info.param_infos: 821 for param in constructor_info.param_infos:
823 inits.Emit(' if ($E != null) _e.$E = $E;\n', E=param.name) 822 inits.Emit(' if ($E != null) _e.$E = $E;\n', E=param.name)
824 823
825 return (constructor_info, info.factory_provider_name) 824 return (constructor_info, info.factory_provider_name)
826 825
827 826
828 def AddAttribute(self, getter, setter): 827 def AddAttribute(self, getter, setter):
829 dom_name = DartDomNameOfAttribute(getter) 828 dom_name = DartDomNameOfAttribute(getter)
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after
1266 def __init__(self, templates, database, emitters, auxiliary_dir, 1265 def __init__(self, templates, database, emitters, auxiliary_dir,
1267 dom_implementation_classes, output_dir): 1266 dom_implementation_classes, output_dir):
1268 """Prepared for generating wrapping implementation. 1267 """Prepared for generating wrapping implementation.
1269 1268
1270 - Creates emitter for Dart code. 1269 - Creates emitter for Dart code.
1271 """ 1270 """
1272 super(HtmlDartiumSystem, self).__init__( 1271 super(HtmlDartiumSystem, self).__init__(
1273 templates, database, emitters, output_dir) 1272 templates, database, emitters, output_dir)
1274 self._auxiliary_dir = auxiliary_dir 1273 self._auxiliary_dir = auxiliary_dir
1275 self._dom_implementation_classes = dom_implementation_classes 1274 self._dom_implementation_classes = dom_implementation_classes
1276 self._shared = HtmlSystemShared(database)
1277 self._dart_dartium_file_paths = []
1278 self._wrap_cases = []
1279 1275
1280 def InterfaceGenerator(self, 1276 def InterfaceGenerator(self,
1281 interface, 1277 interface,
1282 common_prefix, 1278 common_prefix,
1283 super_interface_name, 1279 super_interface_name,
1284 source_filter): 1280 source_filter):
1285 """.""" 1281 # Implementation classes are generated by NativeImplementationSystem.
1286 template_file = 'impl_%s.darttemplate' % interface.id 1282 # FIXME: merge HtmlDartiumSystem into NativeImplementationSystem.
1287 template = self._templates.TryLoad(template_file) 1283 return None
1288 # TODO(jacobr): change this name as it is confusing.
1289 if not template:
1290 template = self._templates.Load('frog_impl.darttemplate')
1291
1292 dart_code = self._ImplFileEmitter(interface.id)
1293 return HtmlDartiumInterfaceGenerator(self, interface, template,
1294 super_interface_name, dart_code, self._BaseDefines(interface),
1295 self._shared)
1296
1297 def _ImplFileEmitter(self, name):
1298 """Returns the file emitter of the Dartium implementation file."""
1299 path = os.path.join(self._output_dir, 'html', 'dartium', '%s.dart' % name)
1300 self._dart_dartium_file_paths.append(path)
1301 return self._emitters.FileEmitter(path);
1302 1284
1303 def ProcessCallback(self, interface, info): 1285 def ProcessCallback(self, interface, info):
1304 pass 1286 pass
1305 1287
1306 def GenerateLibraries(self): 1288 def GenerateLibraries(self):
1307 # Library generated for implementation. 1289 # Library generated for implementation.
1308 auxiliary_dir = os.path.relpath(self._auxiliary_dir, self._output_dir) 1290 auxiliary_dir = os.path.relpath(self._auxiliary_dir, self._output_dir)
1309 1291
1310 self._GenerateLibFile( 1292 self._GenerateLibFile(
1311 'html_dartium.darttemplate', 1293 'html_dartium.darttemplate',
1312 os.path.join(self._output_dir, 'html_dartium.dart'), 1294 os.path.join(self._output_dir, 'html_dartium.dart'),
1313 (self._interface_system._dart_interface_file_paths + 1295 (self._interface_system._dart_interface_file_paths +
1314 self._interface_system._dart_callback_file_paths + 1296 self._interface_system._dart_callback_file_paths +
1315 self._dart_dartium_file_paths +
1316 self._dom_implementation_classes), 1297 self._dom_implementation_classes),
1317 AUXILIARY_DIR=MassagePath(auxiliary_dir), 1298 AUXILIARY_DIR=MassagePath(auxiliary_dir))
1318 WRAPCASES='\n'.join(self._wrap_cases))
1319 1299
1320 def Finish(self): 1300 def Finish(self):
1321 pass 1301 pass
1322 1302
1323 # ------------------------------------------------------------------------------
1324
1325 # TODO(jacobr): there is far too much duplicated code between these bindings
1326 # and the Frog bindings. A larger scale refactoring needs to be performed to
1327 # reduce the duplicated logic.
1328 class HtmlDartiumInterfaceGenerator(object):
1329 """Generates a wrapper based implementation fo the HTML library that works
1330 on Dartium. This is not intended to be the final solution for implementing
1331 dart:html on Dartium. Eventually we should generate direct wrapperless
1332 dart:html bindings that work on dartium."""
1333
1334 def __init__(self, system, interface, template, super_interface, dart_code,
1335 base_members, shared):
1336 """Generates Dart wrapper code for the given interface.
1337
1338 Args:
1339 system: system that is executing this generator.
1340 template: template that output is generated into.
1341 interface: an IDLInterface instance. It is assumed that all types have
1342 been converted to Dart types (e.g. int, String), unless they are in
1343 the same package as the interface.
1344 super_interface: A string or None, the name of the common interface that
1345 this interface implements, if any.
1346 dart_code: an Emitter for the file containing the Dart implementation
1347 class.
1348 base_members: a set of names of members defined in a base class. This is
1349 used to avoid static member 'overriding' in the generated Dart code.
1350 shared: functionaly shared across all Html generators.
1351 """
1352 self._system = system
1353 self._interface = interface
1354 self._super_interface = super_interface
1355 self._dart_code = dart_code
1356 self._base_members = base_members
1357 self._current_secondary_parent = None
1358 self._shared = shared
1359 self._template = template
1360
1361 def DomObjectName(self):
1362 return '_ptr'
1363
1364 # TODO(jacobr): these 3 methods are duplicated.
1365 def _NarrowToImplementationType(self, type_name):
1366 # TODO(sra): Move into the 'system' and cache the result.
1367 if type_name == 'EventListener':
1368 # Callbacks are typedef functions so don't have a class.
1369 return type_name
1370 if self._system._database.HasInterface(type_name):
1371 interface = self._system._database.GetInterface(type_name)
1372 if RecognizeCallback(interface):
1373 # Callbacks are typedef functions so don't have a class.
1374 return type_name
1375 else:
1376 return self._ImplClassName(type_name)
1377 return type_name
1378
1379 def _NarrowInputType(self, type_name):
1380 return self._NarrowToImplementationType(type_name)
1381
1382 def _NarrowOutputType(self, type_name):
1383 return self._NarrowToImplementationType(type_name)
1384
1385 def StartInterface(self):
1386
1387 interface = self._interface
1388 interface_name = interface.id
1389 self._class_name = self._ImplClassName(interface_name)
1390
1391 base = None
1392 if interface.parents:
1393 supertype = interface.parents[0].type.id
1394 if not IsDartListType(supertype):
1395 base = self._ImplClassName(supertype)
1396 if IsDartCollectionType(supertype):
1397 # List methods are injected in AddIndexer.
1398 pass
1399 else:
1400 base = self._ImplClassName(supertype)
1401
1402 # TODO(jacobr): this is fragile. There isn't a guarantee that
1403 # dart:dom_deprecated will continue to exactly match the IDL
1404 # names.
1405 dom_name = interface.javascript_binding_name
1406 self._system._wrap_cases.append(
1407 " case '%s': return new %s._wrap(domObject);" %
1408 (dom_name, self._class_name))
1409
1410 extends = ' extends ' + base if base else ' extends _DOMTypeBase'
1411
1412 # TODO: Include all implemented interfaces, including other Lists.
1413 implements = [interface_name]
1414 element_type = MaybeTypedArrayElementType(self._interface)
1415 if element_type:
1416 implements.append('List<' + DartType(element_type) + '>')
1417 implements_str = ', '.join(implements)
1418
1419 (self._members_emitter,
1420 self._top_level_emitter) = self._dart_code.Emit(
1421 self._template + '$!TOP_LEVEL',
1422 #class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
1423 #$!MEMBERS
1424 #}
1425 NATIVESPEC='', # hack to make reusing the same templates work.
1426 CLASSNAME=self._class_name,
1427 EXTENDS=extends,
1428 IMPLEMENTS=' implements ' + implements_str)
1429
1430 self._members_emitter.Emit(
1431 ' $(CLASSNAME)._wrap(ptr) : super._wrap(ptr);\n',
1432 CLASSNAME=self._class_name)
1433
1434 # Emit a factory provider class for the constructor.
1435 constructor_info = AnalyzeConstructor(interface)
1436 if constructor_info:
1437 self._EmitFactoryProvider(interface_name, constructor_info)
1438
1439 emit_events, events = self._shared.GetEventAttributes(self._interface)
1440 if emit_events:
1441 self._members_emitter.Emit(
1442 '\n'
1443 ' Events get on() => $THIS.on;\n',
1444 THIS=self.DomObjectName())
1445
1446 def _EmitFactoryProvider(self, interface_name, constructor_info):
1447 template_file = 'factoryprovider_%s.darttemplate' % interface_name
1448 template = self._system._templates.TryLoad(template_file)
1449 if not template:
1450 template = self._system._templates.Load('factoryprovider.darttemplate')
1451
1452 factory_provider = '_' + interface_name + 'FactoryProvider'
1453 emitter = self._system._ImplFileEmitter(factory_provider)
1454 emitter.Emit(
1455 template,
1456 FACTORYPROVIDER=factory_provider,
1457 INTERFACE=interface_name,
1458 DOM_INTERFACE=self._interface.javascript_binding_name,
1459 PARAMETERS=constructor_info.ParametersImplementationDeclaration(),
1460 NAMED_CONSTRUCTOR=constructor_info.name or interface_name,
1461 ARGUMENTS=self._UnwrappedParameters(constructor_info,
1462 len(constructor_info.param_infos)))
1463
1464 def _UnwrappedParameters(self, operation_info, length):
1465 """Returns string for an argument list that unwraps first |length|
1466 parameters."""
1467 def UnwrapParamInfo(param_info):
1468 # TODO(sra): Type dependent unwrapping.
1469 return '_unwrap(%s)' % param_info.name
1470
1471 return ', '.join(map(UnwrapParamInfo, operation_info.param_infos[:length]))
1472
1473 def _BaseClassName(self, interface):
1474 if not interface.parents:
1475 return '_DOMTypeBase'
1476
1477 supertype = DartType(interface.parents[0].type.id)
1478
1479 if IsDartListType(supertype) or IsDartCollectionType(supertype):
1480 return 'DOMWrapperBase'
1481
1482 if supertype == 'EventTarget':
1483 # Most implementors of EventTarget specify the EventListener operations
1484 # again. If the operations are not specified, try to inherit from the
1485 # EventTarget implementation.
1486 #
1487 # Applies to MessagePort.
1488 if not [op for op in interface.operations if op.id == 'addEventListener']:
1489 return self._ImplClassName(supertype)
1490 return 'DOMWrapperBase'
1491
1492 return self._ImplClassName(supertype)
1493
1494 def _ImplClassName(self, type_name):
1495 return self._shared._ImplClassName(type_name)
1496
1497 def FinishInterface(self):
1498 """."""
1499 pass
1500
1501 def AddConstant(self, constant):
1502 # Constants are already defined on the interface.
1503 pass
1504
1505 def _MethodName(self, prefix, name):
1506 method_name = prefix + name
1507 if name in self._base_members: # Avoid illegal Dart 'static override'.
1508 method_name = method_name + '_' + self._interface.id
1509 return method_name
1510
1511 def AddAttribute(self, getter, setter):
1512 dom_name = DartDomNameOfAttribute(getter or setter)
1513 html_getter_name = None
1514 if not self._shared.IsCustomInHtmlLibrary(
1515 self._interface, dom_name, 'get:'):
1516 html_getter_name = self._shared.RenameInHtmlLibrary(
1517 self._interface.id, dom_name, 'get:',
1518 implementation_class=True)
1519 html_setter_name = None
1520 if not self._shared.IsCustomInHtmlLibrary(
1521 self._interface, dom_name, 'set:'):
1522 html_setter_name = self._shared.RenameInHtmlLibrary(
1523 self._interface.id, dom_name, 'set:',
1524 implementation_class=True)
1525
1526 if getter and html_getter_name:
1527 self._AddGetter(getter, html_getter_name)
1528 if setter and html_setter_name:
1529 self._AddSetter(setter, html_setter_name)
1530
1531 def _AddGetter(self, attr, html_name):
1532 self._members_emitter.Emit(
1533 '\n'
1534 ' $TYPE get $(HTML_NAME)() => _wrap($(THIS).$HTML_NAME);\n',
1535 HTML_NAME=html_name,
1536 TYPE=DartType(attr.type.id),
1537 THIS=self.DomObjectName())
1538
1539 def _AddSetter(self, attr, html_name):
1540 self._members_emitter.Emit(
1541 '\n'
1542 ' void set $(HTML_NAME)($TYPE value) { '
1543 '$(THIS).$HTML_NAME = _unwrap(value); }\n',
1544 HTML_NAME=html_name,
1545 TYPE=DartType(attr.type.id),
1546 THIS=self.DomObjectName())
1547
1548 def AddSecondaryAttribute(self, interface, getter, setter):
1549 self._SecondaryContext(interface)
1550 self.AddAttribute(getter, setter)
1551
1552 def AddSecondaryOperation(self, interface, info):
1553 self._SecondaryContext(interface)
1554 self.AddOperation(info)
1555
1556 def _SecondaryContext(self, interface):
1557 if interface is not self._current_secondary_parent:
1558 self._current_secondary_parent = interface
1559 self._members_emitter.Emit('\n // From $WHERE\n', WHERE=interface.id)
1560
1561 # TODO(jacobr): change this to more directly match the frog version.
1562 def AddIndexer(self, element_type):
1563 """Adds all the methods required to complete implementation of List."""
1564 # We would like to simply inherit the implementation of everything except
1565 # get length(), [], and maybe []=. It is possible to extend from a base
1566 # array implementation class only when there is no other implementation
1567 # inheritance. There might be no implementation inheritance other than
1568 # DOMBaseWrapper for many classes, but there might be some where the
1569 # array-ness is introduced by a non-root interface:
1570 #
1571 # interface Y extends X, List<T> ...
1572 #
1573 # In the non-root case we have to choose between:
1574 #
1575 # class YImpl extends XImpl { add List<T> methods; }
1576 #
1577 # and
1578 #
1579 # class YImpl extends ListBase<T> { copies of transitive XImpl methods; }
1580 #
1581 if self._HasNativeIndexGetter(self._interface):
1582 self._EmitNativeIndexGetter(self._interface, element_type)
1583 else:
1584 self._members_emitter.Emit(
1585 '\n'
1586 ' $TYPE operator[](int index) => _wrap($(THIS)[index]);\n'
1587 '\n',
1588 THIS=self.DomObjectName(),
1589 TYPE=DartType(element_type))
1590
1591 if self._HasNativeIndexSetter(self._interface):
1592 self._EmitNativeIndexSetter(self._interface, element_type)
1593 else:
1594 # The HTML library implementation of NodeList has a custom indexed setter
1595 # implementation that uses the parent node the NodeList is associated
1596 # with if one is available.
1597 if self._interface.id != 'NodeList':
1598 self._members_emitter.Emit(
1599 '\n'
1600 ' void operator[]=(int index, $TYPE value) {\n'
1601 ' throw new UnsupportedOperationException("Cannot assign element of immutable List.");\n'
1602 ' }\n',
1603 TYPE=DartType(element_type))
1604
1605 # The list interface for this class is manually generated.
1606 if self._interface.id == 'NodeList':
1607 return
1608
1609 # TODO(sra): Use separate mixins for mutable implementations of List<T>.
1610 # TODO(sra): Use separate mixins for typed array implementations of List<T>.
1611 template_file = 'immutable_list_mixin.darttemplate'
1612 template = self._system._templates.Load(template_file)
1613 self._members_emitter.Emit(template, E=DartType(element_type))
1614
1615 def AmendIndexer(self, element_type):
1616 pass
1617
1618 def _HasNativeIndexGetter(self, interface):
1619 return ('IndexedGetter' in interface.ext_attrs or
1620 'NumericIndexedGetter' in interface.ext_attrs)
1621
1622 def _EmitNativeIndexGetter(self, interface, element_type):
1623 method_name = '_index'
1624 self._members_emitter.Emit(
1625 '\n $TYPE operator[](int index) => _wrap($(THIS)[index]);\n',
1626 TYPE=DartType(element_type),
1627 THIS=self.DomObjectName(),
1628 METHOD=method_name)
1629
1630 def _HasNativeIndexSetter(self, interface):
1631 return 'CustomIndexedSetter' in interface.ext_attrs
1632
1633 def _EmitNativeIndexSetter(self, interface, element_type):
1634 method_name = '_set_index'
1635 self._members_emitter.Emit(
1636 '\n'
1637 ' void operator[]=(int index, $TYPE value) {\n'
1638 ' return $(THIS)[index] = _unwrap(value);\n'
1639 ' }\n',
1640 THIS=self.DomObjectName(),
1641 TYPE=DartType(element_type),
1642 METHOD=method_name)
1643
1644 def AddOperation(self, info):
1645 """
1646 Arguments:
1647 info: An OperationInfo object.
1648 """
1649 if self._shared.IsCustomInHtmlLibrary(self._interface, info.name):
1650 return
1651
1652 html_name = self._shared.RenameInHtmlLibrary(
1653 self._interface.id, info.name, implementation_class=True)
1654
1655 if not html_name:
1656 return
1657
1658 arguments = self._UnwrappedParameters(info, len(info.param_infos))
1659 function_call = '%s.%s(%s)' % (self.DomObjectName(), html_name, arguments)
1660 if info.type_name != 'void':
1661 # We could place the logic for handling Document directly in _wrap
1662 # but we chose to place it here so that bugs in the wrapper and
1663 # wrapperless implementations are more consistent.
1664 function_call = '_wrap(%s)' % function_call
1665
1666 self._members_emitter.Emit(
1667 '\n'
1668 ' $TYPE $HTML_NAME($PARAMS) => $FUNCTION_CALL;\n',
1669 TYPE=info.type_name,
1670 HTML_NAME=html_name,
1671 PARAMS=info.ParametersImplementationDeclaration(),
1672 FUNCTION_CALL=function_call)
1673
1674 def AddStaticOperation(self, info):
1675 pass
1676 1303
1677 def _ComputeInheritanceClosure(database): 1304 def _ComputeInheritanceClosure(database):
1678 def Collect(interface, seen, collected): 1305 def Collect(interface, seen, collected):
1679 name = interface.id 1306 name = interface.id
1680 if '<' in name: 1307 if '<' in name:
1681 # TODO(sra): Handle parameterized types. 1308 # TODO(sra): Handle parameterized types.
1682 return 1309 return
1683 if not name in seen: 1310 if not name in seen:
1684 seen.add(name) 1311 seen.add(name)
1685 collected.append(name) 1312 collected.append(name)
1686 for parent in interface.parents: 1313 for parent in interface.parents:
1687 # TODO(sra): Handle parameterized types. 1314 # TODO(sra): Handle parameterized types.
1688 if not '<' in parent.type.id: 1315 if not '<' in parent.type.id:
1689 if database.HasInterface(parent.type.id): 1316 if database.HasInterface(parent.type.id):
1690 Collect(database.GetInterface(parent.type.id), 1317 Collect(database.GetInterface(parent.type.id),
1691 seen, collected) 1318 seen, collected)
1692 1319
1693 inheritance_closure = {} 1320 inheritance_closure = {}
1694 for interface in database.GetInterfaces(): 1321 for interface in database.GetInterfaces():
1695 seen = set() 1322 seen = set()
1696 collected = [] 1323 collected = []
1697 Collect(interface, seen, collected) 1324 Collect(interface, seen, collected)
1698 inheritance_closure[interface.id] = collected 1325 inheritance_closure[interface.id] = collected
1699 return inheritance_closure 1326 return inheritance_closure
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698