GM 2 port - Function Override Helper

Not yet.

此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.gf.qytechs.cn/scripts/2599/184155/GM%202%20port%20-%20Function%20Override%20Helper.js

  1. // ==UserScript==
  2. // @name GM 2 port - Function Override Helper
  3. // @Description Not yet.
  4. // @namespace org.jixun.gm2.port
  5. // @version 1.0.4
  6.  
  7. // unsafeWindow required to use `exportFunction`.
  8. // @grant unsafeWindow
  9.  
  10. // @run-at document-start
  11. // ==/UserScript==
  12.  
  13. // Check if is GM 2.x
  14. if (typeof exportFunction == 'undefined') {
  15. // For GM 1.x backward compatibility, should work.
  16. var exportFunction = (function (foo, scope, defAs) {
  17. if (defAs && defAs.defineAs) {
  18. scope[defAs.defineAs] = foo;
  19. }
  20. return foo;
  21. }).bind(unsafeWindow);
  22.  
  23. // Well.. It's not going to do anything.
  24. var cloneInto = (function (obj, scope, opt) {
  25. return obj;
  26. }).bind(unsafeWindow);
  27. }
  28.  
  29. /**
  30. * unsafeObject:
  31. * Basically cloneInto but could without scope (Default: unsafeWindow)
  32. *
  33. * @param {Object} obj Object to pass through
  34. * @param {Object} scope Scope where object is going to be applied.
  35. * @param {Object} opt Options
  36. * @return {Object} A reference to the cloned object.
  37. */
  38. var unsafeObject = function (obj, scope, opt) {
  39. return cloneInto (obj, scope || unsafeWindow, opt || {});
  40. };
  41.  
  42. /**
  43. * unsafeDefineFunction
  44. * @param {String} fooName Target name
  45. * @param {Function} foo The function to override
  46. * @param {Object} scope unsafeWindow
  47. * @return {Function} The placeholder function which has been created in the target context.
  48. */
  49. var unsafeDefineFunction = function (fooName, foo, scope) {
  50. // @throw TypeError: can't redefine non-configurable property
  51. // @throw Error: First argument must be a function
  52. return exportFunction (foo, scope || unsafeWindow, {defineAs: fooName});
  53. };
  54.  
  55. /**
  56. * unsafeOverwriteFunction
  57. * @param {Object} fooMapping {name: foo}
  58. * @param {Object} scope unsafeWindow
  59. * @param {String} scopeName Optional, required if target is not `window`.
  60. * e.g. The target is window.api.xxx, '.api' would
  61. * be the scopeName.
  62. * @return {HTML Element} Script Tag
  63. */
  64. var unsafeOverwriteFunction = function (fooMapping, scope, scopeName) {
  65. var argMapping = {}, tmpName;
  66.  
  67. // Mapping new random names.
  68. for (var x in fooMapping) {
  69. if (fooMapping.hasOwnProperty(x)) {
  70. try {
  71. tmpName = 'u_w_f_' + Math.random().toString().slice(2) + +new Date();
  72. // Export function
  73. // unsafeDefineFunction will take care of null values.
  74. unsafeDefineFunction (tmpName, fooMapping[x], scope);
  75. argMapping[x] = tmpName;
  76. } catch (e) {
  77. console.error ('Error at `unsafeOverwrite`:', e);
  78. }
  79. }
  80. }
  81.  
  82. var tmpScript = document.createElement ('script');
  83. tmpScript.textContent = ';('+ (function (j, x) {
  84. for (x in j)
  85. if (j.hasOwnProperty(x))
  86. // Map everything.
  87. // If Object with custom function / Function
  88. // passed in it will throw CloneNonReflectorsWrite.
  89. // Use unsafeOverwriteFunctionSafeProxy if you need to bypass that.
  90. // However, it's going to be slower.
  91. window/**/[x] = window/**/[j[x]];
  92. // TODO: Maybe remove this script tag after finish?
  93. }).toString().replace(/\/\*\*\//g, scopeName ? scopeName : '') +')(' + JSON.stringify(argMapping) + ');';
  94. document.head.appendChild (tmpScript);
  95.  
  96. return tmpScript;
  97. };
  98.  
  99. /**
  100. * ErrorUnsafe:
  101. * An error class for unsafeOverwriteFunctionSafeProxy.
  102. *
  103. * @param {String} name Error Name
  104. * @param {String} message Error Message
  105. */
  106. var ErrorUnsafe = function (name, message) {
  107. return cloneInto ({
  108. name: name || 'ErrorUnsafe',
  109. message: message || 'Unknown error.'
  110. }, scope || unsafeWindow);
  111. };
  112.  
  113. /**
  114. * ErrorUnsafeSuccess:
  115. * An Error Class for unsafeOverwriteFunctionSafeProxy.
  116. * Inform proxy to execute origional function with its full arguments.
  117. *
  118. * @param {[type]} message [description]
  119. * @param {[type]} scope [description]
  120. */
  121. var ErrorUnsafeSuccess = function (message, scope) {
  122. return cloneInto ({
  123. name: 'ErrorUnsafeSuccess: ProxyFinish',
  124. success: true,
  125. message: message || ''
  126. }, scope || unsafeWindow);
  127. };
  128.  
  129. /**
  130. * unsafeOverwriteFunctionSafeProxy
  131. * Similar to unsafeOverwriteFunction, but its a proxy instead.
  132. * It will strip all functions before pass in to sandboxed function.
  133. * So, it can prevent CloneNonReflectorsWrite error.
  134. *
  135. * @param {[type]} fooMapping [description]
  136. * @param {[type]} scope [description]
  137. * @param {[type]} scopeName [description]
  138. * @return {[type]} [description]
  139. */
  140. var unsafeOverwriteFunctionSafeProxy = function (fooMapping, scope, scopeName) {
  141. var argMapping = {}, tmpName;
  142.  
  143. // Mapping new random names.
  144. for (var x in fooMapping) {
  145. if (fooMapping.hasOwnProperty(x)) {
  146. try {
  147. tmpName = 'u_w_f_' + Math.random().toString().slice(2) + +new Date();
  148. // Export function
  149. // unsafeDefineFunction will take care of null values.
  150. unsafeDefineFunction (tmpName, fooMapping[x], scope);
  151. argMapping[x] = tmpName;
  152. } catch (e) {
  153. console.error ('Error at `unsafeOverwrite`:', e);
  154. alert (e);
  155. }
  156. }
  157. }
  158.  
  159. var tmpScript = document.createElement ('script');
  160. tmpScript.textContent = ';('+ (function (j, x) {
  161. for (x in j)
  162. if (j.hasOwnProperty(x)) {
  163. (function (x, bak, foo) {
  164. // Assign variable to our proxy function.
  165. window/**/[x] = function () {
  166. // console.info (arguments);
  167. for (var i = 0, y, args = []; i < arguments.length; i++) {
  168. // Array - Sure we can handle this right?
  169. if (arguments[i] instanceof Array) {
  170. args.push (arguments[i].slice());
  171. } else if (arguments[i] instanceof Object) {
  172. // Strip off all prototype functions, if possible.
  173. // TODO: maybe try-catch the following line?
  174. args.push (JSON.parse(JSON.stringify (arguments[i])));
  175. } else if ('function' == typeof arguments[i]) {
  176. // Function can't be sandboxied :<
  177. args.push (null);
  178. } else {
  179. // idk... should be safe to pass through?
  180. args.push (arguments[i]);
  181. }
  182. }
  183.  
  184. try {
  185. // Try to call our function!
  186. return foo.apply(this, args);
  187. } catch (err) {
  188. // We throw this error on purpose,
  189. // if we need to do the complete callback.
  190. // If the error don'e have success flag, we'll
  191. // throw the error to console.
  192.  
  193. if (!err.success) console.error (err);
  194. return bak.apply (this, arguments);
  195. }
  196. };
  197. }) (x, window/**/[x], window/**/[j[x]]);
  198. }
  199.  
  200. // TODO: Maybe remove this script tag after finish?
  201. }).toString().replace(/\/\*\*\//g, scopeName ? scopeName : '') +')(' + JSON.stringify(argMapping) + ');';
  202. document.head.appendChild (tmpScript);
  203.  
  204. return tmpScript;
  205. };
  206.  
  207. /**
  208. * Execute function anonymously
  209. * @param {Function} foo
  210. * @param {Any} Any arguments to be passed in.
  211. * @return {ScriptNode}
  212. */
  213. var unsafeExec = function (foo) {
  214. var tmpScript = document.createElement ('script');
  215.  
  216. // Now supports arguments!
  217. tmpScript.textContent =
  218. ';(' + foo + ').apply (null, ' +
  219. JSON.stringify([].slice.call(arguments, 1)) + ');';
  220.  
  221. document.head.appendChild (tmpScript);
  222. return tmpScript;
  223. };

QingJ © 2025

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