CallbackWrapper.jsm 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. /*******************************************************************************
  2. ηMatrix - a browser extension to black/white list requests.
  3. Copyright (C) 2014-2019 The uMatrix/uBlock Origin authors
  4. Copyright (C) 2019 Alessio Vanni
  5. This program is free software: you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation, either version 3 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see {http://www.gnu.org/licenses/}.
  15. Home: https://libregit.org/heckyel/ematrix
  16. uMatrix Home: https://github.com/gorhill/uMatrix
  17. */
  18. var EXPORTED_SYMBOLS = ['CallbackWrapper'];
  19. var junkyard = [];
  20. var CallbackWrapper = function (messageManager, channelName,
  21. listenerId, requestId) {
  22. // This allows to avoid creating a closure for every single
  23. // message which expects an answer. Having a closure created
  24. // each time a message is processed has been always bothering
  25. // me. Another benefit of the implementation here is to reuse
  26. // the callback proxy object, so less memory churning.
  27. //
  28. // https://developers.google.com/speed/articles/optimizing-javascript
  29. // "Creating a closure is significantly slower then creating
  30. // an inner function without a closure, and much slower than
  31. // reusing a static function"
  32. //
  33. // http://hacksoflife.blogspot.ca/2015/01/the-four-horsemen-of-performance.html
  34. // "the dreaded 'uniformly slow code' case where every
  35. // function takes 1% of CPU and you have to make one hundred
  36. // separate performance optimizations to improve performance
  37. // at all"
  38. //
  39. // http://jsperf.com/closure-no-closure/2
  40. this.callback = this.proxy.bind(this); // bind once
  41. this.init(messageManager, channelName, listenerId, requestId);
  42. };
  43. CallbackWrapper.factory = function (messageManager, channelName,
  44. listenerId, requestId) {
  45. let wrapper = junkyard.pop();
  46. if (wrapper) {
  47. wrapper.init(messageManager, channelName, listenerId, requestId);
  48. return wrapper;
  49. }
  50. return new CallbackWrapper(messageManager, channelName,
  51. listenerId, requestId);
  52. };
  53. CallbackWrapper.prototype.init = function (messageManager, channelName,
  54. listenerId, requestId) {
  55. this.messageManager = messageManager;
  56. this.channelName = channelName;
  57. this.listenerId = listenerId;
  58. this.requestId = requestId;
  59. };
  60. CallbackWrapper.prototype.proxy = function (response) {
  61. let message = JSON.stringify({
  62. requestId: this.requestId,
  63. channelName: this.channelName,
  64. msg: response !== undefined ? response : null
  65. });
  66. if (this.messageManager.sendAsyncMessage) {
  67. this.messageManager.sendAsyncMessage(this.listenerId, message);
  68. } else {
  69. this.messageManager.broadcastAsyncMessage(this.listenerId, message);
  70. }
  71. // Mark for reuse
  72. this.messageManager = this.channelName =
  73. this.requestId = this.listenerId = null;
  74. junkyard.push(this);
  75. };