Hooks

A JavaScript hook/reply ultility

当前为 2018-06-06 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.gf.qytechs.cn/scripts/18715/603566/Hooks.js

  1. // ==UserScript==
  2. // @name Hooks
  3. // @namespace xuyiming.open@outlook.com
  4. // @description A JavaScript hook/reply ultility
  5. // @author xymopen
  6. // @version 1.1.3
  7. // @grant none
  8. // @license BSD 2-Clause
  9. // @homepageURL https://github.com/xymopen/JS_Misc/blob/master/Hooks.js
  10. // @updateURL https://raw.githubusercontent.com/xymopen/JS_Misc/master/Hooks.js
  11. // ==/UserScript==
  12.  
  13. // TODO: JsDoc
  14. // TODO: Unit test
  15.  
  16. var Hooks = ( function() {
  17. "use strict";
  18. /**
  19. * Hooks functions or properties, getters/setters
  20. * and methods of an object you are intrested in
  21. */
  22. var Hooks = {
  23. /**
  24. * hook a function
  25. * @function apply
  26. * @param {function} target - a function to be hook
  27. * @param {onApply} onApply - the hook
  28. */
  29. "apply": function apply( target, onApply ) {
  30. if ( "function" === typeof target && "function" === typeof onApply ) {
  31. return function() {
  32. return onApply.call( this, target, this, arguments );
  33. };
  34. } else {
  35. throw new TypeError();
  36. }
  37. },
  38. /**
  39. * @callback onApply the hook
  40. * @param {function} target - the function hooked
  41. * @param {object|undefined} thisArg - #this reference
  42. * @param {arguments} argv - the arguments pass to the target
  43. */
  44.  
  45. /**
  46. * hook a property of an object
  47. * @function property
  48. * @param {object} target - an object having or to have the property to be hooked
  49. * @param {string} propertyName - the name of the property to be hooked
  50. * @param {onGet} onGet - the hook call when about to get the property
  51. * @param {onSet} onSet - the hook call when about to set the property
  52. */
  53. "property": function property( target, propertyName, onGet, onSet ) {
  54. var descriptor, oldValue;
  55.  
  56. if ( Object.prototype.hasOwnProperty.call( target, propertyName ) ) {
  57. descriptor = Object.getOwnPropertyDescriptor( target, propertyName );
  58.  
  59. if ( Object.prototype.hasOwnProperty.call( descriptor, "value" ) ) {
  60. oldValue = descriptor.value;
  61.  
  62. delete descriptor.value;
  63. delete descriptor.writable;
  64. } else if ( Object.prototype.hasOwnProperty.call( descriptor, "get" ) ) {
  65. oldValue = descriptor.get.call( target );
  66. } else {
  67. oldValue = undefined;
  68. }
  69. } else {
  70. descriptor = {
  71. "configurable": true,
  72. "enumerable": true,
  73. };
  74. oldValue = undefined;
  75. }
  76.  
  77. descriptor.get = function get() {
  78. return onGet.call( this, target, propertyName, oldValue );
  79. };
  80.  
  81. descriptor.set = function set( newValue ) {
  82. oldValue = onSet.call( this, target, propertyName, oldValue, newValue );
  83. return oldValue;
  84. };
  85.  
  86. Object.defineProperty( target, propertyName, descriptor );
  87. },
  88. /**
  89. * the hook call when about to get the property
  90. * @callback onGet
  91. * @param {object} target - the object having the property hooked
  92. * @param {string} propertyName - the name of the property hooked
  93. * @param {any} oldValue - the current value of the property
  94. */
  95.  
  96. /**
  97. * the hook call when about to set the property
  98. * @callback onSet
  99. * @param {object} target - the object having the property hooked
  100. * @param {string} propertyName - the name of the property hooked
  101. * @param {any} oldValue - the current value of the property
  102. * @param {any} newValue - the value about to be set to the property
  103. */
  104.  
  105. /**
  106. * alias of #property but fill the #onSet automatically
  107. * @function get
  108. * @param {object} target - an object having or to have the property to be hooked
  109. * @param {string} propertyName - he name of the property to be hooked
  110. * @param {onGet} onGet - the hook call when about to get the property
  111. */
  112. "get": function get( target, propertyName, onGet ) {
  113. return Hooks.property( target, propertyName, onGet, function( target, propertyName, oldValue, newValue ) {
  114. return Hooks.Reply.get( arguments );
  115. } );
  116. },
  117. /**
  118. * the hook call when about to get the property
  119. * @callback onGet
  120. * @param {object} target - the object having the property hooked
  121. * @param {string} propertyName - the name of the property hooked
  122. * @param {any} oldValue - the current value of the property
  123. */
  124.  
  125. /**
  126. * alias of #property but fill the #onGet automatically
  127. * @function set
  128. * @param {object} target - an object having or to have the property to be hooked
  129. * @param {string} propertyName - the name of the property to be hooked
  130. * @param {onSet} onSet - the hook call when about to set the property
  131. */
  132. "set": function set( target, propertyName, onSet ) {
  133. return Hooks.property( target, propertyName, function( target, propertyName, oldValue ) {
  134. return Hooks.Reply.set( arguments );
  135. }, onSet );
  136. },
  137. /**
  138. * the hook call when about to set the property
  139. * @callback onSet
  140. * @param {object} target - the object having the property hooked
  141. * @param {string} propertyName - he name of the property hooked
  142. * @param {any} oldValue - the current value of the property
  143. * @param {any} newValue - the value about to be set to the property
  144. */
  145.  
  146. /**
  147. * hook a method of an object
  148. * @function method
  149. * @param {object} target - an object having or to have the method to be hooked
  150. * @param {string} methodName - the name of the method to be hooked
  151. * @param {onApply} onApply - the hook replace the method
  152. */
  153. "method": function method( target, methodName, onApply ) {
  154. var method = target[ methodName ], descriptor;
  155. function hookMethod( method, onApply ) {
  156. return Hooks.apply( method, function( method, thisArg, argv ) {
  157. return onApply.call( this, target, methodName, method, thisArg, argv );
  158. } );
  159. };
  160. if ( "function" === typeof method ) {
  161. target[ methodName ] = hookMethod( method, onApply );
  162. } else {
  163. if ( Object.prototype.hasOwnProperty.call( target, propertyName ) ) {
  164. throw new Error( "ERR_PROPERTY_EXISTS_NOT_METHOD" );
  165. } else {
  166. Hooks.set( target, methodName, function onSet( target, propertyName, oldValue, newValue ) {
  167. Object.defineProperty( target, methodName, {
  168. "configurable": true,
  169. "enumerable": true,
  170. "value": "function" === typeof newValue ? hookMethod( newValue, onApply ) : newValue,
  171. "writable": true,
  172. } );
  173. } );
  174. }
  175. }
  176. },
  177. /**
  178. * the hook replace the method
  179. * @callback onApply
  180. * @param {object} target - the object having the method hooked
  181. * @param {string} methodName - the name of the method hooked
  182. * @param {object|undefined} thisArg - #this reference
  183. * @param {arguments} argv - the arguments pass to the method
  184. */
  185. /**
  186. * hook a getter property of an object
  187. * @function getter
  188. * @param {object} target - an object having the getter property to be hooked
  189. * @param {string} propertyName - the name of the getter property to be hooked
  190. * @param {onGetter} onGetter - the hook replace the getter
  191. */
  192. "getter": function getter( target, propertyName, onGetter ) {
  193. return trap( target, propertyName, onGetter, "get", "ERR_NOT_A_GETTER" );
  194. },
  195. /**
  196. * the hook replace the getter
  197. * @callback onSetter
  198. * @param {object} target - the object having the getter property hooked
  199. * @param {string} propertyName - he name of the getter property hooked
  200. * @param {function} getter - the getter replaced
  201. * @param {object|undefined} thisArg - #this reference
  202. * @param {arguments} argv - the arguments pass to the getter, should be #undefined
  203. */
  204.  
  205. /**
  206. * hook a setter property of an object
  207. * @function setter
  208. * @param {object} target - an object having the setter property to be hooked
  209. * @param {string} propertyName - the name of the setter property to be hooked
  210. * @param {onSetter} onSetter - the hook replace the setter
  211. */
  212. "setter": function setter( target, propertyName, onSetter ) {
  213. return trap( target, propertyName, onSetter, "set", "ERR_NOT_A_SETTER" );
  214. },
  215. /**
  216. * the hook replace the setter
  217. * @callback onSetter
  218. * @param {object} target - the object having the setter property hooked
  219. * @param {string} propertyName - he name of the setter property hooked
  220. * @param {function} setter - the setter replaced
  221. * @param {object|undefined} thisArg - #this reference
  222. * @param {arguments} argv - the arguments pass to the setter, should be a right value
  223. */
  224. };
  225. var Reply = {
  226. "apply": function apply( param ) {
  227. var target = param[ 0 ],
  228. thisArg = param[ 1 ],
  229. argv = param[ 2 ];
  230. return target.apply( thisArg, argv );
  231. },
  232. "get": function( param ) {
  233. var target = param[ 0 ],
  234. propertyName = param[ 1 ],
  235. oldValue = param[ 2 ],
  236. newValue = param[ 3 ];
  237. return param[ param.length - 1 ];
  238. },
  239. "getter": function( param ) {
  240. var target = param[ 0 ],
  241. propertyName = param[ 1 ],
  242. fn = param[ 2 ],
  243. thisArg = param[ 3 ],
  244. argv = param[ 4 ];
  245. return fn.apply( thisArg, argv );
  246. },
  247. "method": function method( param ) {
  248. var target = param[ 0 ],
  249. methodName = param[ 1 ],
  250. method = param[ 2 ],
  251. thisArg = param[ 3 ],
  252. argv = param[ 4 ];
  253. return method.apply( thisArg, argv );
  254. },
  255. };
  256. Reply.set = Reply.get;
  257. Reply.setter = Reply.getter;
  258. Hooks.Reply = Reply;
  259.  
  260. return Hooks;
  261. } )();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址