index.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. var indexOf = require('indexof');
  2. var Object_keys = function (obj) {
  3. if (Object.keys) return Object.keys(obj)
  4. else {
  5. var res = [];
  6. for (var key in obj) res.push(key)
  7. return res;
  8. }
  9. };
  10. var forEach = function (xs, fn) {
  11. if (xs.forEach) return xs.forEach(fn)
  12. else for (var i = 0; i < xs.length; i++) {
  13. fn(xs[i], i, xs);
  14. }
  15. };
  16. var defineProp = (function() {
  17. try {
  18. Object.defineProperty({}, '_', {});
  19. return function(obj, name, value) {
  20. Object.defineProperty(obj, name, {
  21. writable: true,
  22. enumerable: false,
  23. configurable: true,
  24. value: value
  25. })
  26. };
  27. } catch(e) {
  28. return function(obj, name, value) {
  29. obj[name] = value;
  30. };
  31. }
  32. }());
  33. var globals = ['Array', 'Boolean', 'Date', 'Error', 'EvalError', 'Function',
  34. 'Infinity', 'JSON', 'Math', 'NaN', 'Number', 'Object', 'RangeError',
  35. 'ReferenceError', 'RegExp', 'String', 'SyntaxError', 'TypeError', 'URIError',
  36. 'decodeURI', 'decodeURIComponent', 'encodeURI', 'encodeURIComponent', 'escape',
  37. 'eval', 'isFinite', 'isNaN', 'parseFloat', 'parseInt', 'undefined', 'unescape'];
  38. function Context() {}
  39. Context.prototype = {};
  40. var Script = exports.Script = function NodeScript (code) {
  41. if (!(this instanceof Script)) return new Script(code);
  42. this.code = code;
  43. };
  44. Script.prototype.runInContext = function (context) {
  45. if (!(context instanceof Context)) {
  46. throw new TypeError("needs a 'context' argument.");
  47. }
  48. var iframe = document.createElement('iframe');
  49. if (!iframe.style) iframe.style = {};
  50. iframe.style.display = 'none';
  51. document.body.appendChild(iframe);
  52. var win = iframe.contentWindow;
  53. var wEval = win.eval, wExecScript = win.execScript;
  54. if (!wEval && wExecScript) {
  55. // win.eval() magically appears when this is called in IE:
  56. wExecScript.call(win, 'null');
  57. wEval = win.eval;
  58. }
  59. forEach(Object_keys(context), function (key) {
  60. win[key] = context[key];
  61. });
  62. forEach(globals, function (key) {
  63. if (context[key]) {
  64. win[key] = context[key];
  65. }
  66. });
  67. var winKeys = Object_keys(win);
  68. var res = wEval.call(win, this.code);
  69. forEach(Object_keys(win), function (key) {
  70. // Avoid copying circular objects like `top` and `window` by only
  71. // updating existing context properties or new properties in the `win`
  72. // that was only introduced after the eval.
  73. if (key in context || indexOf(winKeys, key) === -1) {
  74. context[key] = win[key];
  75. }
  76. });
  77. forEach(globals, function (key) {
  78. if (!(key in context)) {
  79. defineProp(context, key, win[key]);
  80. }
  81. });
  82. document.body.removeChild(iframe);
  83. return res;
  84. };
  85. Script.prototype.runInThisContext = function () {
  86. return eval(this.code); // maybe...
  87. };
  88. Script.prototype.runInNewContext = function (context) {
  89. var ctx = Script.createContext(context);
  90. var res = this.runInContext(ctx);
  91. forEach(Object_keys(ctx), function (key) {
  92. context[key] = ctx[key];
  93. });
  94. return res;
  95. };
  96. forEach(Object_keys(Script.prototype), function (name) {
  97. exports[name] = Script[name] = function (code) {
  98. var s = Script(code);
  99. return s[name].apply(s, [].slice.call(arguments, 1));
  100. };
  101. });
  102. exports.createScript = function (code) {
  103. return exports.Script(code);
  104. };
  105. exports.createContext = Script.createContext = function (context) {
  106. var copy = new Context();
  107. if(typeof context === 'object') {
  108. forEach(Object_keys(context), function (key) {
  109. copy[key] = context[key];
  110. });
  111. }
  112. return copy;
  113. };