Skip to content

Commit

Permalink
perf(message): change message type to typescript enum
Browse files Browse the repository at this point in the history
  • Loading branch information
crimx committed Apr 5, 2018
1 parent 7cdb034 commit 7682a1d
Show file tree
Hide file tree
Showing 8 changed files with 190 additions and 139 deletions.
39 changes: 23 additions & 16 deletions src/_helpers/__mocks__/browser-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import { Observable } from 'rxjs/Observable'
import { fromEventPattern } from 'rxjs/observable/fromEventPattern'
import _ from 'lodash'
import { MsgType } from '@/typings/message'

/* --------------------------------------- *\
* #Types
Expand All @@ -28,10 +29,16 @@ export type StorageListenerCb = (
) => void

export interface Message {
type: string
type: number
[propName: string]: any
}

type onMessageEvent = (
message: Message,
sender: browser.runtime.MessageSender,
sendResponse: Function
) => Promise<any> | boolean | void

/* --------------------------------------- *\
* #Globals
\* --------------------------------------- */
Expand All @@ -42,14 +49,14 @@ const noop = () => { /* do nothing */ }
* key: {function} user's callback function
* values: {Map} listeners, key: message type, values: generated or user's callback functions
*/
const messageListeners: Map<browser.runtime.onMessageEvent, Map<string, browser.runtime.onMessageEvent>> = new Map()
const messageListeners: Map<onMessageEvent, Map<Message['type'], onMessageEvent>> = new Map()

/**
* For self page messaging
* key: {function} user's callback function
* values: {Map} listeners, key: message type, values: generated or user's callback functions
*/
const messageSelfListeners: Map<browser.runtime.onMessageEvent, Map<string, browser.runtime.onMessageEvent>> = new Map()
const messageSelfListeners: Map<onMessageEvent, Map<Message['type'], onMessageEvent>> = new Map()

/**
* key: {function} user's callback function
Expand Down Expand Up @@ -335,8 +342,8 @@ function _messageSend (self: boolean) {
function _messageAddListener (self: boolean) {
return jest.fn(messageAddListener)

function messageAddListener (messageType: string, cb: browser.runtime.onMessageEvent): void
function messageAddListener (cb: browser.runtime.onMessageEvent): void
function messageAddListener (messageType: Message['type'], cb: onMessageEvent): void
function messageAddListener (cb: onMessageEvent): void
function messageAddListener (...args): void {
const allListeners = self ? messageSelfListeners : messageListeners
const messageType = args.length === 1 ? undefined : args[0]
Expand All @@ -346,7 +353,7 @@ function _messageAddListener (self: boolean) {
listeners = new Map()
allListeners.set(cb, listeners)
}
let listener = listeners.get(messageType || '_&_MSG_DEFAULT_&_')
let listener = listeners.get(messageType || MsgType.Default)
if (!listener) {
listener = (
(message, sender, sendResponse) => {
Expand All @@ -356,7 +363,7 @@ function _messageAddListener (self: boolean) {
}
}
}
) as browser.runtime.onMessageEvent
) as onMessageEvent
listeners.set(messageType, listener)
}
}
Expand All @@ -365,8 +372,8 @@ function _messageAddListener (self: boolean) {
function _messageRemoveListener (self: boolean) {
return jest.fn(messageRemoveListener)

function messageRemoveListener (messageType: string, cb: browser.runtime.onMessageEvent): void
function messageRemoveListener (cb: browser.runtime.onMessageEvent): void
function messageRemoveListener (messageType: Message['type'], cb: onMessageEvent): void
function messageRemoveListener (cb: onMessageEvent): void
function messageRemoveListener (...args): void {
const allListeners = self ? messageSelfListeners : messageListeners
const messageType = args.length === 1 ? undefined : args[0]
Expand Down Expand Up @@ -395,9 +402,9 @@ function _messageCreateStream (self: boolean) {
return jest.fn(messageCreateStream)

function messageCreateStream<T> (selector?: (...args) => T): Observable<T>
function messageCreateStream<T> (messageType: string, selector?: (...args) => T): Observable<T>
function messageCreateStream<T> (messageType: Message['type'], selector?: (...args) => T): Observable<T>
function messageCreateStream (...args) {
let messageType = ''
let messageType: Message['type'] = MsgType.Null
let selector = x => x

if (typeof args[0] === 'function') {
Expand All @@ -408,16 +415,16 @@ function _messageCreateStream (self: boolean) {
}

const obj = _.get(message, self ? 'self' : '')
if (messageType) {
if (messageType !== MsgType.Null) {
return fromEventPattern(
handler => obj.addListener(messageType, handler as browser.runtime.onMessageEvent),
handler => obj.removeListener(messageType, handler as browser.runtime.onMessageEvent),
handler => obj.addListener(messageType, handler as onMessageEvent),
handler => obj.removeListener(messageType, handler as onMessageEvent),
selector,
)
} else {
return fromEventPattern(
handler => obj.addListener(handler as browser.runtime.onMessageEvent),
handler => obj.removeListener(handler as browser.runtime.onMessageEvent),
handler => obj.addListener(handler as onMessageEvent),
handler => obj.removeListener(handler as onMessageEvent),
selector,
)
}
Expand Down
53 changes: 30 additions & 23 deletions src/_helpers/browser-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import { Observable } from 'rxjs/Observable'
import { fromEventPattern } from 'rxjs/observable/fromEventPattern'
import { MsgType } from '@/typings/message'

/* --------------------------------------- *\
* #Types
Expand All @@ -27,10 +28,16 @@ export type StorageListenerCb = (
) => void

export interface Message {
type: string
type: number
[propName: string]: any
}

type onMessageEvent = (
message: Message,
sender: browser.runtime.MessageSender,
sendResponse: Function
) => Promise<any> | boolean | void

/* --------------------------------------- *\
* #Globals
\* --------------------------------------- */
Expand All @@ -41,14 +48,14 @@ const noop = () => { /* do nothing */ }
* key: {function} user's callback function
* values: {Map} listeners, key: message type, values: generated or user's callback functions
*/
const messageListeners: Map<browser.runtime.onMessageEvent, Map<string, browser.runtime.onMessageEvent>> = new Map()
const messageListeners: Map<onMessageEvent, Map<Message['type'], onMessageEvent>> = new Map()

