@@ -22,13 +22,11 @@ module EventEmitter {
2222 /**
2323 * Gets a node that refers to an EventEmitter object.
2424 */
25- DataFlow:: SourceNode trackEventEmitter ( EventEmitter:: Range emitter ) {
25+ DataFlow:: SourceNode trackEventEmitter ( EventEmitter emitter ) {
2626 result = trackEventEmitter ( DataFlow:: TypeTracker:: end ( ) , emitter )
2727 }
2828
29- private DataFlow:: SourceNode trackEventEmitter (
30- DataFlow:: TypeTracker t , EventEmitter:: Range emitter
31- ) {
29+ private DataFlow:: SourceNode trackEventEmitter ( DataFlow:: TypeTracker t , EventEmitter emitter ) {
3230 t .start ( ) and result = emitter
3331 or
3432 exists ( DataFlow:: TypeTracker t2 , DataFlow:: SourceNode pred |
@@ -38,7 +36,7 @@ module EventEmitter {
3836 or
3937 // invocation of a chainable method
4038 exists ( DataFlow:: MethodCallNode mcn |
41- mcn = pred .getAMethodCall ( EventEmitter :: chainableMethod ( ) ) and
39+ mcn = pred .getAMethodCall ( chainableMethod ( ) ) and
4240 // exclude getter versions
4341 exists ( mcn .getAnArgument ( ) ) and
4442 result = mcn and
@@ -50,36 +48,24 @@ module EventEmitter {
5048 /**
5149 * An object that implements the EventEmitter API.
5250 * Extending this class does nothing, its mostly to indicate intent.
53- * The magic only happens when extending EventRegistration::Range and EventDispatch::Range.
51+ *
52+ * The classes EventRegistration::Range and EventDispatch::Range must be extended to get a working EventEmitter model.
53+ * An EventRegistration models a method call that registers some event handler on an EventEmitter.
54+ * And EventDispatch models that some event is dispatched on an EventEmitter.
55+ *
56+ * Both the EventRegistration and EventDispatch have a field `emitter`,
57+ * which is the EventEmitter that events are registered on / dispatched to respectively.
58+ *
59+ * Here is a simple JavaScript example with the NodeJS EventEmitter:
60+ * var e = new EventEmitter(); // <- EventEmitter
61+ * e.on("name", (data) => {...}); // <- EventRegistration
62+ * e.emit("name", "foo"); // <- EventDispatch
5463 */
5564 abstract class Range extends DataFlow:: Node { }
56-
57- /**
58- * An NodeJS EventEmitter instance.
59- * Events dispatched on this EventEmitter will be handled by event handlers registered on this EventEmitter.
60- * (That is opposed to e.g. SocketIO, which implements the same interface, but where events cross object boundaries).
61- */
62- abstract class NodeJSEventEmitter extends Range {
63- /**
64- * Get a Node that refers to a NodeJS EventEmitter instance.
65- */
66- DataFlow:: SourceNode ref ( ) { result = trackEventEmitter ( this ) }
67- }
68-
69- private class ImportedNodeJSEventEmitter extends NodeJSEventEmitter {
70- ImportedNodeJSEventEmitter ( ) {
71- exists ( DataFlow:: SourceNode clazz |
72- clazz = DataFlow:: moduleImport ( "events" ) or
73- clazz = DataFlow:: moduleMember ( "events" , "EventEmitter" )
74- |
75- this = clazz .getAnInstantiation ( )
76- )
77- }
78- }
7965}
8066
8167/**
82- * An EventEmitter instance that implements the NodeJS EventEmitter API.
68+ * An EventEmitter instance that implements the EventEmitter API.
8369 * Extend EventEmitter::Range to mark something as being an EventEmitter.
8470 */
8571class EventEmitter extends DataFlow:: Node {
@@ -112,7 +98,7 @@ class EventRegistration extends DataFlow::Node {
11298 DataFlow:: Node getAReturnedValue ( ) { result = range .getAReturnedValue ( ) }
11399
114100 /**
115- * Get a dispatch that this event handler can return a value to.
101+ * Get a dispatch that this event handler can return a value to.
116102 * The default implementation is that there exists no such dispatch.
117103 */
118104 EventDispatch getAReturnDispatch ( ) { result = range .getAReturnDispatch ( ) }
@@ -121,30 +107,39 @@ class EventRegistration extends DataFlow::Node {
121107module EventRegistration {
122108 /**
123109 * A registration of an event handler on an EventEmitter.
124- * The default implementation assumes that `this` is a DataFlow::InvokeNode where the
125- * first argument is a string describing which channel is registered, and the second
126- * argument is the event handler callback.
127110 */
128111 abstract class Range extends DataFlow:: Node {
129112 EventEmitter:: Range emitter ;
130113
131114 final EventEmitter getEmitter ( ) { result = emitter }
132115
133- string getChannel ( ) { this . ( DataFlow :: InvokeNode ) . getArgument ( 0 ) . mayHaveStringValue ( result ) }
116+ abstract string getChannel ( ) ;
134117
135- DataFlow:: Node getReceivedItem ( int i ) {
136- result = this .( DataFlow:: InvokeNode ) .getABoundCallbackParameter ( 1 , i )
137- }
118+ abstract DataFlow:: Node getReceivedItem ( int i ) ;
138119
139- DataFlow:: Node getAReturnedValue ( ) { none ( ) }
120+ abstract DataFlow:: Node getAReturnedValue ( ) ;
140121
141- EventDispatch:: Range getAReturnDispatch ( ) { none ( ) }
122+ abstract EventDispatch:: Range getAReturnDispatch ( ) ;
142123 }
143124
144- private class NodeJSEventRegistration extends Range , DataFlow:: MethodCallNode {
145- override EventEmitter:: NodeJSEventEmitter emitter ;
125+ /**
126+ * A default implementation of an EventRegistration.
127+ * The default implementation assumes that `this` is a DataFlow::InvokeNode where the
128+ * first argument is a string describing which channel is registered, and the second
129+ * argument is the event handler callback.
130+ */
131+ abstract class DefaultEventRegistration extends Range {
132+ override string getChannel ( ) {
133+ this .( DataFlow:: InvokeNode ) .getArgument ( 0 ) .mayHaveStringValue ( result )
134+ }
135+
136+ override DataFlow:: Node getReceivedItem ( int i ) {
137+ result = this .( DataFlow:: InvokeNode ) .getABoundCallbackParameter ( 1 , i )
138+ }
146139
147- NodeJSEventRegistration ( ) { this = emitter .ref ( ) .getAMethodCall ( EventEmitter:: on ( ) ) }
140+ override DataFlow:: Node getAReturnedValue ( ) { none ( ) }
141+
142+ override EventDispatch:: Range getAReturnDispatch ( ) { none ( ) }
148143 }
149144}
150145
@@ -176,26 +171,35 @@ class EventDispatch extends DataFlow::Node {
176171module EventDispatch {
177172 /**
178173 * A dispatch of an event on an EventEmitter.
179- * The default implementation assumes that the dispatch is a DataFlow::InvokeNode,
180- * where the first argument is a string describing the channel, and the `i`+1 argument
181- * is the `i`th item sent to the event handler.
182174 */
183175 abstract class Range extends DataFlow:: Node {
184176 EventEmitter:: Range emitter ;
185177
186178 final EventEmitter getEmitter ( ) { result = emitter }
187179
188- string getChannel ( ) { this . ( DataFlow :: InvokeNode ) . getArgument ( 0 ) . mayHaveStringValue ( result ) }
180+ abstract string getChannel ( ) ;
189181
190- DataFlow:: Node getSentItem ( int i ) { result = this . ( DataFlow :: InvokeNode ) . getArgument ( i + 1 ) }
182+ abstract DataFlow:: Node getSentItem ( int i ) ;
191183
192- EventRegistration:: Range getAReceiver ( ) { this . getEmitter ( ) = result . getEmitter ( ) }
184+ abstract EventRegistration:: Range getAReceiver ( ) ;
193185 }
194186
195- private class NodeJSEventDispatch extends Range , DataFlow:: MethodCallNode {
196- override EventEmitter:: NodeJSEventEmitter emitter ;
187+ /**
188+ * A default implementation of an EventDispatch.
189+ * The default implementation assumes that the dispatch is a DataFlow::InvokeNode,
190+ * where the first argument is a string describing the channel, and the `i`+1 argument
191+ * is the `i`th item sent to the event handler.
192+ */
193+ abstract class DefaultEventDispatch extends Range {
194+ override string getChannel ( ) {
195+ this .( DataFlow:: InvokeNode ) .getArgument ( 0 ) .mayHaveStringValue ( result )
196+ }
197+
198+ override DataFlow:: Node getSentItem ( int i ) {
199+ result = this .( DataFlow:: InvokeNode ) .getArgument ( i + 1 )
200+ }
197201
198- NodeJSEventDispatch ( ) { this = emitter . ref ( ) . getAMethodCall ( "emit" ) }
202+ override EventRegistration :: Range getAReceiver ( ) { this . getEmitter ( ) = result . getEmitter ( ) }
199203 }
200204}
201205
0 commit comments