aboutsummaryrefslogtreecommitdiffstats
path: root/lib/CallbackWrapper.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CallbackWrapper.jsm')
-rw-r--r--lib/CallbackWrapper.jsm92
1 files changed, 92 insertions, 0 deletions
diff --git a/lib/CallbackWrapper.jsm b/lib/CallbackWrapper.jsm
new file mode 100644
index 0000000..1d3664e
--- /dev/null
+++ b/lib/CallbackWrapper.jsm
@@ -0,0 +1,92 @@
+/*******************************************************************************
+
+ ηMatrix - a browser extension to black/white list requests.
+ Copyright (C) 2014-2019 The uMatrix/uBlock Origin authors
+ Copyright (C) 2019 Alessio Vanni
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see {http://www.gnu.org/licenses/}.
+
+ Home: https://gitlab.com/vannilla/ematrix
+ uMatrix Home: https://github.com/gorhill/uMatrix
+*/
+
+'use strict';
+
+var EXPORTED_SYMBOLS = ['CallbackWrapper'];
+
+var junkyard = [];
+
+var CallbackWrapper = function (messageManager, channelName,
+ listenerId, requestId) {
+ // This allows to avoid creating a closure for every single
+ // message which expects an answer. Having a closure created
+ // each time a message is processed has been always bothering
+ // me. Another benefit of the implementation here is to reuse
+ // the callback proxy object, so less memory churning.
+ //
+ // https://developers.google.com/speed/articles/optimizing-javascript
+ // "Creating a closure is significantly slower then creating
+ // an inner function without a closure, and much slower than
+ // reusing a static function"
+ //
+ // http://hacksoflife.blogspot.ca/2015/01/the-four-horsemen-of-performance.html
+ // "the dreaded 'uniformly slow code' case where every
+ // function takes 1% of CPU and you have to make one hundred
+ // separate performance optimizations to improve performance
+ // at all"
+ //
+ // http://jsperf.com/closure-no-closure/2
+ this.callback = this.proxy.bind(this); // bind once
+ this.init(messageManager, channelName, listenerId, requestId);
+};
+
+CallbackWrapper.factory = function (messageManager, channelName,
+ listenerId, requestId) {
+ let wrapper = junkyard.pop();
+ if (wrapper) {
+ wrapper.init(messageManager, channelName, listenerId, requestId);
+ return wrapper;
+ }
+
+ return new CallbackWrapper(messageManager, channelName,
+ listenerId, requestId);
+};
+
+CallbackWrapper.prototype.init = function (messageManager, channelName,
+ listenerId, requestId) {
+ this.messageManager = messageManager;
+ this.channelName = channelName;
+ this.listenerId = listenerId;
+ this.requestId = requestId;
+};
+
+CallbackWrapper.prototype.proxy = function (response) {
+ let message = JSON.stringify({
+ requestId: this.requestId,
+ channelName: this.channelName,
+ msg: response !== undefined ? response : null
+ });
+
+ if (this.messageManager.sendAsyncMessage) {
+ this.messageManager.sendAsyncMessage(this.listenerId, message);
+ } else {
+ this.messageManager.broadcastAsyncMessage(this.listenerId, message);
+ }
+
+ // Mark for reuse
+ this.messageManager = this.channelName =
+ this.requestId = this.listenerId = null;
+
+ junkyard.push(this);
+};