/**
* For self page messaging
* key: {function} user's callback function
* values: {Map} listeners, key: message type, values: generated or user's callback functions
*/
const messageSelfListeners: Map<browser.runtime.onMessageEvent, Map<string, browser.runtime.onMessageEvent>> = new Map()
const messageSelfListeners: Map<onMessageEvent, Map<Message['type'], onMessageEvent>> = new Map()

/**
* key: {function} user's callback function
Expand Down Expand Up @@ -286,12 +293,12 @@ function messageSendSelf (message: Message): Promise<any> {
}
return browser.runtime.sendMessage(Object.assign({}, message, {
__pageId__: window.pageId,
type: `_&_${message.type}_&_`
type: `[[${message.type}]]`
}))
}

function messageAddListener (messageType: string, cb: browser.runtime.onMessageEvent): void
function messageAddListener (cb: browser.runtime.onMessageEvent): void
function messageAddListener (messageType: Message['type'], cb: onMessageEvent): void
function messageAddListener (cb: onMessageEvent): void
function messageAddListener (this: MessageThis, ...args): void {
const allListeners = this.__self__ ? messageSelfListeners : messageListeners
const messageType = args.length === 1 ? undefined : args[0]
Expand All @@ -301,7 +308,7 @@ function messageAddListener (this: MessageThis, ...args): void {
listeners = new Map()
allListeners.set(cb, listeners)
}
let listener = listeners.get(messageType || '_&_MSG_DEFAULT_&_')
let listener = listeners.get(messageType || MsgType.Default)
if (!listener) {
listener = (
(message, sender, sendResponse) => {
Expand All @@ -311,14 +318,14 @@ function messageAddListener (this: MessageThis, ...args): void {
}
}
}
) as browser.runtime.onMessageEvent
) as onMessageEvent
listeners.set(messageType, listener)
}
return browser.runtime.onMessage.addListener(listener)
}

function messageRemoveListener (messageType: string, cb: browser.runtime.onMessageEvent): void
function messageRemoveListener (cb: browser.runtime.onMessageEvent): void
function messageRemoveListener (messageType: Message['type'], cb: onMessageEvent): void
function messageRemoveListener (cb: onMessageEvent): void
function messageRemoveListener (this: MessageThis, ...args): void {
const allListeners = this.__self__ ? messageSelfListeners : messageListeners
const messageType = args.length === 1 ? undefined : args[0]
Expand Down Expand Up @@ -346,9 +353,9 @@ function messageRemoveListener (this: MessageThis, ...args): void {
}

function messageCreateStream<T> (selector?: (...args) => T): Observable<T>
function messageCreateStream<T> (messageType: string, selector?: (...args) => T): Observable<T>
function messageCreateStream<T> (messageType: Message['type'], selector?: (...args) => T): Observable<T>
function messageCreateStream (this: MessageThis, ...args) {
let messageType = ''
let messageType: Message['type'] = MsgType.Null
let selector = x => x

if (typeof args[0] === 'function') {
Expand All @@ -358,28 +365,28 @@ function messageCreateStream (this: MessageThis, ...args) {
selector = args[1]
}

if (messageType) {
if (messageType !== MsgType.Null) {
return fromEventPattern(
handler => this.addListener(messageType, handler as browser.runtime.onMessageEvent),
handler => this.removeListener(messageType, handler as browser.runtime.onMessageEvent),
handler => this.addListener(messageType, handler as onMessageEvent),
handler => this.removeListener(messageType, handler as onMessageEvent),
selector,
)
} else {
return fromEventPattern(
handler => this.addListener(handler as browser.runtime.onMessageEvent),
handler => this.removeListener(handler as browser.runtime.onMessageEvent),
handler => this.addListener(handler as onMessageEvent),
handler => this.removeListener(handler as onMessageEvent),
selector,
)
}
}

/**
* Deploy client side
* Deploy page script for self-messaging
* This method is called on the first sendMessage
*/
function initClient (): Promise<typeof window.pageId> {
if (window.pageId === undefined) {
return browser.runtime.sendMessage({ type: '__PAGE_INFO__' })
return browser.runtime.sendMessage({ type: MsgType.__PageInfo__ })
.then(({ pageId, faviconURL, pageTitle, pageURL }) => {
window.pageId = pageId
window.faviconURL = faviconURL
Expand All @@ -393,18 +400,18 @@ function initClient (): Promise<typeof window.pageId> {
}

/**
* Deploy server side
* Deploy background proxy for self-messaging
* This method should be invoked in background script
*/
function initServer (): void {
window.pageId = 'background page'
const selfMsgTester = /^_&_(.+)_&_$/
const selfMsgTester = /^\[\[(.+)\]\]$/

browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (!message) { return }

switch (message.type) {
case '__PAGE_INFO__':
case MsgType.__PageInfo__:
sendResponse(_getPageInfo(sender))
break
default:
Expand All @@ -413,7 +420,7 @@ function initServer (): void {

const selfMsg = selfMsgTester.exec(message.type)
if (selfMsg) {
message.type = selfMsg[1]
message.type = Number(selfMsg[1])
if (sender.tab && sender.tab.id) {
return messageSend(sender.tab.id, message)
} else {
Expand Down
41 changes: 21 additions & 20 deletions src/background/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,30 @@ import { DictID } from '@/app-config'
import { message, openURL } from '@/_helpers/browser-api'
import { play } from './audio-manager'
import { chsToChz } from '@/_helpers/chs-to-chz'
import { MsgType } from '@/typings/message'

interface MessageOpenUrlWithEscape {
type: 'OPEN_URL'
interface MsgOpenUrlWithEscape {
type: MsgType.OpenURL
url: string
escape: true
text: string
}

interface MessageOpenUrlWithoutEscape {
type: 'OPEN_URL'
interface MsgOpenUrlWithoutEscape {
type: MsgType.OpenURL
url: string
escape?: false
}

type MessageOpenUrl = MessageOpenUrlWithoutEscape | MessageOpenUrlWithEscape
type MsgOpenUrl = MsgOpenUrlWithoutEscape | MsgOpenUrlWithEscape

interface MessageAudioPlay {
type: 'AUDIO_PLAY'
interface MsgAudioPlay {
type: MsgType.PlayAudio
src: string
}

interface MessageFetchDictResult {
type: 'FETCH_DICT_RESULT'
interface MsgFetchDictResult {
type: MsgType.FetchDictResult
dict: DictID
text: string
}
Expand All @@ -34,18 +35,18 @@ message.self.initServer()
// background script as transfer station
message.addListener((data, sender: browser.runtime.MessageSender): Promise<void> | undefined => {
switch (data.type) {
case 'OPEN_URL':
return createTab(data)
case 'AUDIO_PLAY':
return playAudio(data)
case 'FETCH_DICT_RESULT':
return fetchDictResult(data)
case 'PRELOAD_SELECTION':
case MsgType.OpenURL:
return createTab(data as MsgOpenUrl)
case MsgType.PlayAudio:
return playAudio(data as MsgAudioPlay)
case MsgType.FetchDictResult:
return fetchDictResult(data as MsgFetchDictResult)
case MsgType.PreloadSelection:
return preloadSelection()
}
})

function createTab (data: MessageOpenUrl): Promise<void> {
function createTab (data: MsgOpenUrl): Promise<void> {
return openURL(
data.escape
? data.url
Expand All @@ -55,11 +56,11 @@ function createTab (data: MessageOpenUrl): Promise<void> {
)
}

function playAudio (data: MessageAudioPlay): Promise<void> {
function playAudio (data: MsgAudioPlay): Promise<void> {
return play(data.src)
}

function fetchDictResult (data: MessageFetchDictResult): Promise<void> {
function fetchDictResult (data: MsgFetchDictResult): Promise<void> {
let search

try {
Expand All @@ -76,7 +77,7 @@ function preloadSelection (): Promise<void> {
return browser.tabs.query({ active: true, currentWindow: true })
.then(tabs => {
if (tabs.length > 0 && tabs[0].id != null) {
return message.send(tabs[0].id as number, { type: '__PRELOAD_SELECTION__' })
return message.send(tabs[0].id as number, { type: MsgType.__PreloadSelection__ })
}
})
.then(text => text || '')
Expand Down
Loading

0 comments on commit 7682a1d

Please sign in to comment.