/src/index.coffee
CoffeeScript | 139 lines | 91 code | 23 blank | 25 comment | 18 complexity | 9b640a8d51af8503efd72eb551554b5b MD5 | raw file
1# Node.js Implementation 2CoffeeScript = require './coffeescript' 3fs = require 'fs' 4vm = require 'vm' 5path = require 'path' 6 7helpers = CoffeeScript.helpers 8 9CoffeeScript.transpile = (js, options) -> 10 try 11 babel = require '@babel/core' 12 catch 13 try 14 babel = require 'babel-core' 15 catch 16 # This error is only for Node, as CLI users will see a different error 17 # earlier if they don’t have Babel installed. 18 throw new Error 'To use the transpile option, you must have the \'@babel/core\' module installed' 19 babel.transform js, options 20 21# The `compile` method shared by the CLI, Node and browser APIs. 22universalCompile = CoffeeScript.compile 23# The `compile` method particular to the Node API. 24CoffeeScript.compile = (code, options) -> 25 # Pass a reference to Babel into the compiler, so that the transpile option 26 # is available in the Node API. We need to do this so that tools like Webpack 27 # can `require('coffeescript')` and build correctly, without trying to 28 # require Babel. 29 if options?.transpile 30 options.transpile.transpile = CoffeeScript.transpile 31 universalCompile.call CoffeeScript, code, options 32 33# Compile and execute a string of CoffeeScript (on the server), correctly 34# setting `__filename`, `__dirname`, and relative `require()`. 35CoffeeScript.run = (code, options = {}) -> 36 mainModule = require.main 37 38 # Set the filename. 39 mainModule.filename = process.argv[1] = 40 if options.filename then fs.realpathSync(options.filename) else '<anonymous>' 41 42 # Clear the module cache. 43 mainModule.moduleCache and= {} 44 45 # Assign paths for node_modules loading 46 dir = if options.filename? 47 path.dirname fs.realpathSync options.filename 48 else 49 fs.realpathSync '.' 50 mainModule.paths = require('module')._nodeModulePaths dir 51 52 # Save the options for compiling child imports. 53 mainModule.options = options 54 55 # Compile. 56 if not helpers.isCoffee(mainModule.filename) or require.extensions 57 answer = CoffeeScript.compile code, options 58 code = answer.js ? answer 59 60 mainModule._compile code, mainModule.filename 61 62# Compile and evaluate a string of CoffeeScript (in a Node.js-like environment). 63# The CoffeeScript REPL uses this to run the input. 64CoffeeScript.eval = (code, options = {}) -> 65 return unless code = code.trim() 66 createContext = vm.Script.createContext ? vm.createContext 67 68 isContext = vm.isContext ? (ctx) -> 69 options.sandbox instanceof createContext().constructor 70 71 if createContext 72 if options.sandbox? 73 if isContext options.sandbox 74 sandbox = options.sandbox 75 else 76 sandbox = createContext() 77 sandbox[k] = v for own k, v of options.sandbox 78 sandbox.global = sandbox.root = sandbox.GLOBAL = sandbox 79 else 80 sandbox = global 81 sandbox.__filename = options.filename || 'eval' 82 sandbox.__dirname = path.dirname sandbox.__filename 83 # define module/require only if they chose not to specify their own 84 unless sandbox isnt global or sandbox.module or sandbox.require 85 Module = require 'module' 86 sandbox.module = _module = new Module(options.modulename || 'eval') 87 sandbox.require = _require = (path) -> Module._load path, _module, true 88 _module.filename = sandbox.__filename 89 for r in Object.getOwnPropertyNames require when r not in ['paths', 'arguments', 'caller'] 90 _require[r] = require[r] 91 # use the same hack node currently uses for their own REPL 92 _require.paths = _module.paths = Module._nodeModulePaths process.cwd() 93 _require.resolve = (request) -> Module._resolveFilename request, _module 94 o = {} 95 o[k] = v for own k, v of options 96 o.bare = on # ensure return value 97 js = CoffeeScript.compile code, o 98 if sandbox is global 99 vm.runInThisContext js 100 else 101 vm.runInContext js, sandbox 102 103CoffeeScript.register = -> require './register' 104 105# Throw error with deprecation warning when depending upon implicit `require.extensions` registration 106if require.extensions 107 for ext in CoffeeScript.FILE_EXTENSIONS then do (ext) -> 108 require.extensions[ext] ?= -> 109 throw new Error """ 110 Use CoffeeScript.register() or require the coffeescript/register module to require #{ext} files. 111 """ 112 113CoffeeScript._compileRawFileContent = (raw, filename, options = {}) -> 114 115 # Strip the Unicode byte order mark, if this file begins with one. 116 stripped = if raw.charCodeAt(0) is 0xFEFF then raw.substring 1 else raw 117 118 options = Object.assign {}, options, 119 filename: filename 120 literate: helpers.isLiterate filename 121 sourceFiles: [filename] 122 inlineMap: yes # Always generate a source map, so that stack traces line up. 123 124 try 125 answer = CoffeeScript.compile stripped, options 126 catch err 127 # As the filename and code of a dynamically loaded file will be different 128 # from the original file compiled with CoffeeScript.run, add that 129 # information to error so it can be pretty-printed later. 130 throw helpers.updateSyntaxError err, stripped, filename 131 132 answer 133 134CoffeeScript._compileFile = (filename, options = {}) -> 135 raw = fs.readFileSync filename, 'utf8' 136 137 CoffeeScript._compileRawFileContent raw, filename, options 138 139module.exports = CoffeeScript