Skip to content

Commit

Permalink
improve(plugin): add beforeunload interceptor
Browse files Browse the repository at this point in the history
  • Loading branch information
xyhp915 committed May 21, 2021
1 parent d8fd0b9 commit 1cf08d0
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 11 deletions.
41 changes: 34 additions & 7 deletions libs/src/LSPlugin.caller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@ const debug = Debug('LSPlugin:caller')

type DeferredActor = ReturnType<typeof deferred>

export const FLAG_AWAIT = '#await#response#'
export const LSPMSG = '#lspmsg#'
export const LSPMSG_ERROR_TAG = '#lspmsg#error#'
export const LSPMSG_SETTINGS = '#lspmsg#settings#'
export const LSPMSG_BEFORE_UNLOAD = '#lspmsg#beforeunload#'
export const LSPMSG_SYNC = '#lspmsg#reply#'
export const LSPMSG_READY = '#lspmsg#ready#'
export const LSPMSGFn = (id: string) => `${LSPMSG}${id}`
export const AWAIT_LSPMSGFn = (id: string) => `${FLAG_AWAIT}${id}`

/**
* Call between core and user
Expand All @@ -33,10 +36,16 @@ class LSPluginCaller extends EventEmitter {
private _call?: (type: string, payload: any, actor?: DeferredActor) => Promise<any>
private _callUserModel?: (type: string, payload: any) => Promise<any>

private _debugTag = ''

constructor (
private _pluginLocal: PluginLocal | null
) {
super()

if (_pluginLocal) {
this._debugTag = _pluginLocal.debugTag
}
}

async connectToChild () {
Expand Down Expand Up @@ -67,12 +76,18 @@ class LSPluginCaller extends EventEmitter {
await readyDeferred.resolve()
},

[LSPMSG_BEFORE_UNLOAD]: async (e) => {
const actor = deferred(10 * 1000)
caller.emit('beforeunload', Object.assign({ actor }, e))
await actor.promise
},

[LSPMSG_SETTINGS]: async ({ type, payload }) => {
caller.emit('settings:changed', payload)
},

[LSPMSG]: async ({ ns, type, payload }: any) => {
debug(`[call from host #${this._pluginLocal?.id}]`, ns, type, payload)
debug(`${this._debugTag} [call from host]`, ns, type, payload)

if (ns && ns.startsWith('hook')) {
caller.emit(`${ns}:${type}`, payload)
Expand Down Expand Up @@ -160,8 +175,6 @@ class LSPluginCaller extends EventEmitter {
}

async call (type: any, payload: any = {}) {
// TODO: ?
this.emit(type, payload)
return this._call?.call(this, type, payload)
}

Expand Down Expand Up @@ -207,12 +220,17 @@ class LSPluginCaller extends EventEmitter {
})

this._call = async (...args: any) => {
// parent all will get message
// parent all will get message before handshaked
await refChild.call(LSPMSGFn(pl.id), { type: args[0], payload: args[1] || {} })
}

this._callUserModel = async (...args: any) => {
await refChild.call(args[0], args[1] || {})
this._callUserModel = async (type, payload: any) => {
if (type.startsWith(FLAG_AWAIT)) {
// TODO: attach payload
return await refChild.get(type.replace(FLAG_AWAIT, ''))
} else {
refChild.call(type, payload)
}
}

resolve(null)
Expand Down Expand Up @@ -252,7 +270,12 @@ class LSPluginCaller extends EventEmitter {
}

this._callUserModel = async (...args: any) => {
const type = args[0]
let type = args[0] as string

if (type?.startsWith(FLAG_AWAIT)) {
type = type.replace(FLAG_AWAIT, '')
}

const payload = args[1] || {}
const fn = this._userModel[type]

Expand Down Expand Up @@ -280,6 +303,10 @@ class LSPluginCaller extends EventEmitter {
return this._shadow?.frame
}

set debugTag (value: string) {
this._debugTag = value
}

async destroy () {
if (this._parent) {
await this._parent.destroy()
Expand Down
7 changes: 4 additions & 3 deletions libs/src/LSPlugin.core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
LSPluginCaller,
LSPMSG_READY, LSPMSG_SYNC,
LSPMSG, LSPMSG_SETTINGS,
LSPMSG_ERROR_TAG
LSPMSG_ERROR_TAG, LSPMSG_BEFORE_UNLOAD, AWAIT_LSPMSGFn
} from './LSPlugin.caller'
import {
ILSPluginThemeManager,
Expand Down Expand Up @@ -590,10 +590,11 @@ class PluginLocal
try {
this._status = PluginLocalLoadStatus.UNLOADING

const eventBeforeUnload = {}
const eventBeforeUnload = { unregister }

// sync call
try {
await this._caller?.callUserModel(AWAIT_LSPMSGFn(LSPMSG_BEFORE_UNLOAD), eventBeforeUnload)
this.emit('beforeunload', eventBeforeUnload)
} catch (e) {
console.error('[beforeunload Error]', e)
Expand Down Expand Up @@ -689,7 +690,7 @@ class PluginLocal
}

get debugTag () {
return `[${this._options?.name} #${this._id}]`
return `#${this._id} [${this._options?.name}]`
}

get localRoot (): string {
Expand Down
5 changes: 5 additions & 0 deletions libs/src/LSPlugin.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,11 @@ interface ILSPluginUser extends EventEmitter<LSPluginUserEvents> {

ready (model?: Record<string, any>, callback?: (e: any) => void | {}): Promise<any>

/**
* @param callback
*/
beforeunload: (callback:() => Promise<void>) => void

/**
* @param model
*/
Expand Down
35 changes: 34 additions & 1 deletion libs/src/LSPlugin.user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,22 @@ const KEY_MAIN_UI = 0
*/
export class LSPluginUser extends EventEmitter<LSPluginUserEvents> implements ILSPluginUser {
/**
* Indicate connected with host
* @private
*/
private _connected: boolean = false

/**
* ui frame identities
* @private
*/
private _ui = new Map<number, uiState>()

/**
* handler of before unload plugin
* @private
*/
private _beforeunloadCallback?: (e: any) => Promise<void>

/**
* @param _baseInfo
* @param _caller
Expand All @@ -130,6 +140,20 @@ export class LSPluginUser extends EventEmitter<LSPluginUserEvents> implements IL
const a = Object.assign(this._baseInfo.settings, payload)
this.emit('settings:changed', { ...a }, b)
})

_caller.on('beforeunload', async (payload) => {
const { actor, ...rest } = payload
const cb = this._beforeunloadCallback
if (!cb || !actor) return

try {
cb && await cb(rest)
actor.resolve(null)
} catch (e) {
console.debug(`${_caller.debugTag} [beforeunload] `, e)
actor.reject(e)
}
})
}

async ready (
Expand All @@ -151,12 +175,21 @@ export class LSPluginUser extends EventEmitter<LSPluginUserEvents> implements IL

this._connected = true

if (baseInfo?.id) {
this._caller.debugTag = `#${baseInfo.id} [${baseInfo.name}]`
}

callback && callback.call(this, baseInfo)
} catch (e) {
console.error('[LSPlugin Ready Error]', e)
}
}

beforeunload (callback: (e: any) => Promise<void>): void {
if (typeof callback !== 'function') return
this._beforeunloadCallback = callback
}

provideModel (model: Record<string, any>) {
this.caller._extendUserModel(model)
return this
Expand Down

0 comments on commit 1cf08d0

Please sign in to comment.