summaryrefslogtreecommitdiffstats
path: root/addon-sdk/source/lib/sdk/util/dispatcher.js
diff options
context:
space:
mode:
Diffstat (limited to 'addon-sdk/source/lib/sdk/util/dispatcher.js')
-rw-r--r--addon-sdk/source/lib/sdk/util/dispatcher.js54
1 files changed, 54 insertions, 0 deletions
diff --git a/addon-sdk/source/lib/sdk/util/dispatcher.js b/addon-sdk/source/lib/sdk/util/dispatcher.js
new file mode 100644
index 000000000..67d29dfed
--- /dev/null
+++ b/addon-sdk/source/lib/sdk/util/dispatcher.js
@@ -0,0 +1,54 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
+
+module.metadata = {
+ "stability": "experimental"
+};
+
+const method = require("method/core");
+
+// Utility function that is just an enhancement over `method` to
+// allow predicate based dispatch in addition to polymorphic
+// dispatch. Unfortunately polymorphic dispatch does not quite
+// cuts it in the world of XPCOM where no types / classes exist
+// and all the XUL nodes share same type / prototype.
+// Probably this is more generic and belongs some place else, but
+// we can move it later once this will be relevant.
+var dispatcher = hint => {
+ const base = method(hint);
+ // Make a map for storing predicate, implementation mappings.
+ let implementations = new Map();
+
+ // Dispatcher function goes through `predicate, implementation`
+ // pairs to find predicate that matches first argument and
+ // returns application of arguments on the associated
+ // `implementation`. If no matching predicate is found delegates
+ // to a `base` polymorphic function.
+ let dispatch = (value, ...rest) => {
+ for (let [predicate, implementation] of implementations) {
+ if (predicate(value))
+ return implementation(value, ...rest);
+ }
+
+ return base(value, ...rest);
+ };
+
+ // Expose base API.
+ dispatch.define = base.define;
+ dispatch.implement = base.implement;
+ dispatch.toString = base.toString;
+
+ // Add a `when` function to allow extending function via
+ // predicates.
+ dispatch.when = (predicate, implementation) => {
+ if (implementations.has(predicate))
+ throw TypeError("Already implemented for the given predicate");
+ implementations.set(predicate, implementation);
+ };
+
+ return dispatch;
+};
+
+exports.dispatcher = dispatcher;