109 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			109 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
'use strict'
 | 
						|
 | 
						|
const refs = {
 | 
						|
  exit: [],
 | 
						|
  beforeExit: []
 | 
						|
}
 | 
						|
const functions = {
 | 
						|
  exit: onExit,
 | 
						|
  beforeExit: onBeforeExit
 | 
						|
}
 | 
						|
 | 
						|
let registry
 | 
						|
 | 
						|
function ensureRegistry () {
 | 
						|
  if (registry === undefined) {
 | 
						|
    registry = new FinalizationRegistry(clear)
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
function install (event) {
 | 
						|
  if (refs[event].length > 0) {
 | 
						|
    return
 | 
						|
  }
 | 
						|
 | 
						|
  process.on(event, functions[event])
 | 
						|
}
 | 
						|
 | 
						|
function uninstall (event) {
 | 
						|
  if (refs[event].length > 0) {
 | 
						|
    return
 | 
						|
  }
 | 
						|
  process.removeListener(event, functions[event])
 | 
						|
  if (refs.exit.length === 0 && refs.beforeExit.length === 0) {
 | 
						|
    registry = undefined
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
function onExit () {
 | 
						|
  callRefs('exit')
 | 
						|
}
 | 
						|
 | 
						|
function onBeforeExit () {
 | 
						|
  callRefs('beforeExit')
 | 
						|
}
 | 
						|
 | 
						|
function callRefs (event) {
 | 
						|
  for (const ref of refs[event]) {
 | 
						|
    const obj = ref.deref()
 | 
						|
    const fn = ref.fn
 | 
						|
 | 
						|
    // This should always happen, however GC is
 | 
						|
    // undeterministic so it might not happen.
 | 
						|
    /* istanbul ignore else */
 | 
						|
    if (obj !== undefined) {
 | 
						|
      fn(obj, event)
 | 
						|
    }
 | 
						|
  }
 | 
						|
  refs[event] = []
 | 
						|
}
 | 
						|
 | 
						|
function clear (ref) {
 | 
						|
  for (const event of ['exit', 'beforeExit']) {
 | 
						|
    const index = refs[event].indexOf(ref)
 | 
						|
    refs[event].splice(index, index + 1)
 | 
						|
    uninstall(event)
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
function _register (event, obj, fn) {
 | 
						|
  if (obj === undefined) {
 | 
						|
    throw new Error('the object can\'t be undefined')
 | 
						|
  }
 | 
						|
  install(event)
 | 
						|
  const ref = new WeakRef(obj)
 | 
						|
  ref.fn = fn
 | 
						|
 | 
						|
  ensureRegistry()
 | 
						|
  registry.register(obj, ref)
 | 
						|
  refs[event].push(ref)
 | 
						|
}
 | 
						|
 | 
						|
function register (obj, fn) {
 | 
						|
  _register('exit', obj, fn)
 | 
						|
}
 | 
						|
 | 
						|
function registerBeforeExit (obj, fn) {
 | 
						|
  _register('beforeExit', obj, fn)
 | 
						|
}
 | 
						|
 | 
						|
function unregister (obj) {
 | 
						|
  if (registry === undefined) {
 | 
						|
    return
 | 
						|
  }
 | 
						|
  registry.unregister(obj)
 | 
						|
  for (const event of ['exit', 'beforeExit']) {
 | 
						|
    refs[event] = refs[event].filter((ref) => {
 | 
						|
      const _obj = ref.deref()
 | 
						|
      return _obj && _obj !== obj
 | 
						|
    })
 | 
						|
    uninstall(event)
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
module.exports = {
 | 
						|
  register,
 | 
						|
  registerBeforeExit,
 | 
						|
  unregister
 | 
						|
}
 |