mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-09-17 11:17:28 +03:00
Improved EventEmitter for tauri api shell (#4697)
Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
This commit is contained in:
parent
f7ea867d31
commit
aa9f1243e6
5
.changes/improve-event-emitter.md
Normal file
5
.changes/improve-event-emitter.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"api": minor
|
||||
---
|
||||
|
||||
Improve shell's `Command`, `Command.stdout` and `Command.stderr` events with new `once`, `off`, `listenerCount`, `prependListener`, `prependOnceListener` and `removeAllListeners` functions.
|
File diff suppressed because one or more lines are too long
2
examples/api/dist/assets/index.css
vendored
2
examples/api/dist/assets/index.css
vendored
File diff suppressed because one or more lines are too long
54
examples/api/dist/assets/index.js
vendored
54
examples/api/dist/assets/index.js
vendored
File diff suppressed because one or more lines are too long
@ -93,9 +93,7 @@
|
||||
svelte-hmr "^0.14.12"
|
||||
|
||||
"@tauri-apps/api@../../tooling/api/dist":
|
||||
version "1.0.1"
|
||||
dependencies:
|
||||
type-fest "2.14.0"
|
||||
version "1.0.2"
|
||||
|
||||
"@unocss/cli@0.39.3":
|
||||
version "0.39.3"
|
||||
@ -888,11 +886,6 @@ totalist@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/totalist/-/totalist-3.0.0.tgz#4ef9c58c5f095255cdc3ff2a0a55091c57a3a1bd"
|
||||
integrity sha512-eM+pCBxXO/njtF7vdFsHuqb+ElbxqtI4r5EAvk6grfAFyJ6IvWlSkfZ5T9ozC6xWw3Fj1fGoSmrl0gUs46JVIw==
|
||||
|
||||
type-fest@2.14.0:
|
||||
version "2.14.0"
|
||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.14.0.tgz#f990e19169517d689c98e16d128b231022b27e12"
|
||||
integrity sha512-hQnTQkFjL5ik6HF2fTAM8ycbr94UbQXK364wF930VHb0dfBJ5JBP8qwrR8TaK9zwUEk7meruo2JAUDMwvuxd/w==
|
||||
|
||||
ufo@^0.8.4:
|
||||
version "0.8.4"
|
||||
resolved "https://registry.yarnpkg.com/ufo/-/ufo-0.8.4.tgz#23e9ed82398d2116dcb378e8fba5ced8eca2ee40"
|
||||
|
@ -134,46 +134,159 @@ async function execute(
|
||||
}
|
||||
|
||||
class EventEmitter<E extends string> {
|
||||
/** @ignore */
|
||||
/** @ignore */
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
private eventListeners: {
|
||||
[key: string]: Array<(arg: any) => void>
|
||||
} = Object.create(null)
|
||||
private eventListeners: Record<E, Array<(...args: any[]) => void>> =
|
||||
Object.create(null)
|
||||
|
||||
/** @ignore */
|
||||
private addEventListener(event: string, handler: (arg: any) => void): void {
|
||||
if (event in this.eventListeners) {
|
||||
// eslint-disable-next-line security/detect-object-injection
|
||||
this.eventListeners[event].push(handler)
|
||||
} else {
|
||||
// eslint-disable-next-line security/detect-object-injection
|
||||
this.eventListeners[event] = [handler]
|
||||
}
|
||||
}
|
||||
|
||||
/** @ignore */
|
||||
_emit(event: E, payload: any): void {
|
||||
if (event in this.eventListeners) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
const listeners = this.eventListeners[event as any]
|
||||
for (const listener of listeners) {
|
||||
listener(payload)
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Alias for `emitter.on(eventName, listener)`.
|
||||
*/
|
||||
addListener(eventName: E, listener: (...args: any[]) => void): this {
|
||||
return this.on(eventName, listener)
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen to an event from the child process.
|
||||
*
|
||||
* @param event The event name.
|
||||
* @param handler The event handler.
|
||||
*
|
||||
* @return The `this` instance for chained calls.
|
||||
* Alias for `emitter.off(eventName, listener)`.
|
||||
*/
|
||||
on(event: E, handler: (arg: any) => void): EventEmitter<E> {
|
||||
this.addEventListener(event, handler)
|
||||
removeListener(eventName: E, listener: (...args: any[]) => void): this {
|
||||
return this.off(eventName, listener)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the `listener` function to the end of the listeners array for the
|
||||
* event named `eventName`. No checks are made to see if the `listener` has
|
||||
* already been added. Multiple calls passing the same combination of `eventName`and `listener` will result in the `listener` being added, and called, multiple
|
||||
* times.
|
||||
*
|
||||
* Returns a reference to the `EventEmitter`, so that calls can be chained.
|
||||
* @param eventName The name of the event.
|
||||
* @param listener The callback function
|
||||
*/
|
||||
on(eventName: E, listener: (...args: any[]) => void): this {
|
||||
if (eventName in this.eventListeners) {
|
||||
// eslint-disable-next-line security/detect-object-injection
|
||||
this.eventListeners[eventName].push(listener)
|
||||
} else {
|
||||
// eslint-disable-next-line security/detect-object-injection
|
||||
this.eventListeners[eventName] = [listener]
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a **one-time**`listener` function for the event named `eventName`. The
|
||||
* next time `eventName` is triggered, this listener is removed and then invoked.
|
||||
*
|
||||
* Returns a reference to the `EventEmitter`, so that calls can be chained.
|
||||
*
|
||||
* @param eventName The name of the event.
|
||||
* @param listener The callback function
|
||||
*/
|
||||
once(eventName: E, listener: (...args: any[]) => void): this {
|
||||
const wrapper = (...args: any[]): void => {
|
||||
this.removeListener(eventName, wrapper)
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||
listener(...args)
|
||||
}
|
||||
return this.addListener(eventName, wrapper)
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the all specified listener from the listener array for the event eventName
|
||||
* Returns a reference to the `EventEmitter`, so that calls can be chained.
|
||||
*/
|
||||
off(eventName: E, listener: (...args: any[]) => void): this {
|
||||
if (eventName in this.eventListeners) {
|
||||
// eslint-disable-next-line security/detect-object-injection
|
||||
this.eventListeners[eventName] = this.eventListeners[eventName].filter(
|
||||
(l) => l !== listener
|
||||
)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all listeners, or those of the specified eventName.
|
||||
*
|
||||
* Returns a reference to the `EventEmitter`, so that calls can be chained.
|
||||
*/
|
||||
removeAllListeners(event?: E): this {
|
||||
if (event) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete,security/detect-object-injection
|
||||
delete this.eventListeners[event]
|
||||
} else {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
this.eventListeners = Object.create(null)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
* Synchronously calls each of the listeners registered for the event named`eventName`, in the order they were registered, passing the supplied arguments
|
||||
* to each.
|
||||
*
|
||||
* Returns `true` if the event had listeners, `false` otherwise.
|
||||
*/
|
||||
emit(eventName: E, ...args: any[]): boolean {
|
||||
if (eventName in this.eventListeners) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,security/detect-object-injection
|
||||
const listeners = this.eventListeners[eventName]
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||
for (const listener of listeners) listener(...args)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of listeners listening to the event named `eventName`.
|
||||
*/
|
||||
listenerCount(eventName: E): number {
|
||||
if (eventName in this.eventListeners)
|
||||
// eslint-disable-next-line security/detect-object-injection
|
||||
return this.eventListeners[eventName].length
|
||||
return 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the `listener` function to the _beginning_ of the listeners array for the
|
||||
* event named `eventName`. No checks are made to see if the `listener` has
|
||||
* already been added. Multiple calls passing the same combination of `eventName`and `listener` will result in the `listener` being added, and called, multiple
|
||||
* times.
|
||||
*
|
||||
* Returns a reference to the `EventEmitter`, so that calls can be chained.
|
||||
* @param eventName The name of the event.
|
||||
* @param listener The callback function
|
||||
*/
|
||||
prependListener(eventName: E, listener: (...args: any[]) => void): this {
|
||||
if (eventName in this.eventListeners) {
|
||||
// eslint-disable-next-line security/detect-object-injection
|
||||
this.eventListeners[eventName].unshift(listener)
|
||||
} else {
|
||||
// eslint-disable-next-line security/detect-object-injection
|
||||
this.eventListeners[eventName] = [listener]
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a **one-time**`listener` function for the event named `eventName` to the_beginning_ of the listeners array. The next time `eventName` is triggered, this
|
||||
* listener is removed, and then invoked.
|
||||
*
|
||||
* Returns a reference to the `EventEmitter`, so that calls can be chained.
|
||||
* @param eventName The name of the event.
|
||||
* @param listener The callback function
|
||||
*/
|
||||
prependOnceListener(eventName: E, listener: (...args: any[]) => void): this {
|
||||
const wrapper = (...args: any[]): void => {
|
||||
this.removeListener(eventName, wrapper)
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||
listener(...args)
|
||||
}
|
||||
return this.prependListener(eventName, wrapper)
|
||||
}
|
||||
}
|
||||
|
||||
class Child {
|
||||
@ -311,16 +424,16 @@ class Command extends EventEmitter<'close' | 'error'> {
|
||||
(event) => {
|
||||
switch (event.event) {
|
||||
case 'Error':
|
||||
this._emit('error', event.payload)
|
||||
this.emit('error', event.payload)
|
||||
break
|
||||
case 'Terminated':
|
||||
this._emit('close', event.payload)
|
||||
this.emit('close', event.payload)
|
||||
break
|
||||
case 'Stdout':
|
||||
this.stdout._emit('data', event.payload)
|
||||
this.stdout.emit('data', event.payload)
|
||||
break
|
||||
case 'Stderr':
|
||||
this.stderr._emit('data', event.payload)
|
||||
this.stderr.emit('data', event.payload)
|
||||
break
|
||||
}
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user