CallbackWrapper.jsm 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  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-2022 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://gitlab.com/vannilla/ematrix
  16. uMatrix Home: https://github.com/gorhill/uMatrix
  17. */
  18. 'use strict';
  19. var EXPORTED_SYMBOLS = ['CallbackWrapper'];
  20. var junkyard = [];
  21. var CallbackWrapper = function (messageManager, channelName,
  22. listenerId, requestId) {
  23. // This allows to avoid creating a closure for every single
  24. // message which expects an answer. Having a closure created
  25. // each time a message is processed has been always bothering
  26. // me. Another benefit of the implementation here is to reuse
  27. // the callback proxy object, so less memory churning.
  28. //
  29. // https://developers.google.com/speed/articles/optimizing-javascript
  30. // "Creating a closure is significantly slower then creating
  31. // an inner function without a closure, and much slower than
  32. // reusing a static function"
  33. //
  34. // http://hacksoflife.blogspot.ca/2015/01/the-four-horsemen-of-performance.html
  35. // "the dreaded 'uniformly slow code' case where every
  36. // function takes 1% of CPU and you have to make one hundred
  37. // separate performance optimizations to improve performance
  38. // at all"
  39. //
  40. // http://jsperf.com/closure-no-closure/2
  41. this.callback = this.proxy.bind(this); // bind once
  42. this.init(messageManager, channelName, listenerId, requestId);
  43. };
  44. CallbackWrapper.factory = function (messageManager, channelName,
  45. listenerId, requestId) {
  46. let wrapper = junkyard.pop();
  47. if (wrapper) {
  48. wrapper.init(messageManager, channelName, listenerId, requestId);
  49. return wrapper;
  50. }
  51. return new CallbackWrapper(messageManager, channelName,
  52. listenerId, requestId);
  53. };
  54. CallbackWrapper.prototype.init = function (messageManager, channelName,
  55. listenerId, requestId) {
  56. this.messageManager = messageManager;
  57. this.channelName = channelName;
  58. this.listenerId = listenerId;
  59. this.requestId = requestId;
  60. };
  61. CallbackWrapper.prototype.proxy = function (response) {
  62. let message = JSON.stringify({
  63. requestId: this.requestId,
  64. channelName: this.channelName,
  65. msg: response !== undefined ? response : null
  66. });
  67. if (this.messageManager.sendAsyncMessage) {
  68. this.messageManager.sendAsyncMessage(this.listenerId, message);
  69. } else {
  70. this.messageManager.broadcastAsyncMessage(this.listenerId, message);
  71. }
  72. // Mark for reuse
  73. this.messageManager = this.channelName =
  74. this.requestId = this.listenerId = null;
  75. junkyard.push(this);
  76. };