Debian package: Calling a symlinked xulrunner-stub
[conkeror.git] / modules / hook.js
blobd6d4a40420349c68c9b0ec4587a108d8e905762d
1 /**
2  * (C) Copyright 2007-2008 Jeremy Maitin-Shepard
3  *
4  * Use, modification, and distribution are subject to the terms specified in the
5  * COPYING file.
6 **/
8 /* Adds the specified function to the specified hook.  To add a local
9  * hook, invoke this function as:  add_hook.call(context, hook_name, ...).
10  * Note: hook_name must be a string */
11 function add_hook(hook_name, func, prepend, avoid_duplicates)
13     if (!this[hook_name])
14         this[hook_name] = [];
15     var hook = this[hook_name];
17     if (avoid_duplicates && hook.indexOf(func) != -1)
18         return func;
20     if (prepend)
21         hook.unshift(func);
22     else
23         hook.push(func);
24     return func;
27 /**
28  * Call every function in the array `hook' with the remaining
29  * arguments of this function.  Note: This should only be used by
30  * define_hook and friends to define hook.run(...) functions.  Hooks
31  * should always be run by calling hook.run(...).
32  */
33 function run_hooks(hook, args)
35     if (hook == null)
36         return;
37     for (let i = 0; i < hook.length; ++i)
38         hook[i].apply (null, Array.prototype.slice.call(args));
41 function run_hooks_until_success(hook, args)
43     if (hook == null)
44         return false;
45     for (let i = 0; i < hook.length; ++i)
46         if (hook[i].apply (null, Array.prototype.slice.call(args)))
47             return true;
48     return false;
51 function run_hooks_until_failure(hook, args)
53     if (hook == null)
54         return true;
55     for (let i = 0; i < hook.length; ++i)
56         if (!hook[i].apply (null, Array.prototype.slice.call(args)))
57             return false;
58     return true;
61 var hook_type_doc_strings = [
62     /* RUN_HOOK */
63     "Each hook function is run in sequence.",
65     /* RUN_HOOK_UNTIL_SUCCESS */
66     "Each hook function is run in sequence until one returns a "+
67         "logically true value.",
69     /* RUN_HOOK_UNTIL_FAILURE */
70     "Each hook function is run in sequence until one returns a "+
71         "logically false value.  If no function returns such a "+
72         "value, then the result of the hook will be `true'."];
75 /* This should only be used by define_hook functions */
76 function initialize_hook(prototype, hook_name, hook_type, doc_string, extra_doc_string)
78     var h = this[hook_name];
79     if (h == null)
80         h = this[hook_name] = [];
81     if (hook_type == null)
82         hook_type = RUN_HOOK;
83     switch (hook_type) {
84     case RUN_HOOK:
85         h.run = prototype.run;
86         break;
87     case RUN_HOOK_UNTIL_SUCCESS:
88         h.run = prototype.run_until_success;
89         break;
90     case RUN_HOOK_UNTIL_FAILURE:
91         h.run = prototype.run_until_failure;
92         break;
93     }
94     h.hook_type = hook_type;
95     h.hook_name = hook_name;
96     h.doc_string =
97         (doc_string? doc_string + "\n" : "") +
98         hook_type_doc_strings[hook_type] +
99         (extra_doc_string? "\n" + extra_doc_string : "");
100     h.source_code_reference = get_caller_source_code_reference(1);
101     return h;
104 var hook_global_prototype = {
105     run: function() {
106         run_hooks(this, arguments);
107     },
108     run_until_success: function() {
109         return run_hooks_until_success(this, arguments);
110     },
111     run_until_failure: function() {
112         return run_hooks_until_failure(this, arguments);
113     }
116 const RUN_HOOK = 0;
117 const RUN_HOOK_UNTIL_SUCCESS = 1;
118 const RUN_HOOK_UNTIL_FAILURE = 2;
120 function define_hook(hook_name, hook_type, doc_string)
122     initialize_hook(hook_global_prototype, hook_name, hook_type, doc_string);
125 var hook_simple_local_prototype = {
126     run: function(x) {
127         var hook_name = this.hook_name;
128         if (hook_name in x) run_hooks(x[hook_name], arguments);
129         run_hooks(this, arguments);
130     },
131     run_until_success: function (x) {
132         var hook_name = this.hook_name;
133         if ((hook_name in x) && run_hooks_until_success(x[hook_name], arguments)) return true;
134             return run_hooks_until_success(conkeror[hook_name], arguments);
135     },
136     run_until_failure: function (x) {
137         var hook_name = this.hook_name;
138         if ((hook_name in x) && !run_hooks_until_success(x[hook_name], arguments)) return false;
139         return run_hooks_until_failure(conkeror[hook_name], arguments);
140     }
143 function simple_local_hook_definer(extra_doc_string) {
144     return function (hook_name, hook_type, doc_string) {
145         initialize_hook(hook_simple_local_prototype, hook_name, hook_type, doc_string, extra_doc_string);
146     };
149 /* This function is called with a variable number of string arguments
150  * in addition to the first, that specify the additional hook arrays
151  * to use.  As an example: local_hook_definer("buffer", "buffer", "buffer.window")
152  */
153 function local_hook_definer(prop_name, extra_doc_string) {
154     var prototype = {
155         run: function(x) {
156             var hook_name = this.hook_name;
157             if (hook_name in x) run_hooks(x[hook_name], arguments);
158             if (hook_name in x[prop_name]) run_hooks(x[prop_name][hook_name], arguments);
159             run_hooks(this, arguments);
160         },
161         run_until_success: function (x) {
162             var hook_name = this.hook_name;
163             if ((hook_name in x) && run_hooks_until_success(x[hook_name], arguments)) return true;
164             if ((hook_name in x[prop_name]) && run_hooks_until_success(x[prop_name][hook_name], arguments)) return true;
165             return run_hooks_until_success(conkeror[hook_name], arguments);
166         },
167         run_until_failure: function (x) {
168             var hook_name = this.hook_name;
169             if ((hook_name in x) && !run_hooks_until_success(x[hook_name], arguments)) return false;
170             if ((hook_name in x[prop_name]) && !run_hooks_until_success(x[prop_name][hook_name], arguments)) return false;
171             return run_hooks_until_failure(conkeror[hook_name], arguments);
172         }
173     };
174     return function (hook_name, hook_type, doc_string) {
175         initialize_hook(prototype, hook_name, hook_type, doc_string, extra_doc_string);
176     };
179 function remove_hook(hook_name, func)
181     var hook = this[hook_name];
182     var index;
183     if (hook && (index = hook.indexOf(func)) != -1)
184         hook.splice(index, 1);