Add Object.addListener(same as '.on') and prependListener to allow a handler to be added first

This commit is contained in:
Gordon Williams 2023-06-16 10:30:10 +01:00
parent 0ff17562bb
commit 8f07e0e0dd
4 changed files with 59 additions and 13 deletions

View File

@ -11,6 +11,7 @@
Graphics: Add Espruino-specific extension to PBF font loader to handle 2bpp
Graphics: Improve blendColor when outputting to 2/4/8bpp Graphics
Graphics: Allow setFont(...) to work with >1bpp and PBF fonts
Add Object.addListener(same as '.on') and prependListener to allow a handler to be added first
2v18 : Fix drawString with setClipRect with 90/270-degree rotation (fix #2343)
Pico/Wifi: Enabled JIT compiler

View File

@ -841,8 +841,23 @@ If you have more than one handler for an event, and you'd
like that handler to stop the event being passed to other handlers
then you can call `E.stopEventPropagation()` in that handler.
*/
/*JSON{
"type" : "method",
"class" : "Object",
"name" : "addListener",
"ifndef" : "ESPR_EMBED",
"generate" : "jswrap_object_on",
"params" : [
["event","JsVar","The name of the event, for instance 'data'"],
["listener","JsVar","The listener to call when this event is received"]
]
}
Register an event listener for this object, for instance `Serial1.addListener('data', function(d) {...})`.
An alias for `Object.on`
*/
#ifndef ESPR_EMBED
void jswrap_object_on(JsVar *parent, JsVar *event, JsVar *listener) {
void jswrap_object_on_X(JsVar *parent, JsVar *event, JsVar *listener, bool addFirst) {
if (!jsvHasChildren(parent)) {
jsExceptionHere(JSET_TYPEERROR, "Parent must be an object - not a String, Integer, etc.");
return;
@ -863,20 +878,20 @@ void jswrap_object_on(JsVar *parent, JsVar *event, JsVar *listener) {
jsvUnLock(eventName);
JsVar *eventListeners = jsvSkipName(eventList);
if (jsvIsUndefined(eventListeners)) {
// just add
// just add the one handler on its own
jsvSetValueOfName(eventList, listener);
} else {
if (jsvIsArray(eventListeners)) {
// we already have an array, just add to it
jsvArrayPush(eventListeners, listener);
} else {
// not an array - we need to make it an array
JsVar *arr = jsvNewEmptyArray();
// we already have an array and we just add to it
// OR it's not an array but we need to make it an array
JsVar *arr = jsvNewEmptyArray();
if (addFirst) jsvArrayPush(arr, listener);
if (jsvIsArray(eventListeners))
jsvArrayPushAll(arr, eventListeners, false);
else
jsvArrayPush(arr, eventListeners);
jsvArrayPush(arr, listener);
jsvSetValueOfName(eventList, arr);
jsvUnLock(arr);
}
if (!addFirst) jsvArrayPush(arr, listener);
jsvSetValueOfName(eventList, arr);
jsvUnLock(arr);
}
jsvUnLock2(eventListeners, eventList);
/* Special case if we're a data listener and data has already arrived then
@ -890,8 +905,31 @@ void jswrap_object_on(JsVar *parent, JsVar *event, JsVar *listener) {
jsvUnLock(buf);
}
}
void jswrap_object_on(JsVar *parent, JsVar *event, JsVar *listener) {
jswrap_object_on_X(parent, event, listener, false/*addFirst*/);
}
/*JSON{
"type" : "method",
"class" : "Object",
"name" : "prependListener",
"ifndef" : "ESPR_EMBED",
"generate" : "jswrap_object_prependListener",
"params" : [
["event","JsVar","The name of the event, for instance 'data'"],
["listener","JsVar","The listener to call when this event is received"]
]
}
Register an event listener for this object, for instance `Serial1.addListener('data', function(d) {...})`.
An alias for `Object.on`
*/
void jswrap_object_prependListener(JsVar *parent, JsVar *event, JsVar *listener) {
jswrap_object_on_X(parent, event, listener, true/*addFirst*/);
}
#endif
/*JSON{
"type" : "method",
"class" : "Object",

View File

@ -53,6 +53,7 @@ JsVar *jswrap_object_setPrototypeOf(JsVar *object, JsVar *proto);
JsVar *jswrap_object_assign(JsVar *args);
#ifndef ESPR_EMBED
void jswrap_object_on(JsVar *parent, JsVar *event, JsVar *listener);
void jswrap_object_prependListener(JsVar *parent, JsVar *event, JsVar *listener);
void jswrap_object_emit(JsVar *parent, JsVar *event, JsVar *argArray);
#endif
void jswrap_object_removeListener(JsVar *parent, JsVar *event, JsVar *callback);

View File

@ -12,5 +12,11 @@ foo.on('down', function(x) { val-=x; });
foo.emit('up');
foo.emit('down', 58);
var val2 = "";
foo.on('a', function() { val2+="b"; });
foo.addListener('a', function() { val2+="c"; }); // same as .on
foo.prependListener('a', function() { val2+="a"; }); // add first
foo.emit("a");
// set result after a timeout - to allow the events time to execute
setTimeout("result = val==42;",1);
setTimeout("result = val==42 && val2='abc';",1);