Re-use existing JS event emitters when creating JS side wrappers
By not re-using JS event emitters, if a JS/C++ wrapper is created twice for a `QObject` then any previously registered event handlers will be overwritten and lost when the `QObject`'s `initNodeEventEmitter()` is called for a 2nd time.
This commit is contained in:
parent
faa6adcb23
commit
87e6531c65
@ -22,6 +22,14 @@
|
||||
return env.Null(); \
|
||||
} \
|
||||
\
|
||||
Napi::Value getNodeEventEmitter(const Napi::CallbackInfo& info) { \
|
||||
Napi::Env env = info.Env(); \
|
||||
if (this->instance->emitOnNode) { \
|
||||
return this->instance->emitOnNode.Value(); \
|
||||
} else { \
|
||||
return env.Null(); \
|
||||
} \
|
||||
} \
|
||||
Napi::Value subscribeToQtEvent(const Napi::CallbackInfo& info) { \
|
||||
Napi::Env env = info.Env(); \
|
||||
Napi::String eventString = info[0].As<Napi::String>(); \
|
||||
@ -42,6 +50,8 @@
|
||||
COMPONENT_WRAPPED_METHODS_EXPORT_DEFINE(WidgetWrapName) \
|
||||
InstanceMethod("initNodeEventEmitter", \
|
||||
&WidgetWrapName::initNodeEventEmitter), \
|
||||
InstanceMethod("getNodeEventEmitter", \
|
||||
&WidgetWrapName::getNodeEventEmitter), \
|
||||
InstanceMethod("subscribeToQtEvent", \
|
||||
&WidgetWrapName::subscribeToQtEvent), \
|
||||
InstanceMethod("unSubscribeToQtEvent", \
|
||||
|
||||
@ -38,30 +38,37 @@ export abstract class EventWidget<Signals extends unknown> extends Component {
|
||||
private _isEventProcessed = false;
|
||||
constructor(native: NativeElement) {
|
||||
super();
|
||||
if (native.initNodeEventEmitter) {
|
||||
this.emitter = new EventEmitter();
|
||||
this.emitter.emit = wrapWithActivateUvLoop(this.emitter.emit.bind(this.emitter));
|
||||
const logExceptions = (event: string | symbol, ...args: any[]): boolean => {
|
||||
// Preserve the value of `_isQObjectEventProcessed` as we dispatch this event
|
||||
// to JS land, and restore it afterwards. This lets us support recursive event
|
||||
// dispatches on the same object.
|
||||
const previousEventProcessed = this._isEventProcessed;
|
||||
this._isEventProcessed = false;
|
||||
try {
|
||||
this.emitter.emit(event, ...args);
|
||||
} catch (e) {
|
||||
console.log(`An exception was thrown while dispatching an event of type '${event.toString()}':`);
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
const returnCode = this._isEventProcessed;
|
||||
this._isEventProcessed = previousEventProcessed;
|
||||
return returnCode;
|
||||
};
|
||||
native.initNodeEventEmitter(logExceptions);
|
||||
} else {
|
||||
if (native.initNodeEventEmitter == null) {
|
||||
throw new Error('initNodeEventEmitter not implemented on native side');
|
||||
}
|
||||
|
||||
const preexistingEmitterFunc = native.getNodeEventEmitter();
|
||||
if (preexistingEmitterFunc != null) {
|
||||
this.emitter = preexistingEmitterFunc.emitter;
|
||||
return;
|
||||
}
|
||||
|
||||
this.emitter = new EventEmitter();
|
||||
this.emitter.emit = wrapWithActivateUvLoop(this.emitter.emit.bind(this.emitter));
|
||||
const logExceptions = (event: string | symbol, ...args: any[]): boolean => {
|
||||
// Preserve the value of `_isQObjectEventProcessed` as we dispatch this event
|
||||
// to JS land, and restore it afterwards. This lets us support recursive event
|
||||
// dispatches on the same object.
|
||||
const previousEventProcessed = this._isEventProcessed;
|
||||
this._isEventProcessed = false;
|
||||
try {
|
||||
this.emitter.emit(event, ...args);
|
||||
} catch (e) {
|
||||
console.log(`An exception was thrown while dispatching an event of type '${event.toString()}':`);
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
const returnCode = this._isEventProcessed;
|
||||
this._isEventProcessed = previousEventProcessed;
|
||||
return returnCode;
|
||||
};
|
||||
logExceptions.emitter = this.emitter;
|
||||
native.initNodeEventEmitter(logExceptions);
|
||||
addDefaultErrorHandler(native, this.emitter);
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user