objects-registry.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. 'use strict'
  2. const v8Util = process.atomBinding('v8_util')
  3. class ObjectsRegistry {
  4. constructor () {
  5. this.nextId = 0
  6. // Stores all objects by ref-counting.
  7. // (id) => {object, count}
  8. this.storage = {}
  9. // Stores the IDs of objects referenced by WebContents.
  10. // (webContentsId) => [id]
  11. this.owners = {}
  12. }
  13. // Register a new object and return its assigned ID. If the object is already
  14. // registered then the already assigned ID would be returned.
  15. add (webContents, obj) {
  16. // Get or assign an ID to the object.
  17. const id = this.saveToStorage(obj)
  18. // Add object to the set of referenced objects.
  19. const webContentsId = webContents.getId()
  20. let owner = this.owners[webContentsId]
  21. if (!owner) {
  22. owner = this.owners[webContentsId] = new Set()
  23. this.registerDeleteListener(webContents, webContentsId)
  24. }
  25. if (!owner.has(id)) {
  26. owner.add(id)
  27. // Increase reference count if not referenced before.
  28. this.storage[id].count++
  29. }
  30. return id
  31. }
  32. // Get an object according to its ID.
  33. get (id) {
  34. return this.storage[id].object
  35. }
  36. // Dereference an object according to its ID.
  37. remove (webContentsId, id) {
  38. // Dereference from the storage.
  39. this.dereference(id)
  40. // Also remove the reference in owner.
  41. let owner = this.owners[webContentsId]
  42. if (owner) {
  43. owner.delete(id)
  44. }
  45. }
  46. // Clear all references to objects refrenced by the WebContents.
  47. clear (webContentsId) {
  48. let owner = this.owners[webContentsId]
  49. if (!owner) return
  50. for (let id of owner) this.dereference(id)
  51. delete this.owners[webContentsId]
  52. }
  53. // Private: Saves the object into storage and assigns an ID for it.
  54. saveToStorage (object) {
  55. let id = v8Util.getHiddenValue(object, 'atomId')
  56. if (!id) {
  57. id = ++this.nextId
  58. this.storage[id] = {
  59. count: 0,
  60. object: object
  61. }
  62. v8Util.setHiddenValue(object, 'atomId', id)
  63. }
  64. return id
  65. }
  66. // Private: Dereference the object from store.
  67. dereference (id) {
  68. let pointer = this.storage[id]
  69. if (pointer == null) {
  70. return
  71. }
  72. pointer.count -= 1
  73. if (pointer.count === 0) {
  74. v8Util.deleteHiddenValue(pointer.object, 'atomId')
  75. delete this.storage[id]
  76. }
  77. }
  78. // Private: Clear the storage when webContents is reloaded/navigated.
  79. registerDeleteListener (webContents, webContentsId) {
  80. const listener = (event, deletedProcessId) => {
  81. if (deletedProcessId === webContentsId) {
  82. webContents.removeListener('render-view-deleted', listener)
  83. this.clear(webContentsId)
  84. }
  85. }
  86. webContents.on('render-view-deleted', listener)
  87. }
  88. }
  89. module.exports = new ObjectsRegistry()