mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
[CS2] Module should be require-able in non-Node environments like Webpack and Browserify (#4546)
* Add webpack support * Move Node.js-only code from src/coffee-script.coffee to src/index.coffee * Use lib/coffee-script/index.js as npm package's "main" script * Export CoffeeScript from src/browser.coffee * Set package.json's "browser" field to lib/coffee-script/browser.js (used by webpack as entry point) * Use lib/coffee-script/browser.js as bower package's "main" script * Use NOP moduleMain when generating parser with Jison * Remove legacy debug code from browser.coffee * Improve comments, style * Fix path * Remove stub that was only to avoid breaking browser tests; compensate for the lack of stub when running the browser tests in Node * Update output * Add test:webpack task to Cakefile * Update output files * Run browser tests against webpack build * Fix newline at end of file * Export webpack test bundle as CommonJS module * Remove build:webpack task * Save webpack build to tmpdir; suppress build output unless it fails
This commit is contained in:
parent
993347bb8a
commit
8407dd885a
18 changed files with 301 additions and 266 deletions
41
Cakefile
41
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
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "coffeescript",
|
||||
"main": [
|
||||
"lib/coffeescript/coffeescript.js"
|
||||
"lib/coffeescript/browser.js"
|
||||
],
|
||||
"description": "Unfancy JavaScript",
|
||||
"keywords": [
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
optparse = require('./optparse');
|
||||
|
||||
CoffeeScript = require('./coffeescript');
|
||||
CoffeeScript = require('./');
|
||||
|
||||
CoffeeScript.register();
|
||||
|
||||
|
|
|
@ -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) : '<anonymous>';
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
optparse = require('./optparse');
|
||||
|
||||
CoffeeScript = require('./coffeescript');
|
||||
CoffeeScript = require('./');
|
||||
|
||||
({spawn, exec} = require('child_process'));
|
||||
|
||||
|
|
|
@ -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) : '<anonymous>';
|
||||
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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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');
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
nodeREPL = require('repl');
|
||||
|
||||
CoffeeScript = require('./coffeescript');
|
||||
CoffeeScript = require('./');
|
||||
|
||||
({merge, updateSyntaxError} = require('./helpers'));
|
||||
|
||||
|
|
|
@ -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": {}
|
||||
}
|
||||
|
|
|
@ -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 = {}) ->
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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 '<anonymous>'
|
||||
|
||||
# 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
|
||||
|
|
|
@ -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'
|
||||
|
||||
|
|
108
src/index.coffee
108
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 '<anonymous>'
|
||||
|
||||
# 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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
CoffeeScript = require './coffeescript'
|
||||
CoffeeScript = require './'
|
||||
child_process = require 'child_process'
|
||||
helpers = require './helpers'
|
||||
path = require 'path'
|
||||
|
|
|
@ -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 =
|
||||
|
|
Loading…
Add table
Reference in a new issue