diff --git a/Cakefile b/Cakefile index 9df14cd1..f2ea57d6 100644 --- a/Cakefile +++ b/Cakefile @@ -1,4 +1,5 @@ fs = require 'fs' +os = require 'os' path = require 'path' _ = require 'underscore' { spawn, exec, execSync } = require 'child_process' @@ -51,14 +52,8 @@ run = (args, callback) -> buildParser = -> helpers.extend global, require 'util' require 'jison' - parser = require('./lib/coffeescript/grammar').parser.generate() - # Patch Jison’s output, until https://github.com/zaach/jison/pull/339 is accepted, - # to ensure that require('fs') is only called where it exists. - parser = parser.replace "var source = require('fs')", """ - var source = ''; - var fs = require('fs'); - if (typeof fs !== 'undefined' && fs !== null) - source = fs""" + # We don't need `moduleMain`, since the parser is unlikely to be run standalone. + parser = require('./lib/coffeescript/grammar').parser.generate(moduleMain: ->) fs.writeFileSync 'lib/coffeescript/parser.js', parser buildExceptParser = (callback) -> @@ -135,7 +130,7 @@ task 'build:browser', 'merge the built scripts into a single file for use in a b var CoffeeScript = function() { function require(path){ return require[path]; } #{code} - return require['./coffeescript']; + return require['./browser']; }(); if (typeof define === 'function' && define.amd) { @@ -368,7 +363,7 @@ task 'bench', 'quick benchmark of compilation time', -> # Run the CoffeeScript test suite. runTests = (CoffeeScript) -> - CoffeeScript.register() + CoffeeScript.register() unless global.testingBrowser startTime = Date.now() # These are attached to `global` so that they’re accessible from within @@ -440,3 +435,29 @@ task 'test:browser', 'run the test suite against the merged browser script', -> (-> eval source).call result testResults = runTests result.CoffeeScript process.exit 1 unless testResults + +task 'test:integrations', 'test the module integrated with other libraries and environments', -> + # Tools like Webpack and Browserify generate builds intended for a browser + # environment where Node modules are not available. We want to ensure that + # the CoffeeScript module as presented by the `browser` key in `package.json` + # can be built by such tools; if such a build succeeds, it verifies that no + # Node modules are required as part of the compiler (as opposed to the tests) + # and that therefore the compiler will run in a browser environment. + tmpdir = os.tmpdir() + try + buildLog = execSync "./node_modules/webpack/bin/webpack.js + --entry=./ + --output-library=CoffeeScript + --output-library-target=commonjs2 + --output-path=#{tmpdir} + --output-filename=coffeescript.js" + catch exception + console.error buildLog.toString() + throw exception + + builtCompiler = path.join tmpdir, 'coffeescript.js' + CoffeeScript = require builtCompiler + global.testingBrowser = yes + testResults = runTests CoffeeScript + fs.unlinkSync builtCompiler + process.exit 1 unless testResults diff --git a/bower.json b/bower.json index 40a15966..c3a333dd 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,7 @@ { "name": "coffeescript", "main": [ - "lib/coffeescript/coffeescript.js" + "lib/coffeescript/browser.js" ], "description": "Unfancy JavaScript", "keywords": [ diff --git a/lib/coffeescript/browser.js b/lib/coffeescript/browser.js index cf1b4654..a168726c 100644 --- a/lib/coffeescript/browser.js +++ b/lib/coffeescript/browser.js @@ -5,8 +5,6 @@ CoffeeScript = require('./coffeescript'); - CoffeeScript.require = require; - compile = CoffeeScript.compile; CoffeeScript.eval = function(code, options = {}) { @@ -22,6 +20,8 @@ return Function(compile(code, options))(); }; + module.exports = CoffeeScript; + if (typeof window === "undefined" || window === null) { return; } diff --git a/lib/coffeescript/cake.js b/lib/coffeescript/cake.js index 5ae03160..be80a50f 100644 --- a/lib/coffeescript/cake.js +++ b/lib/coffeescript/cake.js @@ -10,7 +10,7 @@ optparse = require('./optparse'); - CoffeeScript = require('./coffeescript'); + CoffeeScript = require('./'); CoffeeScript.register(); diff --git a/lib/coffeescript/coffeescript.js b/lib/coffeescript/coffeescript.js index 20521183..13664693 100644 --- a/lib/coffeescript/coffeescript.js +++ b/lib/coffeescript/coffeescript.js @@ -1,13 +1,6 @@ // Generated by CoffeeScript 2.0.0-beta1 (function() { - var Lexer, SourceMap, base64encode, compile, ext, fn1, formatSourcePosition, fs, getSourceMap, helpers, i, len, lexer, packageJson, parser, path, ref, sourceMaps, sources, vm, withPrettyErrors, - hasProp = {}.hasOwnProperty; - - fs = require('fs'); - - vm = require('vm'); - - path = require('path'); + var Lexer, SourceMap, base64encode, compile, formatSourcePosition, getSourceMap, helpers, lexer, packageJson, parser, sourceMaps, sources, withPrettyErrors; ({Lexer} = require('./lexer')); @@ -153,118 +146,8 @@ } }); - exports.run = function(code, options = {}) { - var answer, dir, mainModule, ref; - mainModule = require.main; - mainModule.filename = process.argv[1] = options.filename ? fs.realpathSync(options.filename) : ''; - mainModule.moduleCache && (mainModule.moduleCache = {}); - dir = options.filename != null ? path.dirname(fs.realpathSync(options.filename)) : fs.realpathSync('.'); - mainModule.paths = require('module')._nodeModulePaths(dir); - if (!helpers.isCoffee(mainModule.filename) || require.extensions) { - answer = compile(code, options); - code = (ref = answer.js) != null ? ref : answer; - } - return mainModule._compile(code, mainModule.filename); - }; - - exports.eval = function(code, options = {}) { - var Module, _module, _require, createContext, i, isContext, js, k, len, o, r, ref, ref1, ref2, ref3, sandbox, v; - if (!(code = code.trim())) { - return; - } - createContext = (ref = vm.Script.createContext) != null ? ref : vm.createContext; - isContext = (ref1 = vm.isContext) != null ? ref1 : function(ctx) { - return options.sandbox instanceof createContext().constructor; - }; - if (createContext) { - if (options.sandbox != null) { - if (isContext(options.sandbox)) { - sandbox = options.sandbox; - } else { - sandbox = createContext(); - ref2 = options.sandbox; - for (k in ref2) { - if (!hasProp.call(ref2, k)) continue; - v = ref2[k]; - sandbox[k] = v; - } - } - sandbox.global = sandbox.root = sandbox.GLOBAL = sandbox; - } else { - sandbox = global; - } - sandbox.__filename = options.filename || 'eval'; - sandbox.__dirname = path.dirname(sandbox.__filename); - if (!(sandbox !== global || 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, true); - }; - _module.filename = sandbox.__filename; - ref3 = Object.getOwnPropertyNames(require); - for (i = 0, len = ref3.length; i < len; i++) { - r = ref3[i]; - if (r !== 'paths' && r !== 'arguments' && r !== 'caller') { - _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, o); - if (sandbox === global) { - return vm.runInThisContext(js); - } else { - return vm.runInContext(js, sandbox); - } - }; - - exports.register = function() { - return require('./register'); - }; - - if (require.extensions) { - ref = this.FILE_EXTENSIONS; - fn1 = function(ext) { - var base; - return (base = require.extensions)[ext] != null ? base[ext] : base[ext] = function() { - throw new Error(`Use CoffeeScript.register() or require the coffeescript/register module to require ${ext} files.`); - }; - }; - for (i = 0, len = ref.length; i < len; i++) { - ext = ref[i]; - fn1(ext); - } - } - - exports._compileFile = function(filename, sourceMap = false, inlineMap = false) { - var answer, err, raw, stripped; - raw = fs.readFileSync(filename, 'utf8'); - stripped = raw.charCodeAt(0) === 0xFEFF ? raw.substring(1) : raw; - try { - answer = compile(stripped, { - filename, - sourceMap, - inlineMap, - sourceFiles: [filename], - literate: helpers.isLiterate(filename) - }); - } catch (error) { - err = error; - throw helpers.updateSyntaxError(err, stripped, filename); - } - return answer; + exports.run = exports.eval = exports.register = function() { + throw new Error('require index.coffee, not this file'); }; lexer = new Lexer; @@ -393,10 +276,10 @@ } }; frames = (function() { - var j, len1, results; + var i, len, results; results = []; - for (j = 0, len1 = stack.length; j < len1; j++) { - frame = stack[j]; + for (i = 0, len = stack.length; i < len; i++) { + frame = stack[i]; if (frame.getFunction() === exports.run) { break; } diff --git a/lib/coffeescript/command.js b/lib/coffeescript/command.js index 4a54ab45..53602cf1 100644 --- a/lib/coffeescript/command.js +++ b/lib/coffeescript/command.js @@ -11,7 +11,7 @@ optparse = require('./optparse'); - CoffeeScript = require('./coffeescript'); + CoffeeScript = require('./'); ({spawn, exec} = require('child_process')); diff --git a/lib/coffeescript/index.js b/lib/coffeescript/index.js index a7d6463d..eead5e3b 100644 --- a/lib/coffeescript/index.js +++ b/lib/coffeescript/index.js @@ -1,11 +1,134 @@ // Generated by CoffeeScript 2.0.0-beta1 (function() { - var key, ref, val; + var CoffeeScript, compile, ext, fn, fs, helpers, i, len, path, ref, vm, + hasProp = {}.hasOwnProperty; - ref = require('./coffeescript'); - for (key in ref) { - val = ref[key]; - exports[key] = val; + CoffeeScript = require('./coffeescript'); + + fs = require('fs'); + + vm = require('vm'); + + path = require('path'); + + helpers = CoffeeScript.helpers; + + compile = CoffeeScript.compile; + + CoffeeScript.run = function(code, options = {}) { + var answer, dir, mainModule, ref; + mainModule = require.main; + mainModule.filename = process.argv[1] = options.filename ? fs.realpathSync(options.filename) : ''; + mainModule.moduleCache && (mainModule.moduleCache = {}); + dir = options.filename != null ? path.dirname(fs.realpathSync(options.filename)) : fs.realpathSync('.'); + mainModule.paths = require('module')._nodeModulePaths(dir); + if (!helpers.isCoffee(mainModule.filename) || require.extensions) { + answer = compile(code, options); + code = (ref = answer.js) != null ? ref : answer; + } + return mainModule._compile(code, mainModule.filename); + }; + + CoffeeScript.eval = function(code, options = {}) { + var Module, _module, _require, createContext, i, isContext, js, k, len, o, r, ref, ref1, ref2, ref3, sandbox, v; + if (!(code = code.trim())) { + return; + } + createContext = (ref = vm.Script.createContext) != null ? ref : vm.createContext; + isContext = (ref1 = vm.isContext) != null ? ref1 : function(ctx) { + return options.sandbox instanceof createContext().constructor; + }; + if (createContext) { + if (options.sandbox != null) { + if (isContext(options.sandbox)) { + sandbox = options.sandbox; + } else { + sandbox = createContext(); + ref2 = options.sandbox; + for (k in ref2) { + if (!hasProp.call(ref2, k)) continue; + v = ref2[k]; + sandbox[k] = v; + } + } + sandbox.global = sandbox.root = sandbox.GLOBAL = sandbox; + } else { + sandbox = global; + } + sandbox.__filename = options.filename || 'eval'; + sandbox.__dirname = path.dirname(sandbox.__filename); + if (!(sandbox !== global || 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, true); + }; + _module.filename = sandbox.__filename; + ref3 = Object.getOwnPropertyNames(require); + for (i = 0, len = ref3.length; i < len; i++) { + r = ref3[i]; + if (r !== 'paths' && r !== 'arguments' && r !== 'caller') { + _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, o); + if (sandbox === global) { + return vm.runInThisContext(js); + } else { + return vm.runInContext(js, sandbox); + } + }; + + CoffeeScript.register = function() { + return require('./register'); + }; + + if (require.extensions) { + ref = CoffeeScript.FILE_EXTENSIONS; + fn = function(ext) { + var base; + return (base = require.extensions)[ext] != null ? base[ext] : base[ext] = function() { + throw new Error(`Use CoffeeScript.register() or require the coffeescript/register module to require ${ext} files.`); + }; + }; + for (i = 0, len = ref.length; i < len; i++) { + ext = ref[i]; + fn(ext); + } } + CoffeeScript._compileFile = function(filename, sourceMap = false, inlineMap = false) { + var answer, err, raw, stripped; + raw = fs.readFileSync(filename, 'utf8'); + stripped = raw.charCodeAt(0) === 0xFEFF ? raw.substring(1) : raw; + try { + answer = compile(stripped, { + filename, + sourceMap, + inlineMap, + sourceFiles: [filename], + literate: helpers.isLiterate(filename) + }); + } catch (error) { + err = error; + throw helpers.updateSyntaxError(err, stripped, filename); + } + return answer; + }; + + module.exports = CoffeeScript; + }).call(this); diff --git a/lib/coffeescript/parser.js b/lib/coffeescript/parser.js index 5a78dc31..634c77d2 100755 --- a/lib/coffeescript/parser.js +++ b/lib/coffeescript/parser.js @@ -877,17 +877,7 @@ if (typeof require !== 'undefined' && typeof exports !== 'undefined') { exports.parser = parser; exports.Parser = parser.Parser; exports.parse = function () { return parser.parse.apply(parser, arguments); }; -exports.main = function commonjsMain(args) { - if (!args[1]) { - console.log('Usage: '+args[0]+' FILE'); - process.exit(1); - } - var source = ''; - var fs = require('fs'); - if (typeof fs !== 'undefined' && fs !== null) - source = fs.readFileSync(require('path').normalize(args[1]), "utf8"); - return exports.parser.parse(source); -}; +exports.main = function () {}; if (typeof module !== 'undefined' && require.main === module) { exports.main(process.argv.slice(1)); } diff --git a/lib/coffeescript/register.js b/lib/coffeescript/register.js index 8d3d982e..9920c26d 100644 --- a/lib/coffeescript/register.js +++ b/lib/coffeescript/register.js @@ -2,7 +2,7 @@ (function() { var CoffeeScript, Module, binary, child_process, ext, findExtension, fork, helpers, i, len, loadFile, path, ref; - CoffeeScript = require('./coffeescript'); + CoffeeScript = require('./'); child_process = require('child_process'); diff --git a/lib/coffeescript/repl.js b/lib/coffeescript/repl.js index 11faae8b..7a3e558d 100644 --- a/lib/coffeescript/repl.js +++ b/lib/coffeescript/repl.js @@ -10,7 +10,7 @@ nodeREPL = require('repl'); - CoffeeScript = require('./coffeescript'); + CoffeeScript = require('./'); ({merge, updateSyntaxError} = require('./helpers')); diff --git a/package.json b/package.json index 79f0aa3a..1c5c5f5c 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,8 @@ "directories": { "lib": "./lib/coffeescript" }, - "main": "./lib/coffeescript/coffeescript", + "main": "./lib/coffeescript/index", + "browser": "./lib/coffeescript/browser", "bin": { "coffee": "./bin/coffee", "cake": "./bin/cake" @@ -45,7 +46,8 @@ "highlight.js": "~9.11.0", "jison": ">=0.4.17", "markdown-it": "^8.3.1", - "underscore": "~1.8.3" + "underscore": "~1.8.3", + "webpack": "^2.5.1" }, "dependencies": {} } diff --git a/src/browser.coffee b/src/browser.coffee index f320b246..6100b0a6 100644 --- a/src/browser.coffee +++ b/src/browser.coffee @@ -4,7 +4,6 @@ # `text/coffeescript` script tags, source maps via data-URLs, and so on. CoffeeScript = require './coffeescript' -CoffeeScript.require = require compile = CoffeeScript.compile # Use standard JavaScript `eval` to eval code. @@ -18,11 +17,15 @@ CoffeeScript.run = (code, options = {}) -> options.shiftLine = on Function(compile code, options)() -# If we're not in a browser environment, we're finished with the public API. +# Export this more limited `CoffeeScript` than what is exported by +# `index.coffee`, which is intended for a Node environment. +module.exports = CoffeeScript + +# If we’re not in a browser environment, we’re finished with the public API. return unless window? -# Include source maps where possible. If we've got a base64 encoder, a -# JSON serializer, and tools for escaping unicode characters, we're good to go. +# Include source maps where possible. If we’ve got a base64 encoder, a +# JSON serializer, and tools for escaping unicode characters, we’re good to go. # Ported from https://developer.mozilla.org/en-US/docs/DOM/window.btoa if btoa? and JSON? compile = (code, options = {}) -> diff --git a/src/cake.coffee b/src/cake.coffee index 7ba5544c..ec997e8a 100644 --- a/src/cake.coffee +++ b/src/cake.coffee @@ -11,7 +11,7 @@ fs = require 'fs' path = require 'path' helpers = require './helpers' optparse = require './optparse' -CoffeeScript = require './coffeescript' +CoffeeScript = require './' # Register .coffee extension CoffeeScript.register() diff --git a/src/coffeescript.coffee b/src/coffeescript.coffee index a5f1581a..4f7ab3b1 100644 --- a/src/coffeescript.coffee +++ b/src/coffeescript.coffee @@ -3,9 +3,6 @@ # contains the main entry functions for tokenizing, parsing, and compiling # source CoffeeScript into JavaScript. -fs = require 'fs' -vm = require 'vm' -path = require 'path' {Lexer} = require './lexer' {parser} = require './parser' helpers = require './helpers' @@ -156,101 +153,13 @@ exports.nodes = withPrettyErrors (source, options) -> else parser.parse source -# Compile and execute a string of CoffeeScript (on the server), correctly -# setting `__filename`, `__dirname`, and relative `require()`. -exports.run = (code, options = {}) -> - mainModule = require.main - - # Set the filename. - mainModule.filename = process.argv[1] = - if options.filename then fs.realpathSync(options.filename) else '' - - # Clear the module cache. - mainModule.moduleCache and= {} - - # Assign paths for node_modules loading - dir = if options.filename? - path.dirname fs.realpathSync options.filename - else - fs.realpathSync '.' - mainModule.paths = require('module')._nodeModulePaths dir - - # Compile. - if not helpers.isCoffee(mainModule.filename) or require.extensions - answer = compile code, options - code = answer.js ? answer - - mainModule._compile code, mainModule.filename - -# Compile and evaluate a string of CoffeeScript (in a Node.js-like environment). -# The CoffeeScript REPL uses this to run the input. -exports.eval = (code, options = {}) -> - return unless code = code.trim() - createContext = vm.Script.createContext ? vm.createContext - - isContext = vm.isContext ? (ctx) -> - options.sandbox instanceof createContext().constructor - - if createContext - if options.sandbox? - if isContext options.sandbox - sandbox = options.sandbox - else - sandbox = createContext() - sandbox[k] = v for own k, v of options.sandbox - sandbox.global = sandbox.root = sandbox.GLOBAL = sandbox - else - sandbox = global - sandbox.__filename = options.filename || 'eval' - sandbox.__dirname = path.dirname sandbox.__filename - # define module/require only if they chose not to specify their own - unless sandbox isnt global or sandbox.module or sandbox.require - Module = require 'module' - sandbox.module = _module = new Module(options.modulename || 'eval') - sandbox.require = _require = (path) -> Module._load path, _module, true - _module.filename = sandbox.__filename - for r in Object.getOwnPropertyNames require when r not in ['paths', 'arguments', 'caller'] - _require[r] = require[r] - # 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, o - if sandbox is global - vm.runInThisContext js - else - vm.runInContext js, sandbox - -exports.register = -> require './register' - -# Throw error with deprecation warning when depending upon implicit `require.extensions` registration -if require.extensions - for ext in @FILE_EXTENSIONS then do (ext) -> - require.extensions[ext] ?= -> - throw new Error """ - Use CoffeeScript.register() or require the coffeescript/register module to require #{ext} files. - """ - -exports._compileFile = (filename, sourceMap = no, inlineMap = no) -> - raw = fs.readFileSync filename, 'utf8' - # Strip the Unicode byte order mark, if this file begins with one. - stripped = if raw.charCodeAt(0) is 0xFEFF then raw.substring 1 else raw - - try - answer = compile stripped, { - filename, sourceMap, inlineMap - sourceFiles: [filename] - literate: helpers.isLiterate filename - } - catch err - # As the filename and code of a dynamically loaded file will be different - # from the original file compiled with CoffeeScript.run, add that - # information to error so it can be pretty-printed later. - throw helpers.updateSyntaxError err, stripped, filename - - answer +# This file used to export these methods; leave stubs that throw warnings +# instead. These methods have been moved into `index.coffee` to provide +# separate entrypoints for Node and non-Node environments, so that static +# analysis tools don’t choke on Node packages when compiling for a non-Node +# environment. +exports.run = exports.eval = exports.register = -> + throw new Error 'require index.coffee, not this file' # Instantiate a Lexer for our use here. lexer = new Lexer diff --git a/src/command.coffee b/src/command.coffee index 06d903e3..e8676123 100644 --- a/src/command.coffee +++ b/src/command.coffee @@ -9,7 +9,7 @@ fs = require 'fs' path = require 'path' helpers = require './helpers' optparse = require './optparse' -CoffeeScript = require './coffeescript' +CoffeeScript = require './' {spawn, exec} = require 'child_process' {EventEmitter} = require 'events' diff --git a/src/index.coffee b/src/index.coffee index 50843da9..f2bec76e 100644 --- a/src/index.coffee +++ b/src/index.coffee @@ -1,2 +1,106 @@ -# Loader for CoffeeScript as a Node.js library. -exports[key] = val for key, val of require './coffeescript' +# Node.js Implementation +CoffeeScript = require './coffeescript' +fs = require 'fs' +vm = require 'vm' +path = require 'path' + +helpers = CoffeeScript.helpers +compile = CoffeeScript.compile + +# Compile and execute a string of CoffeeScript (on the server), correctly +# setting `__filename`, `__dirname`, and relative `require()`. +CoffeeScript.run = (code, options = {}) -> + mainModule = require.main + + # Set the filename. + mainModule.filename = process.argv[1] = + if options.filename then fs.realpathSync(options.filename) else '' + + # Clear the module cache. + mainModule.moduleCache and= {} + + # Assign paths for node_modules loading + dir = if options.filename? + path.dirname fs.realpathSync options.filename + else + fs.realpathSync '.' + mainModule.paths = require('module')._nodeModulePaths dir + + # Compile. + if not helpers.isCoffee(mainModule.filename) or require.extensions + answer = compile code, options + code = answer.js ? answer + + mainModule._compile code, mainModule.filename + +# Compile and evaluate a string of CoffeeScript (in a Node.js-like environment). +# The CoffeeScript REPL uses this to run the input. +CoffeeScript.eval = (code, options = {}) -> + return unless code = code.trim() + createContext = vm.Script.createContext ? vm.createContext + + isContext = vm.isContext ? (ctx) -> + options.sandbox instanceof createContext().constructor + + if createContext + if options.sandbox? + if isContext options.sandbox + sandbox = options.sandbox + else + sandbox = createContext() + sandbox[k] = v for own k, v of options.sandbox + sandbox.global = sandbox.root = sandbox.GLOBAL = sandbox + else + sandbox = global + sandbox.__filename = options.filename || 'eval' + sandbox.__dirname = path.dirname sandbox.__filename + # define module/require only if they chose not to specify their own + unless sandbox isnt global or sandbox.module or sandbox.require + Module = require 'module' + sandbox.module = _module = new Module(options.modulename || 'eval') + sandbox.require = _require = (path) -> Module._load path, _module, true + _module.filename = sandbox.__filename + for r in Object.getOwnPropertyNames require when r not in ['paths', 'arguments', 'caller'] + _require[r] = require[r] + # 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, o + if sandbox is global + vm.runInThisContext js + else + vm.runInContext js, sandbox + +CoffeeScript.register = -> require './register' + +# Throw error with deprecation warning when depending upon implicit `require.extensions` registration +if require.extensions + for ext in CoffeeScript.FILE_EXTENSIONS then do (ext) -> + require.extensions[ext] ?= -> + throw new Error """ + Use CoffeeScript.register() or require the coffeescript/register module to require #{ext} files. + """ + +CoffeeScript._compileFile = (filename, sourceMap = no, inlineMap = no) -> + raw = fs.readFileSync filename, 'utf8' + # Strip the Unicode byte order mark, if this file begins with one. + stripped = if raw.charCodeAt(0) is 0xFEFF then raw.substring 1 else raw + + try + answer = compile stripped, { + filename, sourceMap, inlineMap + sourceFiles: [filename] + literate: helpers.isLiterate filename + } + catch err + # As the filename and code of a dynamically loaded file will be different + # from the original file compiled with CoffeeScript.run, add that + # information to error so it can be pretty-printed later. + throw helpers.updateSyntaxError err, stripped, filename + + answer + +module.exports = CoffeeScript diff --git a/src/register.coffee b/src/register.coffee index 596f3b92..76d2b9da 100644 --- a/src/register.coffee +++ b/src/register.coffee @@ -1,4 +1,4 @@ -CoffeeScript = require './coffeescript' +CoffeeScript = require './' child_process = require 'child_process' helpers = require './helpers' path = require 'path' diff --git a/src/repl.coffee b/src/repl.coffee index 9c2298b9..7041e587 100644 --- a/src/repl.coffee +++ b/src/repl.coffee @@ -2,7 +2,7 @@ fs = require 'fs' path = require 'path' vm = require 'vm' nodeREPL = require 'repl' -CoffeeScript = require './coffeescript' +CoffeeScript = require './' {merge, updateSyntaxError} = require './helpers' replDefaults =