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

Unified Diff: lib/html/scripts/systemhtml.py

Issue 11020008: Cleanup html events generation. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 3 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 side-by-side diff with in-line comments
Download patch
Index: lib/html/scripts/systemhtml.py
diff --git a/lib/html/scripts/systemhtml.py b/lib/html/scripts/systemhtml.py
index ba81c55e68091b63dae748dfdf062757536e17bf..17de939738ba612262633b6e3697355a6047b692 100644
--- a/lib/html/scripts/systemhtml.py
+++ b/lib/html/scripts/systemhtml.py
@@ -49,179 +49,6 @@ _merged_html_interfaces = {
'HTMLElement': 'Element'
}
-# Events without onEventName attributes in the IDL we want to support.
-# We can automatically extract most event event names by checking for
-# onEventName methods in the IDL but some events aren't listed so we need
-# to manually add them here so that they are easy for users to find.
-_html_manual_events = {
- 'Element': ['touchleave', 'touchenter', 'webkitTransitionEnd'],
- 'Window': ['DOMContentLoaded']
-}
-
-# These event names must be camel case when attaching event listeners
-# using addEventListener even though the onEventName properties in the DOM for
-# them are not camel case.
-_on_attribute_to_event_name_mapping = {
- 'webkitanimationend': 'webkitAnimationEnd',
- 'webkitanimationiteration': 'webkitAnimationIteration',
- 'webkitanimationstart': 'webkitAnimationStart',
- 'webkitspeechchange': 'webkitSpeechChange',
- 'webkittransitionend': 'webkitTransitionEnd',
-}
-
-# Mapping from raw event names to the pretty camelCase event names exposed as
-# properties in dart:html. If the DOM exposes a new event name, you will need
-# to add the lower case to camel case conversion for that event name here.
-_html_event_names = {
- 'DOMContentLoaded': 'contentLoaded',
- 'abort': 'abort',
- 'addstream': 'addStream',
- 'addtrack': 'addTrack',
- 'audioend': 'audioEnd',
- 'audioprocess': 'audioProcess',
- 'audiostart': 'audioStart',
- 'beforecopy': 'beforeCopy',
- 'beforecut': 'beforeCut',
- 'beforepaste': 'beforePaste',
- 'beforeunload': 'beforeUnload',
- 'blocked': 'blocked',
- 'blur': 'blur',
- 'cached': 'cached',
- 'canplay': 'canPlay',
- 'canplaythrough': 'canPlayThrough',
- 'change': 'change',
- 'chargingchange': 'chargingChange',
- 'chargingtimechange': 'chargingTimeChange',
- 'checking': 'checking',
- 'click': 'click',
- 'close': 'close',
- 'complete': 'complete',
- 'connect': 'connect',
- 'connecting': 'connecting',
- 'contextmenu': 'contextMenu',
- 'copy': 'copy',
- 'cuechange': 'cueChange',
- 'cut': 'cut',
- 'dblclick': 'doubleClick',
- 'devicemotion': 'deviceMotion',
- 'deviceorientation': 'deviceOrientation',
- 'dischargingtimechange': 'dischargingTimeChange',
- 'display': 'display',
- 'downloading': 'downloading',
- 'drag': 'drag',
- 'dragend': 'dragEnd',
- 'dragenter': 'dragEnter',
- 'dragleave': 'dragLeave',
- 'dragover': 'dragOver',
- 'dragstart': 'dragStart',
- 'drop': 'drop',
- 'durationchange': 'durationChange',
- 'emptied': 'emptied',
- 'end': 'end',
- 'ended': 'ended',
- 'enter': 'enter',
- 'error': 'error',
- 'exit': 'exit',
- 'focus': 'focus',
- 'hashchange': 'hashChange',
- 'icecandidate': 'iceCandidate',
- 'icechange': 'iceChange',
- 'input': 'input',
- 'invalid': 'invalid',
- 'keydown': 'keyDown',
- 'keypress': 'keyPress',
- 'keyup': 'keyUp',
- 'levelchange': 'levelChange',
- 'load': 'load',
- 'loadeddata': 'loadedData',
- 'loadedmetadata': 'loadedMetadata',
- 'loadend': 'loadEnd',
- 'loadstart': 'loadStart',
- 'message': 'message',
- 'mousedown': 'mouseDown',
- 'mousemove': 'mouseMove',
- 'mouseout': 'mouseOut',
- 'mouseover': 'mouseOver',
- 'mouseup': 'mouseUp',
- 'mousewheel': 'mouseWheel',
- 'mute': 'mute',
- 'negotiationneeded': 'negotiationNeeded',
- 'nomatch': 'noMatch',
- 'noupdate': 'noUpdate',
- 'obsolete': 'obsolete',
- 'offline': 'offline',
- 'online': 'online',
- 'open': 'open',
- 'pagehide': 'pageHide',
- 'pageshow': 'pageShow',
- 'paste': 'paste',
- 'pause': 'pause',
- 'play': 'play',
- 'playing': 'playing',
- 'popstate': 'popState',
- 'progress': 'progress',
- 'ratechange': 'rateChange',
- 'readystatechange': 'readyStateChange',
- 'removestream': 'removeStream',
- 'removetrack': 'removeTrack',
- 'reset': 'reset',
- 'resize': 'resize',
- 'result': 'result',
- 'resultdeleted': 'resultDeleted',
- 'scroll': 'scroll',
- 'search': 'search',
- 'seeked': 'seeked',
- 'seeking': 'seeking',
- 'select': 'select',
- 'selectionchange': 'selectionChange',
- 'selectstart': 'selectStart',
- 'show': 'show',
- 'soundend': 'soundEnd',
- 'soundstart': 'soundStart',
- 'speechend': 'speechEnd',
- 'speechstart': 'speechStart',
- 'stalled': 'stalled',
- 'start': 'start',
- 'statechange': 'stateChange',
- 'storage': 'storage',
- 'submit': 'submit',
- 'success': 'success',
- 'suspend': 'suspend',
- 'timeupdate': 'timeUpdate',
- 'touchcancel': 'touchCancel',
- 'touchend': 'touchEnd',
- 'touchenter': 'touchEnter',
- 'touchleave': 'touchLeave',
- 'touchmove': 'touchMove',
- 'touchstart': 'touchStart',
- 'unload': 'unload',
- 'upgradeneeded': 'upgradeNeeded',
- 'unmute': 'unmute',
- 'updateready': 'updateReady',
- 'versionchange': 'versionChange',
- 'volumechange': 'volumeChange',
- 'waiting': 'waiting',
- 'webkitAnimationEnd': 'animationEnd',
- 'webkitAnimationIteration': 'animationIteration',
- 'webkitAnimationStart': 'animationStart',
- 'webkitfullscreenchange': 'fullscreenChange',
- 'webkitfullscreenerror': 'fullscreenError',
- 'webkitkeyadded': 'keyAdded',
- 'webkitkeyerror': 'keyError',
- 'webkitkeymessage': 'keyMessage',
- 'webkitneedkey': 'needKey',
- 'webkitpointerlockchange': 'pointerLockChange',
- 'webkitpointerlockerror': 'pointerLockError',
- 'webkitSpeechChange': 'speechChange',
- 'webkitsourceclose': 'sourceClose',
- 'webkitsourceended': 'sourceEnded',
- 'webkitsourceopen': 'sourceOpen',
- 'webkitTransitionEnd': 'transitionEnd',
- 'write': 'write',
- 'writeend': 'writeEnd',
- 'writestart': 'writeStart'
-}
-
# Information for generating element constructors.
#
# TODO(sra): maybe remove all the argument complexity and use cascades.
@@ -353,94 +180,21 @@ def EmitHtmlElementFactoryConstructors(emitter, infos, typename, class_name):
for param in constructor_info.param_infos:
inits.Emit(' if ($E != null) _e.$E = $E;\n', E=param.name)
-
-# These classes require an explicit declaration for the "on" method even though
-# they don't declare any unique events, because the concrete class hierarchy
-# doesn't match the interface hierarchy.
-_html_explicit_event_classes = set(['DocumentFragment'])
-
-def _OnAttributeToEventName(on_method):
- event_name = on_method.id[2:]
- if event_name in _on_attribute_to_event_name_mapping:
- return _on_attribute_to_event_name_mapping[event_name]
- else:
- return event_name
-
-def DomToHtmlEvents(interface_id, events):
- event_names = set(map(_OnAttributeToEventName, events))
- if interface_id in _html_manual_events:
- for manual_event_name in _html_manual_events[interface_id]:
- event_names.add(manual_event_name)
-
- return sorted(event_names, key=lambda name: _html_event_names[name])
-
-def DomToHtmlEvent(event_name):
- assert event_name in _html_event_names, \
- 'No known html event name for event: ' + event_name
- return _html_event_names[event_name]
-
-# ------------------------------------------------------------------------------
-class HtmlSystemShared(object):
-
- def __init__(self, database):
- self._event_classes = set()
- self._database = database
-
- # TODO(jacobr): this isn't quite right....
- def GetParentsEventsClasses(self, interface):
- # Ugly hack as we don't specify that Document and DocumentFragment inherit
- # from Element in our IDL.
- if interface.id == 'Document' or interface.id == 'DocumentFragment':
- return ['ElementEvents']
-
- interfaces_with_events = set()
- for parent in self._database.Hierarchy(interface):
- if parent != interface and parent.id in self._event_classes:
- interfaces_with_events.add(parent)
-
- if len(interfaces_with_events) == 0:
- return ['Events']
- else:
- names = []
- for interface in interfaces_with_events:
- names.append(interface.id + 'Events')
- return names
-
- def GetParentEventsClass(self, interface):
- parent_event_classes = self.GetParentsEventsClasses(interface)
- if len(parent_event_classes) != 1:
- raise Exception('Only one parent event class allowed ' + interface.id)
- return parent_event_classes[0]
-
- # This returns two values: the first is whether or not an "on" property should
- # be generated for the interface, and the second is the event attributes to
- # generate if it should.
- def GetEventAttributes(self, interface):
- events = set([attr for attr in interface.attributes
- if attr.type.id == 'EventListener'])
-
- if events or interface.id in _html_explicit_event_classes:
- return True, events
- else:
- return False, None
-
- def IsPrivate(self, name):
- return name.startswith('_')
-
# ------------------------------------------------------------------------------
class HtmlDartInterfaceGenerator(BaseGenerator):
"""Generates dart interface and implementation for the DOM IDL interface."""
- def __init__(self, shared, options, library_emitter, interface, backend):
+ def __init__(self, options, library_emitter, event_generator, interface,
+ backend):
super(HtmlDartInterfaceGenerator, self).__init__(None, None, interface)
self._renamer = options.renamer
self._database = options.database
self._template_loader = options.templates
self._type_registry = options.type_registry
self._library_emitter = library_emitter
+ self._event_generator = event_generator
self._backend = backend
- self._shared = shared
self._html_interface_name = options.renamer.RenameInterface(self._interface)
def GenerateCallback(self, info):
@@ -570,7 +324,12 @@ class HtmlDartInterfaceGenerator(BaseGenerator):
TYPE=self._DartType(element_type),
FACTORY=factory_provider)
- self._GenerateEvents()
+ events_interface = self._event_generator.ProcessInterface(
+ self._interface, self._html_interface_name,
+ self._backend.CustomJSMembers(),
+ self._interface_emitter, self._implementation_emitter)
+ if events_interface:
+ self._EmitEventGetter(events_interface, '_%sImpl' % events_interface)
old_backend = self._backend
if not self._backend.ImplementsMergedMembers():
@@ -591,7 +350,7 @@ class HtmlDartInterfaceGenerator(BaseGenerator):
dom_name = DartDomNameOfAttribute(attribute)
html_name = self._renamer.RenameMember(
self._interface.id, dom_name, 'get:')
- if not html_name or self._shared.IsPrivate(html_name):
+ if not html_name or self._IsPrivate(html_name):
return
@@ -634,7 +393,7 @@ class HtmlDartInterfaceGenerator(BaseGenerator):
self._backend.AddOperation(info, '_item')
return
- if not self._shared.IsPrivate(html_name) and not skip_declaration:
+ if not self._IsPrivate(html_name) and not skip_declaration:
self._members_emitter.Emit('\n /** @domName $DOMINTERFACE.$DOMNAME */',
DOMINTERFACE=info.overloads[0].doc_js_interface_name,
DOMNAME=info.name)
@@ -668,58 +427,6 @@ class HtmlDartInterfaceGenerator(BaseGenerator):
VALUE=constant.value)
self._backend.AddConstant(constant)
- def _GenerateEvents(self):
- emit_events, event_attrs = self._shared.GetEventAttributes(self._interface)
- if not emit_events:
- return
-
- self._shared._event_classes.add(self._interface.id)
- events_interface = self._html_interface_name + 'Events'
- events_class = '_%sImpl' % events_interface
- parent_events_interface = self._shared.GetParentEventsClass(self._interface)
- parent_events_class = '_%sImpl' % parent_events_interface
-
- if not event_attrs:
- self._EmitEventGetter(parent_events_interface, parent_events_class)
- return
-
- self._EmitEventGetter(events_interface, events_class)
-
- events_members = self._interface_emitter.Emit(
- '\nabstract class $INTERFACE implements $PARENTS {\n$!MEMBERS}\n',
- INTERFACE=events_interface,
- PARENTS=', '.join(
- self._shared.GetParentsEventsClasses(self._interface)))
-
- template_file = 'impl_%s.darttemplate' % events_interface
- template = (self._template_loader.TryLoad(template_file) or
- '\n'
- 'class $CLASSNAME extends $SUPER implements $INTERFACE {\n'
- ' $CLASSNAME(_ptr) : super(_ptr);\n'
- '$!MEMBERS}\n')
-
- # TODO(jacobr): specify the type of _ptr as EventTarget
- implementation_events_members = self._implementation_emitter.Emit(
- template,
- CLASSNAME=events_class,
- INTERFACE=events_interface,
- SUPER=parent_events_class)
-
- event_attrs = DomToHtmlEvents(self._html_interface_name, event_attrs)
- for event_name in event_attrs:
- if event_name in _html_event_names:
- dart_event_name = _html_event_names[event_name]
- events_members.Emit('\n EventListenerList get $NAME;\n',
- NAME=dart_event_name)
- if not self._backend.HasCustomEventImplementation(dart_event_name):
- implementation_events_members.Emit(
- "\n"
- " EventListenerList get $NAME => this['$DOM_NAME'];\n",
- NAME=dart_event_name,
- DOM_NAME=event_name)
- else:
- raise Exception('No known html even name for event: ' + event_name)
-
def _EmitEventGetter(self, events_interface, events_class):
self._members_emitter.Emit(
'\n /**'
@@ -733,6 +440,9 @@ class HtmlDartInterfaceGenerator(BaseGenerator):
'\n $TYPE get on =>\n new $TYPE(this);\n',
TYPE=events_class)
+ def _IsPrivate(self, name):
+ return name.startswith('_')
+
class HtmlGeneratorDummyBackend(object):
def AddAttribute(self, attribute, html_name, read_only):
@@ -1217,9 +927,8 @@ class Dart2JSBackend(BaseGenerator):
member_name = '%s.%s' % (self._html_interface_name, member_name)
return member_name in _js_custom_members
- def HasCustomEventImplementation(self, member_name):
- member_name = '%sEvents.%s' % (self._html_interface_name, member_name)
- return member_name in _js_custom_members
+ def CustomJSMembers(self):
+ return _js_custom_members
def _HasJavaScriptIndexingBehaviour(self):
"""Returns True if the native object has an indexer and length property."""

Powered by Google App Engine
This is Rietveld 408576698