# JavaScript Hooker Monkey-patch (hook) functions for debugging and stuff. ## Getting Started This code should work just fine in Node.js: First, install the module with: `npm install hooker` ```javascript var hooker = require('hooker'); hooker.hook(Math, "max", function() { console.log(arguments.length + " arguments passed"); }); Math.max(5, 6, 7) // logs: "3 arguments passed", returns 7 ``` Or in the browser: ```html ``` In the browser, you can attach Hooker's methods to any object. ```html ``` ## Documentation ### hooker.hook Monkey-patch (hook) one or more methods of an object. #### Signature: `hooker.hook(object, [ props, ] [options | prehookFunction])` #### `props` The optional `props` argument can be a method name, array of method names or null. If null (or omitted), all enumerable methods of `object` will be hooked. #### `options` * `pre` - (Function) a pre-hook function to be executed before the original function. Arguments passed into the method will be passed into the pre-hook function as well. * `post` - (Function) a post-hook function to be executed after the original function. The original function's result is passed into the post-hook function as its first argument, followed by the method arguments. * `once` - (Boolean) if true, auto-unhook the function after the first execution. * `passName` - (Boolean) if true, pass the name of the method into the pre-hook function as its first arg (preceding all other arguments), and into the post-hook function as the second arg (after result but preceding all other arguments). #### Returns: An array of hooked method names. ### hooker.unhook Un-monkey-patch (unhook) one or more methods of an object. #### Signature: `hooker.unhook(object [, props ])` #### `props` The optional `props` argument can be a method name, array of method names or null. If null (or omitted), all methods of `object` will be unhooked. #### Returns: An array of unhooked method names. ### hooker.orig Get a reference to the original method from a hooked function. #### Signature: `hooker.orig(object, props)` ### hooker.override When a pre- or post-hook returns the result of this function, the value passed will be used in place of the original function's return value. Any post-hook override value will take precedence over a pre-hook override value. #### Signature: `hooker.override(value)` ### hooker.preempt When a pre-hook returns the result of this function, the value passed will be used in place of the original function's return value, and the original function will NOT be executed. #### Signature: `hooker.preempt(value)` ### hooker.filter When a pre-hook returns the result of this function, the context and arguments passed will be applied into the original function. #### Signature: `hooker.filter(context, arguments)` ## Examples See the unit tests for more examples. ```javascript var hooker = require('hooker'); // Simple logging. hooker.hook(Math, "max", function() { console.log(arguments.length + " arguments passed"); }); Math.max(5, 6, 7) // logs: "3 arguments passed", returns 7 hooker.unhook(Math, "max"); // (This is assumed between all further examples) Math.max(5, 6, 7) // 7 // Returning hooker.override(value) overrides the original value. hooker.hook(Math, "max", function() { if (arguments.length === 0) { return hooker.override(9000); } }); Math.max(5, 6, 7) // 7 Math.max() // 9000 // Auto-unhook after one execution. hooker.hook(Math, "max", { once: true, pre: function() { console.log("Init something here"); } }); Math.max(5, 6, 7) // logs: "Init something here", returns 7 Math.max(5, 6, 7) // 7 // Filter `this` and arguments through a pre-hook function. hooker.hook(Math, "max", { pre: function() { var args = [].map.call(arguments, function(num) { return num * 2; }); return hooker.filter(this, args); // thisValue, arguments } }); Math.max(5, 6, 7) // 14 // Modify the original function's result with a post-hook function. hooker.hook(Math, "max", { post: function(result) { return hooker.override(result * 100); } }); Math.max(5, 6, 7) // 700 // Hook every Math method. Note: if Math's methods were enumerable, the second // argument could be omitted. Since they aren't, an array of properties to hook // must be explicitly passed. Non-method properties will be skipped. // See a more generic example here: http://bit.ly/vvJlrS hooker.hook(Math, Object.getOwnPropertyNames(Math), { passName: true, pre: function(name) { console.log("=> Math." + name, [].slice.call(arguments, 1)); }, post: function(result, name) { console.log("<= Math." + name, result); } }); var result = Math.max(5, 6, 7); // => Math.max [ 5, 6, 7 ] // <= Math.max 7 result // 7 result = Math.ceil(3.456); // => Math.ceil [ 3.456 ] // <= Math.ceil 4 result // 4 ``` ## Contributing In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using [grunt](https://github.com/cowboy/grunt). _Also, please don't edit files in the "dist" subdirectory as they are generated via grunt. You'll find source code in the "lib" subdirectory!_ ## Release History 2012/01/09 - v0.2.3 - First official release. ## License Copyright (c) 2012 "Cowboy" Ben Alman Licensed under the MIT license.