add support for this references in classes that extend EventEmitter

This commit is contained in:
Erik Krogh Kristensen
2020-01-28 09:37:54 +01:00
parent 816a8d1f9e
commit a2e54b1477

View File

@@ -892,6 +892,11 @@ module NodeJSLib {
* Get a Node that refers to a NodeJS EventEmitter instance. * Get a Node that refers to a NodeJS EventEmitter instance.
*/ */
DataFlow::SourceNode ref() { result = EventEmitter::trackEventEmitter(this) } DataFlow::SourceNode ref() { result = EventEmitter::trackEventEmitter(this) }
/**
* Gets the node that will used for comparison when determining whether one EventEmitter can send an event to another EventEmitter.
*/
DataFlow::SourceNode getBaseEmitter() {result = this}
} }
/** /**
@@ -906,9 +911,7 @@ module NodeJSLib {
* An instance of an EventEmitter that is imported through the 'events' module. * An instance of an EventEmitter that is imported through the 'events' module.
*/ */
private class ImportedNodeJSEventEmitter extends NodeJSEventEmitter { private class ImportedNodeJSEventEmitter extends NodeJSEventEmitter {
ImportedNodeJSEventEmitter() { ImportedNodeJSEventEmitter() { this = getAnEventEmitterImport().getAnInstantiation() }
this = getAnEventEmitterImport().getAnInstantiation()
}
} }
/** /**
@@ -922,20 +925,27 @@ module NodeJSLib {
} }
/** /**
* An instantiation of a class that extends EventEmitter. * An instantiation of a class that extends EventEmitter.
* *
* By extending `NodeJSEventEmitter' we get data-flow on the events passing through this EventEmitter. * By extending `NodeJSEventEmitter' we get data-flow on the events passing through this EventEmitter.
*/ */
private class CustomEventEmitter extends NodeJSEventEmitter { class CustomEventEmitter extends NodeJSEventEmitter {
EventEmitterSubClass clazz;
CustomEventEmitter() { CustomEventEmitter() {
this = any(EventEmitterSubClass clazz).getAClassReference().getAnInstantiation() this = clazz.getAnInstanceReference()
}
// we define that events can flow between all instances of the same class, as we thereby support the `this` references in the class itself.
override DataFlow::SourceNode getBaseEmitter() {
result = clazz
} }
} }
/** /**
* A registration of an event handler on a NodeJS EventEmitter instance. * A registration of an event handler on a NodeJS EventEmitter instance.
*/ */
private class NodeJSEventRegistration extends EventRegistration::DefaultEventRegistration, DataFlow::MethodCallNode { private class NodeJSEventRegistration extends EventRegistration::DefaultEventRegistration,
DataFlow::MethodCallNode {
override NodeJSEventEmitter emitter; override NodeJSEventEmitter emitter;
NodeJSEventRegistration() { this = emitter.ref().getAMethodCall(EventEmitter::on()) } NodeJSEventRegistration() { this = emitter.ref().getAMethodCall(EventEmitter::on()) }
@@ -944,9 +954,12 @@ module NodeJSLib {
/** /**
* A dispatch of an event on a NodeJS EventEmitter instance. * A dispatch of an event on a NodeJS EventEmitter instance.
*/ */
private class NodeJSEventDispatch extends EventDispatch::DefaultEventDispatch, DataFlow::MethodCallNode { private class NodeJSEventDispatch extends EventDispatch::DefaultEventDispatch,
DataFlow::MethodCallNode {
override NodeJSEventEmitter emitter; override NodeJSEventEmitter emitter;
NodeJSEventDispatch() { this = emitter.ref().getAMethodCall("emit") } NodeJSEventDispatch() { this = emitter.ref().getAMethodCall("emit") }
override EventRegistration::Range getAReceiver() { emitter.getBaseEmitter() = result.getEmitter().(NodeJSEventEmitter).getBaseEmitter() }
} }
} }