|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
|
4 */ |
|
5 "use strict"; |
|
6 |
|
7 module.metadata = { |
|
8 "stability": "experimental" |
|
9 }; |
|
10 |
|
11 const method = require("method/core"); |
|
12 |
|
13 // Utility function that is just an enhancement over `method` to |
|
14 // allow predicate based dispatch in addition to polymorphic |
|
15 // dispatch. Unfortunately polymorphic dispatch does not quite |
|
16 // cuts it in the world of XPCOM where no types / classes exist |
|
17 // and all the XUL nodes share same type / prototype. |
|
18 // Probably this is more generic and belongs some place else, but |
|
19 // we can move it later once this will be relevant. |
|
20 let dispatcher = hint => { |
|
21 const base = method(hint); |
|
22 // Make a map for storing predicate, implementation mappings. |
|
23 let implementations = new Map(); |
|
24 |
|
25 // Dispatcher function goes through `predicate, implementation` |
|
26 // pairs to find predicate that matches first argument and |
|
27 // returns application of arguments on the associated |
|
28 // `implementation`. If no matching predicate is found delegates |
|
29 // to a `base` polymorphic function. |
|
30 let dispatch = (value, ...rest) => { |
|
31 for (let [predicate, implementation] of implementations) { |
|
32 if (predicate(value)) |
|
33 return implementation(value, ...rest); |
|
34 } |
|
35 |
|
36 return base(value, ...rest); |
|
37 }; |
|
38 |
|
39 // Expose base API. |
|
40 dispatch.define = base.define; |
|
41 dispatch.implement = base.implement; |
|
42 dispatch.toString = base.toString; |
|
43 |
|
44 // Add a `when` function to allow extending function via |
|
45 // predicates. |
|
46 dispatch.when = (predicate, implementation) => { |
|
47 if (implementations.has(predicate)) |
|
48 throw TypeError("Already implemented for the given predicate"); |
|
49 implementations.set(predicate, implementation); |
|
50 }; |
|
51 |
|
52 return dispatch; |
|
53 }; |
|
54 |
|
55 exports.dispatcher = dispatcher; |