vm.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /*
  2. from https://github.com/substack/vm-browserify/blob/bfd7c5f59edec856dc7efe0b77a4f6b2fa20f226/index.js
  3. MIT license no Copyright holder mentioned
  4. */
  5. function Object_keys(obj) {
  6. if (Object.keys) return Object.keys(obj)
  7. else {
  8. var res = [];
  9. for (var key in obj) res.push(key)
  10. return res;
  11. }
  12. }
  13. function forEach(xs, fn) {
  14. if (xs.forEach) return xs.forEach(fn)
  15. else
  16. for (var i = 0; i < xs.length; i++) {
  17. fn(xs[i], i, xs);
  18. }
  19. }
  20. var _defineProp;
  21. function defineProp(obj, name, value) {
  22. if (typeof _defineProp !== 'function') {
  23. _defineProp = createDefineProp;
  24. }
  25. _defineProp(obj, name, value);
  26. }
  27. function createDefineProp() {
  28. try {
  29. Object.defineProperty({}, '_', {});
  30. return function(obj, name, value) {
  31. Object.defineProperty(obj, name, {
  32. writable: true,
  33. enumerable: false,
  34. configurable: true,
  35. value: value
  36. })
  37. };
  38. } catch (e) {
  39. return function(obj, name, value) {
  40. obj[name] = value;
  41. };
  42. }
  43. }
  44. var globals = ['Array', 'Boolean', 'Date', 'Error', 'EvalError', 'Function',
  45. 'Infinity', 'JSON', 'Math', 'NaN', 'Number', 'Object', 'RangeError',
  46. 'ReferenceError', 'RegExp', 'String', 'SyntaxError', 'TypeError', 'URIError',
  47. 'decodeURI', 'decodeURIComponent', 'encodeURI', 'encodeURIComponent', 'escape',
  48. 'eval', 'isFinite', 'isNaN', 'parseFloat', 'parseInt', 'undefined', 'unescape'
  49. ];
  50. function Context() {}
  51. Context.prototype = {};
  52. export function Script(code) {
  53. if (!(this instanceof Script)) return new Script(code);
  54. this.code = code;
  55. }
  56. function otherRunInContext(code, context) {
  57. var args = Object_keys(global);
  58. args.push('with (this.__ctx__){return eval(this.__code__)}');
  59. var fn = Function.apply(null, args);
  60. return fn.apply({
  61. __code__: code,
  62. __ctx__: context
  63. });
  64. }
  65. Script.prototype.runInContext = function(context) {
  66. if (!(context instanceof Context)) {
  67. throw new TypeError('needs a \'context\' argument.');
  68. }
  69. if (global.document) {
  70. var iframe = global.document.createElement('iframe');
  71. if (!iframe.style) iframe.style = {};
  72. iframe.style.display = 'none';
  73. global.document.body.appendChild(iframe);
  74. var win = iframe.contentWindow;
  75. var wEval = win.eval,
  76. wExecScript = win.execScript;
  77. if (!wEval && wExecScript) {
  78. // win.eval() magically appears when this is called in IE:
  79. wExecScript.call(win, 'null');
  80. wEval = win.eval;
  81. }
  82. forEach(Object_keys(context), function(key) {
  83. win[key] = context[key];
  84. });
  85. forEach(globals, function(key) {
  86. if (context[key]) {
  87. win[key] = context[key];
  88. }
  89. });
  90. var winKeys = Object_keys(win);
  91. var res = wEval.call(win, this.code);
  92. forEach(Object_keys(win), function(key) {
  93. // Avoid copying circular objects like `top` and `window` by only
  94. // updating existing context properties or new properties in the `win`
  95. // that was only introduced after the eval.
  96. if (key in context || indexOf(winKeys, key) === -1) {
  97. context[key] = win[key];
  98. }
  99. });
  100. forEach(globals, function(key) {
  101. if (!(key in context)) {
  102. defineProp(context, key, win[key]);
  103. }
  104. });
  105. global.document.body.removeChild(iframe);
  106. return res;
  107. }
  108. return otherRunInContext(this.code, context);
  109. };
  110. Script.prototype.runInThisContext = function() {
  111. var fn = new Function('code', 'return eval(code);');
  112. return fn.call(global, this.code); // maybe...
  113. };
  114. Script.prototype.runInNewContext = function(context) {
  115. var ctx = createContext(context);
  116. var res = this.runInContext(ctx);
  117. if (context) {
  118. forEach(Object_keys(ctx), function(key) {
  119. context[key] = ctx[key];
  120. });
  121. }
  122. return res;
  123. };
  124. export function createScript(code) {
  125. return new Script(code);
  126. }
  127. export function createContext(context) {
  128. if (isContext(context)) {
  129. return context;
  130. }
  131. var copy = new Context();
  132. if (typeof context === 'object') {
  133. forEach(Object_keys(context), function(key) {
  134. copy[key] = context[key];
  135. });
  136. }
  137. return copy;
  138. }
  139. export function runInContext(code, contextifiedSandbox, options) {
  140. var script = new Script(code, options);
  141. return script.runInContext(contextifiedSandbox, options);
  142. }
  143. export function runInThisContext(code, options) {
  144. var script = new Script(code, options);
  145. return script.runInThisContext(options);
  146. }
  147. export function isContext(context) {
  148. return context instanceof Context;
  149. }
  150. export function runInNewContext(code, sandbox, options) {
  151. var script = new Script(code, options);
  152. return script.runInNewContext(sandbox, options);
  153. }
  154. export default {
  155. runInContext: runInContext,
  156. isContext: isContext,
  157. createContext: createContext,
  158. createScript: createScript,
  159. Script: Script,
  160. runInThisContext: runInThisContext,
  161. runInNewContext: runInNewContext
  162. }
  163. /*
  164. from indexOf
  165. @ author tjholowaychuk
  166. @ license MIT
  167. */
  168. var _indexOf = [].indexOf;
  169. function indexOf(arr, obj){
  170. if (_indexOf) return arr.indexOf(obj);
  171. for (var i = 0; i < arr.length; ++i) {
  172. if (arr[i] === obj) return i;
  173. }
  174. return -1;
  175. }