2 /* Adds the specified function to the specified hook. To add a local
3 * hook, invoke this function as: add_hook.call(context, hook_name, ...).
4 * Note: hook_name must be a string */
5 function add_hook(hook_name, func, prepend, avoid_duplicates)
9 var hook = this[hook_name];
11 if (avoid_duplicates && hook.indexOf(func) != -1)
22 * Call every function in the array `hook' with the remaining
23 * arguments of this function. Note: This should only be used by
24 * define_hook and friends to define hook.run(...) functions. Hooks
25 * should always be run by calling hook.run(...).
27 function run_hooks(hook, args)
31 for (let i = 0; i < hook.length; ++i)
32 hook[i].apply (null, Array.prototype.slice.call(args));
35 function run_hooks_until_success(hook, args)
39 for (let i = 0; i < hook.length; ++i)
40 if (hook[i].apply (null, Array.prototype.slice.call(args)))
45 function run_hooks_until_failure(hook, args)
49 for (let i = 0; i < hook.length; ++i)
50 if (!hook[i].apply (null, Array.prototype.slice.call(args)))
55 var hook_type_doc_strings = [
57 "Each hook function added is run in sequence.",
58 /* RUN_HOOK_UNTIL_SUCCESS */
59 "Only boolean-valued hook functions may be added. Each hook function added is run in sequence until a value that conerts to true is returned.",
60 /* RUN_HOOK_UNTIL_FAILURE */
61 "Only boolean-valued hook functions may be added. Each hook function added is run in sequence until a value that conerts to false is returned."];
64 /* This should only be used by define_hook functions */
65 function initialize_hook(prototype, hook_name, hook_type, doc_string, extra_doc_string)
67 var h = this[hook_name];
69 h = this[hook_name] = [];
70 if (hook_type == null)
74 h.run = prototype.run;
76 case RUN_HOOK_UNTIL_SUCCESS:
77 h.run = prototype.run_until_success;
79 case RUN_HOOK_UNTIL_FAILURE:
80 h.run = prototype.run_until_failure;
83 h.hook_type = hook_type;
84 h.hook_name = hook_name;
86 (doc_string? doc_string + "\n" : "") +
87 hook_type_doc_strings[hook_type] +
88 (extra_doc_string? "\n" + extra_doc_string : "");
89 h.source_code_reference = get_caller_source_code_reference(1);
93 var hook_global_prototype = {
95 run_hooks(this, arguments);
97 run_until_success: function() {
98 return run_hooks_until_success(this, arguments);
100 run_until_failure: function() {
101 return run_hooks_until_failure(this, arguments);
106 const RUN_HOOK_UNTIL_SUCCESS = 1;
107 const RUN_HOOK_UNTIL_FAILURE = 2;
109 function define_hook(hook_name, hook_type, doc_string)
111 initialize_hook(hook_global_prototype, hook_name, hook_type, doc_string);
114 var hook_simple_local_prototype = {
116 var hook_name = this.hook_name;
117 if (hook_name in x) run_hooks(x[hook_name], arguments);
118 run_hooks(this, arguments);
120 run_until_success: function (x) {
121 var hook_name = this.hook_name;
122 if ((hook_name in x) && run_hooks_until_success(x[hook_name], arguments)) return true;
123 return run_hooks_until_success(conkeror[hook_name], arguments);
125 run_until_failure: function (x) {
126 var hook_name = this.hook_name;
127 if ((hook_name in x) && !run_hooks_until_success(x[hook_name], arguments)) return false;
128 return run_hooks_until_failure(conkeror[hook_name], arguments);
132 function simple_local_hook_definer(extra_doc_string) {
133 return function (hook_name, hook_type, doc_string) {
134 initialize_hook(hook_simple_local_prototype, hook_name, hook_type, doc_string, extra_doc_string);
138 /* This function is called with a variable number of string arguments
139 * in addition to the first, that specify the additional hook arrays
140 * to use. As an example: local_hook_definer("buffer", "buffer", "buffer.window")
142 function local_hook_definer(prop_name, extra_doc_string) {
145 var hook_name = this.hook_name;
146 if (hook_name in x) run_hooks(x[hook_name], arguments);
147 if (hook_name in x[prop_name]) run_hooks(x[prop_name][hook_name], arguments);
148 run_hooks(this, arguments);
150 run_until_success: function (x) {
151 var hook_name = this.hook_name;
152 if ((hook_name in x) && run_hooks_until_success(x[hook_name], arguments)) return true;
153 if ((hook_name in x[prop_name]) && run_hooks_until_success(x[prop_name][hook_name], arguments)) return true;
154 return run_hooks_until_success(conkeror[hook_name], arguments);
156 run_until_failure: function (x) {
157 var hook_name = this.hook_name;
158 if ((hook_name in x) && !run_hooks_until_success(x[hook_name], arguments)) return false;
159 if ((hook_name in x[prop_name]) && !run_hooks_until_success(x[prop_name][hook_name], arguments)) return false;
160 return run_hooks_until_failure(conkeror[hook_name], arguments);
163 return function (hook_name, hook_type, doc_string) {
164 initialize_hook(prototype, hook_name, hook_type, doc_string, extra_doc_string);
168 function remove_hook(hook_name, func)
170 var hook = this[hook_name];
172 if (hook && (index = hook.indexOf(func)) != -1)
173 hook.splice(index, 1);