2 * (C) Copyright 2007-2008 Jeremy Maitin-Shepard
4 * Use, modification, and distribution are subject to the terms specified in the
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)
15 var hook = this[hook_name];
17 if (avoid_duplicates && hook.indexOf(func) != -1)
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(...).
33 function run_hooks(hook, args)
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)
45 for (let i = 0; i < hook.length; ++i)
46 if (hook[i].apply (null, Array.prototype.slice.call(args)))
51 function run_hooks_until_failure(hook, args)
55 for (let i = 0; i < hook.length; ++i)
56 if (!hook[i].apply (null, Array.prototype.slice.call(args)))
61 var hook_type_doc_strings = [
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];
80 h = this[hook_name] = [];
81 if (hook_type == null)
85 h.run = prototype.run;
87 case RUN_HOOK_UNTIL_SUCCESS:
88 h.run = prototype.run_until_success;
90 case RUN_HOOK_UNTIL_FAILURE:
91 h.run = prototype.run_until_failure;
94 h.hook_type = hook_type;
95 h.hook_name = hook_name;
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);
104 var hook_global_prototype = {
106 run_hooks(this, arguments);
108 run_until_success: function() {
109 return run_hooks_until_success(this, arguments);
111 run_until_failure: function() {
112 return run_hooks_until_failure(this, arguments);
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 = {
127 var hook_name = this.hook_name;
128 if (hook_name in x) run_hooks(x[hook_name], arguments);
129 run_hooks(this, arguments);
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);
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);
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);
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")
153 function local_hook_definer(prop_name, extra_doc_string) {
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);
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);
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);
174 return function (hook_name, hook_type, doc_string) {
175 initialize_hook(prototype, hook_name, hook_type, doc_string, extra_doc_string);
179 function remove_hook(hook_name, func)
181 var hook = this[hook_name];
183 if (hook && (index = hook.indexOf(func)) != -1)
184 hook.splice(index, 1);