You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.js 4.0KB

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