• Jump To … +
    browser.coffee cake.coffee coffeescript.coffee command.coffee grammar.coffee helpers.coffee index.coffee lexer.coffee nodes.coffee optparse.coffee register.coffee repl.coffee rewriter.coffee scope.litcoffee sourcemap.litcoffee
  • index.coffee

  • §

    Node.js Implementation

    CoffeeScript  = require './coffeescript'
    fs            = require 'fs'
    vm            = require 'vm'
    path          = require 'path'
    
    helpers       = CoffeeScript.helpers
    
    CoffeeScript.transpile = (js, options) ->
      try
        babel = require '@babel/core'
      catch
        try
          babel = require 'babel-core'
        catch
  • §

    This error is only for Node, as CLI users will see a different error earlier if they don’t have Babel installed.

          throw new Error 'To use the transpile option, you must have the \'@babel/core\' module installed'
      babel.transform js, options
  • §

    The compile method shared by the CLI, Node and browser APIs.

    universalCompile = CoffeeScript.compile
  • §

    The compile method particular to the Node API.

    CoffeeScript.compile = (code, options) ->
  • §

    Pass a reference to Babel into the compiler, so that the transpile option is available in the Node API. We need to do this so that tools like Webpack can require('coffeescript') and build correctly, without trying to require Babel.

      if options?.transpile
        options.transpile.transpile = CoffeeScript.transpile
      universalCompile.call CoffeeScript, code, options
  • §

    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 helpers.anonymousFileName()
  • §

    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
  • §

    Save the options for compiling child imports.

      mainModule.options = options
    
      options.filename = mainModule.filename
      options.inlineMap = true
  • §

    Compile.

      answer = CoffeeScript.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 = CoffeeScript.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._compileRawFileContent = (raw, filename, options = {}) ->
  • §

    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
    
      options = Object.assign {}, options,
        filename: filename
        literate: helpers.isLiterate filename
        sourceFiles: [filename]
    
      try
        answer = CoffeeScript.compile stripped, options
      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
    
    CoffeeScript._compileFile = (filename, options = {}) ->
      raw = fs.readFileSync filename, 'utf8'
    
      CoffeeScript._compileRawFileContent raw, filename, options
    
    module.exports = CoffeeScript
  • §

    Explicitly define all named exports so that Node’s automatic detection of named exports from CommonJS packages finds all of them. This enables consuming packages to write code like import { compile } from 'coffeescript'. Don’t simplify this into a loop or similar; the module.exports.name part is essential for Node’s algorithm to successfully detect the name.

    module.exports.VERSION = CoffeeScript.VERSION
    module.exports.FILE_EXTENSIONS = CoffeeScript.FILE_EXTENSIONS
    module.exports.helpers = CoffeeScript.helpers
    module.exports.registerCompiled = CoffeeScript.registerCompiled
    module.exports.compile = CoffeeScript.compile
    module.exports.tokens = CoffeeScript.tokens
    module.exports.nodes = CoffeeScript.nodes
    module.exports.register = CoffeeScript.register
    module.exports.eval = CoffeeScript.eval
    module.exports.run = CoffeeScript.run
    module.exports.transpile = CoffeeScript.transpile
    module.exports.patchStackTrace = CoffeeScript.patchStackTrace
    module.exports._compileRawFileContent = CoffeeScript._compileRawFileContent
    module.exports._compileFile = CoffeeScript._compileFile