Fixes #3208. You now have to require 'coffee-script/extensions' in order to be able to auto-require CoffeeScript files.

This commit is contained in:
Jeremy Ashkenas 2013-10-20 11:08:13 -03:00
parent 581af4540a
commit b173a377a6
5 changed files with 138 additions and 119 deletions

View File

@ -161,6 +161,7 @@ task 'bench', 'quick benchmark of compilation time', ->
# Run the CoffeeScript test suite. # Run the CoffeeScript test suite.
runTests = (CoffeeScript) -> runTests = (CoffeeScript) ->
require './lib/coffee-script/extensions'
startTime = Date.now() startTime = Date.now()
currentFile = null currentFile = null
passedTests = 0 passedTests = 0

View File

@ -1,6 +1,6 @@
// Generated by CoffeeScript 1.6.3 // Generated by CoffeeScript 1.6.3
(function() { (function() {
var Lexer, Module, SourceMap, binary, child_process, compile, compileFile, ext, fileExtensions, findExtension, fork, formatSourcePosition, fs, getSourceMap, helpers, lexer, loadFile, parser, path, sourceMaps, vm, withPrettyErrors, _i, _len, var Lexer, SourceMap, compile, formatSourcePosition, fs, getSourceMap, helpers, lexer, parser, path, sourceMaps, vm, withPrettyErrors,
__hasProp = {}.hasOwnProperty, __hasProp = {}.hasOwnProperty,
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
@ -10,8 +10,6 @@
path = require('path'); path = require('path');
child_process = require('child_process');
Lexer = require('./lexer').Lexer; Lexer = require('./lexer').Lexer;
parser = require('./parser').parser; parser = require('./parser').parser;
@ -22,7 +20,7 @@
exports.VERSION = '1.6.3'; exports.VERSION = '1.6.3';
fileExtensions = ['.coffee', '.litcoffee', '.coffee.md']; exports.FILE_EXTENSIONS = ['.coffee', '.litcoffee', '.coffee.md'];
exports.helpers = helpers; exports.helpers = helpers;
@ -182,8 +180,11 @@
} }
}; };
compileFile = function(filename, sourceMap) { exports._compileFile = function(filename, sourceMap) {
var answer, err, raw, stripped; var answer, err, raw, stripped;
if (sourceMap == null) {
sourceMap = false;
}
raw = fs.readFileSync(filename, 'utf8'); raw = fs.readFileSync(filename, 'utf8');
stripped = raw.charCodeAt(0) === 0xFEFF ? raw.substring(1) : raw; stripped = raw.charCodeAt(0) === 0xFEFF ? raw.substring(1) : raw;
try { try {
@ -199,63 +200,6 @@
return answer; return answer;
}; };
loadFile = function(module, filename) {
var answer;
answer = compileFile(filename, false);
return module._compile(answer, filename);
};
if (require.extensions) {
for (_i = 0, _len = fileExtensions.length; _i < _len; _i++) {
ext = fileExtensions[_i];
require.extensions[ext] = loadFile;
}
Module = require('module');
findExtension = function(filename) {
var curExtension, extensions;
extensions = path.basename(filename).split('.');
if (extensions[0] === '') {
extensions.shift();
}
while (extensions.shift()) {
curExtension = '.' + extensions.join('.');
if (Module._extensions[curExtension]) {
return curExtension;
}
}
return '.js';
};
Module.prototype.load = function(filename) {
var extension;
this.filename = filename;
this.paths = Module._nodeModulePaths(path.dirname(filename));
extension = findExtension(filename);
Module._extensions[extension](this, filename);
return this.loaded = true;
};
}
if (child_process) {
fork = child_process.fork;
binary = require.resolve('../../bin/coffee');
child_process.fork = function(path, args, options) {
var execPath;
if (args == null) {
args = [];
}
if (options == null) {
options = {};
}
execPath = helpers.isCoffee(path) ? binary : null;
if (!Array.isArray(args)) {
args = [];
options = args || {};
}
options.execPath || (options.execPath = execPath);
return fork(path, args, options);
};
}
lexer = new Lexer; lexer = new Lexer;
parser.lexer = { parser.lexer = {
@ -343,10 +287,10 @@
if (sourceMaps[filename]) { if (sourceMaps[filename]) {
return sourceMaps[filename]; return sourceMaps[filename];
} }
if (_ref = path != null ? path.extname(filename) : void 0, __indexOf.call(fileExtensions, _ref) < 0) { if (_ref = path != null ? path.extname(filename) : void 0, __indexOf.call(exports.FILE_EXTENSIONS, _ref) < 0) {
return; return;
} }
answer = compileFile(filename, true); answer = exports._compileFile(filename, true);
return sourceMaps[filename] = answer.sourceMap; return sourceMaps[filename] = answer.sourceMap;
}; };
@ -365,10 +309,10 @@
} }
}; };
frames = (function() { frames = (function() {
var _j, _len1, _results; var _i, _len, _results;
_results = []; _results = [];
for (_j = 0, _len1 = stack.length; _j < _len1; _j++) { for (_i = 0, _len = stack.length; _i < _len; _i++) {
frame = stack[_j]; frame = stack[_i];
if (frame.getFunction() === exports.run) { if (frame.getFunction() === exports.run) {
break; break;
} }

View File

@ -0,0 +1,71 @@
// Generated by CoffeeScript 1.6.3
(function() {
var CoffeeScript, Module, binary, child_process, ext, findExtension, fork, helpers, loadFile, path, _i, _len, _ref;
CoffeeScript = require('./coffee-script');
child_process = require('child_process');
helpers = require('./helpers');
path = require('path');
loadFile = function(module, filename) {
var answer;
answer = CoffeeScript._compileFile(filename, false);
return module._compile(answer, filename);
};
if (require.extensions) {
_ref = CoffeeScript.FILE_EXTENSIONS;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
ext = _ref[_i];
require.extensions[ext] = loadFile;
}
Module = require('module');
findExtension = function(filename) {
var curExtension, extensions;
extensions = path.basename(filename).split('.');
if (extensions[0] === '') {
extensions.shift();
}
while (extensions.shift()) {
curExtension = '.' + extensions.join('.');
if (Module._extensions[curExtension]) {
return curExtension;
}
}
return '.js';
};
Module.prototype.load = function(filename) {
var extension;
this.filename = filename;
this.paths = Module._nodeModulePaths(path.dirname(filename));
extension = findExtension(filename);
Module._extensions[extension](this, filename);
return this.loaded = true;
};
}
if (child_process) {
fork = child_process.fork;
binary = require.resolve('../../bin/coffee');
child_process.fork = function(path, args, options) {
var execPath;
if (args == null) {
args = [];
}
if (options == null) {
options = {};
}
execPath = helpers.isCoffee(path) ? binary : null;
if (!Array.isArray(args)) {
args = [];
options = args || {};
}
options.execPath || (options.execPath = execPath);
return fork(path, args, options);
};
}
}).call(this);

View File

@ -6,7 +6,6 @@
fs = require 'fs' fs = require 'fs'
vm = require 'vm' vm = require 'vm'
path = require 'path' path = require 'path'
child_process = require 'child_process'
{Lexer} = require './lexer' {Lexer} = require './lexer'
{parser} = require './parser' {parser} = require './parser'
helpers = require './helpers' helpers = require './helpers'
@ -15,7 +14,7 @@ SourceMap = require './sourcemap'
# The current CoffeeScript version number. # The current CoffeeScript version number.
exports.VERSION = '1.6.3' exports.VERSION = '1.6.3'
fileExtensions = ['.coffee', '.litcoffee', '.coffee.md'] exports.FILE_EXTENSIONS = ['.coffee', '.litcoffee', '.coffee.md']
# Expose helpers for testing. # Expose helpers for testing.
exports.helpers = helpers exports.helpers = helpers
@ -152,7 +151,7 @@ exports.eval = (code, options = {}) ->
else else
vm.runInContext js, sandbox vm.runInContext js, sandbox
compileFile = (filename, sourceMap) -> exports._compileFile = (filename, sourceMap = no) ->
raw = fs.readFileSync filename, 'utf8' raw = fs.readFileSync filename, 'utf8'
stripped = if raw.charCodeAt(0) is 0xFEFF then raw.substring 1 else raw stripped = if raw.charCodeAt(0) is 0xFEFF then raw.substring 1 else raw
@ -166,53 +165,6 @@ compileFile = (filename, sourceMap) ->
answer answer
# Load and run a CoffeeScript file for Node, stripping any `BOM`s.
loadFile = (module, filename) ->
answer = compileFile filename, false
module._compile answer, filename
# If the installed version of Node supports `require.extensions`, register
# CoffeeScript as an extension.
if require.extensions
for ext in fileExtensions
require.extensions[ext] = loadFile
# Patch Node's module loader to be able to handle mult-dot extensions.
# This is a horrible thing that should not be required. Perhaps, one day,
# when a truly benevolent dictator comes to rule over the Republik of Node,
# it won't be.
Module = require 'module'
findExtension = (filename) ->
extensions = path.basename(filename).split '.'
# Remove the initial dot from dotfiles.
extensions.shift() if extensions[0] is ''
# Start with the longest possible extension and work our way shortwards.
while extensions.shift()
curExtension = '.' + extensions.join '.'
return curExtension if Module._extensions[curExtension]
'.js'
Module::load = (filename) ->
@filename = filename
@paths = Module._nodeModulePaths path.dirname filename
extension = findExtension filename
Module._extensions[extension](this, filename)
@loaded = true
# If we're on Node, patch `child_process.fork` so that Coffee scripts are able
# to fork both CoffeeScript files, and JavaScript files, directly.
if child_process
{fork} = child_process
binary = require.resolve '../../bin/coffee'
child_process.fork = (path, args = [], options = {}) ->
execPath = if helpers.isCoffee(path) then binary else null
if not Array.isArray args
args = []
options = args or {}
options.execPath or= execPath
fork path, args, options
# Instantiate a Lexer for our use here. # Instantiate a Lexer for our use here.
lexer = new Lexer lexer = new Lexer
@ -305,8 +257,8 @@ sourceMaps = {}
# Generates the source map for a coffee file and stores it in the local cache variable. # Generates the source map for a coffee file and stores it in the local cache variable.
getSourceMap = (filename) -> getSourceMap = (filename) ->
return sourceMaps[filename] if sourceMaps[filename] return sourceMaps[filename] if sourceMaps[filename]
return unless path?.extname(filename) in fileExtensions return unless path?.extname(filename) in exports.FILE_EXTENSIONS
answer = compileFile filename, true answer = exports._compileFile filename, true
sourceMaps[filename] = answer.sourceMap sourceMaps[filename] = answer.sourceMap
# Based on [michaelficarra/CoffeeScriptRedux](http://goo.gl/ZTx1p) # Based on [michaelficarra/CoffeeScriptRedux](http://goo.gl/ZTx1p)

51
src/extensions.coffee Normal file
View File

@ -0,0 +1,51 @@
CoffeeScript = require './coffee-script'
child_process = require 'child_process'
helpers = require './helpers'
path = require 'path'
# Load and run a CoffeeScript file for Node, stripping any `BOM`s.
loadFile = (module, filename) ->
answer = CoffeeScript._compileFile filename, false
module._compile answer, filename
# If the installed version of Node supports `require.extensions`, register
# CoffeeScript as an extension.
if require.extensions
for ext in CoffeeScript.FILE_EXTENSIONS
require.extensions[ext] = loadFile
# Patch Node's module loader to be able to handle mult-dot extensions.
# This is a horrible thing that should not be required. Perhaps, one day,
# when a truly benevolent dictator comes to rule over the Republik of Node,
# it won't be.
Module = require 'module'
findExtension = (filename) ->
extensions = path.basename(filename).split '.'
# Remove the initial dot from dotfiles.
extensions.shift() if extensions[0] is ''
# Start with the longest possible extension and work our way shortwards.
while extensions.shift()
curExtension = '.' + extensions.join '.'
return curExtension if Module._extensions[curExtension]
'.js'
Module::load = (filename) ->
@filename = filename
@paths = Module._nodeModulePaths path.dirname filename
extension = findExtension filename
Module._extensions[extension](this, filename)
@loaded = true
# If we're on Node, patch `child_process.fork` so that Coffee scripts are able
# to fork both CoffeeScript files, and JavaScript files, directly.
if child_process
{fork} = child_process
binary = require.resolve '../../bin/coffee'
child_process.fork = (path, args = [], options = {}) ->
execPath = if helpers.isCoffee(path) then binary else null
if not Array.isArray args
args = []
options = args or {}
options.execPath or= execPath
fork path, args, options