diff --git a/lib/coffee-script.js b/lib/coffee-script.js index 04620e1862..eb6b2ae78d 100755 --- a/lib/coffee-script.js +++ b/lib/coffee-script.js @@ -1,8 +1,10 @@ (function() { - var Lexer, RESERVED, compile, fs, lexer, parser, path, vm, _ref; + var Lexer, Module, RESERVED, Script, compile, fs, lexer, parser, path, _ref; + var __hasProp = Object.prototype.hasOwnProperty; fs = require('fs'); path = require('path'); - vm = require('vm'); + Script = require('vm').Script; + Module = require('module'); _ref = require('./lexer'), Lexer = _ref.Lexer, RESERVED = _ref.RESERVED; parser = require('./parser').parser; if (require.extensions) { @@ -45,7 +47,7 @@ } }; exports.run = function(code, options) { - var Module, mainModule; + var mainModule; mainModule = require.main; mainModule.filename = process.argv[1] = options.filename ? fs.realpathSync(options.filename) : '.'; mainModule.moduleCache && (mainModule.moduleCache = {}); @@ -60,39 +62,59 @@ } }; exports.eval = function(code, options) { - var g, js, k, o, sandbox, v, _i, _len, _ref2; + var js, k, o, r, sandbox, v, _, _i, _len, _module, _ref2, _ref3, _require; if (options == null) { options = {}; } if (!(code = code.trim())) { return; } - sandbox = options.sandbox; - if (!sandbox) { - sandbox = { - require: require, - module: { - exports: {} + sandbox = Script.createContext(); + sandbox.global = sandbox.root = sandbox.GLOBAL = sandbox; + if (options.sandbox != null) { + if (options.sandbox instanceof sandbox.constructor) { + sandbox = options.sandbox; + } else { + _ref2 = options.sandbox; + for (k in _ref2) { + if (!__hasProp.call(_ref2, k)) continue; + v = _ref2[k]; + sandbox[k] = v; } - }; - _ref2 = Object.getOwnPropertyNames(global); - for (_i = 0, _len = _ref2.length; _i < _len; _i++) { - g = _ref2[_i]; - sandbox[g] = global[g]; } - sandbox.global = sandbox; - sandbox.global.global = sandbox.global.root = sandbox.global.GLOBAL = sandbox; } sandbox.__filename = options.filename || 'eval'; sandbox.__dirname = path.dirname(sandbox.__filename); + if (!(sandbox.module || sandbox.require)) { + Module = require('module'); + sandbox.module = _module = new Module(options.modulename || 'eval'); + sandbox.require = _require = function(path) { + return Module._load(path, _module); + }; + _module.filename = sandbox.__filename; + _ref3 = Object.getOwnPropertyNames(require); + for (_i = 0, _len = _ref3.length; _i < _len; _i++) { + r = _ref3[_i]; + _require[r] = require[r]; + } + _require.paths = _module.paths = Module._nodeModulePaths(process.cwd()); + _require.resolve = function(request) { + return Module._resolveFilename(request, _module); + }; + } o = {}; for (k in options) { + if (!__hasProp.call(options, k)) continue; v = options[k]; o[k] = v; } o.bare = true; - js = compile("_=(" + code + "\n)", o); - return vm.runInNewContext(js, sandbox, sandbox.__filename); + js = compile("(" + code + "\n)", o); + _ = Script.runInContext(js, sandbox); + if (_ != null) { + sandbox._ = _; + } + return _; }; lexer = new Lexer; parser.lexer = { diff --git a/lib/repl.js b/lib/repl.js index 5f468bc641..f77314be5e 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -1,10 +1,11 @@ (function() { - var ACCESSOR, CoffeeScript, SIMPLEVAR, Script, autocomplete, backlog, completeAttribute, completeVariable, enableColours, error, getCompletions, getPropertyNames, inspect, readline, repl, run, stdin, stdout; + var ACCESSOR, CoffeeScript, Module, SIMPLEVAR, Script, autocomplete, backlog, completeAttribute, completeVariable, enableColours, error, getCompletions, getPropertyNames, inspect, readline, repl, run, stdin, stdout; var __hasProp = Object.prototype.hasOwnProperty; CoffeeScript = require('./coffee-script'); readline = require('readline'); inspect = require('util').inspect; Script = require('vm').Script; + Module = require('module'); enableColours = false; if (process.platform !== 'win32') { enableColours = !process.env.NODE_DISABLE_COLORS; @@ -16,20 +17,9 @@ }; backlog = ''; run = (function() { - var g, sandbox, _i, _len, _ref; - sandbox = { - require: require, - module: { - exports: {} - } - }; - _ref = Object.getOwnPropertyNames(global); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - g = _ref[_i]; - sandbox[g] = global[g]; - } - sandbox.global = sandbox; - sandbox.global.global = sandbox.global.root = sandbox.global.GLOBAL = sandbox; + var sandbox; + sandbox = Script.createContext(); + sandbox.global = sandbox.root = sandbox.GLOBAL = sandbox; return function(buffer) { var code, val; code = backlog += '\n' + buffer.toString(); @@ -40,8 +30,8 @@ try { val = CoffeeScript.eval(code, { sandbox: sandbox, - bare: true, - filename: 'repl' + filename: 'repl', + modulename: 'repl' }); if (val !== void 0) { process.stdout.write(inspect(val, false, 2, enableColours) + '\n'); diff --git a/src/coffee-script.coffee b/src/coffee-script.coffee index 9c6c2e6d9a..9fb30d50b6 100755 --- a/src/coffee-script.coffee +++ b/src/coffee-script.coffee @@ -8,7 +8,8 @@ fs = require 'fs' path = require 'path' -vm = require 'vm' +{Script} = require 'vm' +Module = require 'module' {Lexer,RESERVED} = require './lexer' {parser} = require './parser' @@ -78,20 +79,32 @@ exports.run = (code, options) -> # The CoffeeScript REPL uses this to run the input. exports.eval = (code, options = {}) -> return unless code = code.trim() - sandbox = options.sandbox - unless sandbox - sandbox = - require: require - module : { exports: {} } - sandbox[g] = global[g] for g in Object.getOwnPropertyNames global - sandbox.global = sandbox - sandbox.global.global = sandbox.global.root = sandbox.global.GLOBAL = sandbox + sandbox = Script.createContext() + sandbox.global = sandbox.root = sandbox.GLOBAL = sandbox + if options.sandbox? + if options.sandbox instanceof sandbox.constructor + sandbox = options.sandbox + else + sandbox[k] = v for own k, v of options.sandbox sandbox.__filename = options.filename || 'eval' sandbox.__dirname = path.dirname sandbox.__filename - o = {}; o[k] = v for k, v of options + # define module/require only if they chose not to specify their own + unless sandbox.module or sandbox.require + Module = require 'module' + sandbox.module = _module = new Module(options.modulename || 'eval') + sandbox.require = _require = (path) -> Module._load path, _module + _module.filename = sandbox.__filename + _require[r] = require[r] for r in Object.getOwnPropertyNames require + # use the same hack node currently uses for their own REPL + _require.paths = _module.paths = Module._nodeModulePaths process.cwd() + _require.resolve = (request) -> Module._resolveFilename request, _module + o = {} + o[k] = v for own k, v of options o.bare = on # ensure return value - js = compile "_=(#{code}\n)", o - vm.runInNewContext js, sandbox, sandbox.__filename + js = compile "(#{code}\n)", o + _ = Script.runInContext js, sandbox + sandbox._ = _ if _? + _ # Instantiate a Lexer for our use here. lexer = new Lexer diff --git a/src/repl.coffee b/src/repl.coffee index 1e42e0378d..7e0bf3d398 100644 --- a/src/repl.coffee +++ b/src/repl.coffee @@ -9,6 +9,7 @@ CoffeeScript = require './coffee-script' readline = require 'readline' {inspect} = require 'util' {Script} = require 'vm' +Module = require 'module' # REPL Setup @@ -32,12 +33,8 @@ backlog = '' # Attempt to evaluate the command. If there's an exception, print it out instead # of exiting. run = do -> - sandbox = - require: require - module : { exports: {} } - sandbox[g] = global[g] for g in Object.getOwnPropertyNames global - sandbox.global = sandbox - sandbox.global.global = sandbox.global.root = sandbox.global.GLOBAL = sandbox + sandbox = Script.createContext() + sandbox.global = sandbox.root = sandbox.GLOBAL = sandbox (buffer) -> code = backlog += '\n' + buffer.toString() if code[code.length - 1] is '\\' @@ -46,8 +43,8 @@ run = do -> try val = CoffeeScript.eval code, { sandbox, - bare: on, filename: 'repl' + modulename: 'repl' } unless val is undefined process.stdout.write inspect(val, no, 2, enableColours) + '\n'