mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
It's not used, it doesn't fully work yet, it's incompatible with the static analysis, and it will make implementing CoffeeScript source maps significantly more difficult.
114 lines
4.3 KiB
JavaScript
114 lines
4.3 KiB
JavaScript
var fs = Npm.require('fs');
|
|
var path = Npm.require('path');
|
|
var coffee = Npm.require('coffee-script');
|
|
var _ = Npm.require('underscore');
|
|
|
|
var stripExportedVars = function (source, exports) {
|
|
if (!exports || _.isEmpty(exports))
|
|
return source;
|
|
var lines = source.split("\n");
|
|
|
|
// We make the following assumptions, based on the output of CoffeeScript
|
|
// 1.6.3.
|
|
// - The var declaration in question is not indented and is the first such
|
|
// var declaration. (CoffeeScript only produces one var line at each
|
|
// scope and there's only one top-level scope.) All relevant variables
|
|
// are actually on this line.
|
|
// - The user hasn't used a ###-comment containing a line that looks like
|
|
// a var line, to produce something like
|
|
// /* bla
|
|
// var foo;
|
|
// */
|
|
// before an actual var line. (ie, we do NOT attempt to figure out if
|
|
// we're inside a /**/ comment, which is produced by ### comments.)
|
|
// - The var in question is not assigned to in the declaration, nor are any
|
|
// other vars on this line. (CoffeeScript does produce some assignments
|
|
// but only for internal helpers generated by CoffeeScript, and they end
|
|
// up on subsequent lines.)
|
|
// XXX relax these assumptions by doing actual JS parsing (eg with jsparse).
|
|
// I'd do this now, but there's no easy way to "unparse" a jsparse AST.
|
|
|
|
var foundVarLine = false;
|
|
lines = _.map(lines, function (line) {
|
|
if (foundVarLine)
|
|
return line;
|
|
var match = /^var (.+)([,;])$/.exec(line);
|
|
if (!match)
|
|
return line;
|
|
foundVarLine = true;
|
|
|
|
// If there's an assignment on this line, we assume that there are ONLY
|
|
// assignments and that the var we are looking for is not declared. (Part
|
|
// of our strong assumption about the layout of this code.)
|
|
if (match[1].indexOf('=') !== -1)
|
|
return line;
|
|
|
|
var vars = match[1].split(', ');
|
|
vars = _.difference(vars, exports);
|
|
if (!_.isEmpty(vars))
|
|
return "var " + vars.join(', ') + match[2];
|
|
// We got rid of all the vars on this line. Drop the whole line if this
|
|
// didn't continue to the next line, otherwise keep just the 'var '.
|
|
return match[2] === ';' ? '' : 'var';
|
|
});
|
|
return lines.join('\n');
|
|
};
|
|
|
|
var addSharedHeader = function (source) {
|
|
// We want the symbol "share" to be visible to all CoffeeScript files in the
|
|
// package (and shared between them), but not visible to JavaScript
|
|
// files. (That's because we don't want to introduce two competing ways to
|
|
// make package-local variables into JS ("share" vs assigning to non-var
|
|
// variables).) The following hack accomplishes that: "__coffeescriptShare"
|
|
// will be visible at the package level and "share" at the file level. This
|
|
// should work both in "package" mode where __coffeescriptShare will be added
|
|
// as a var in the package closure, and in "app" mode where it will end up as
|
|
// a global.
|
|
//
|
|
// This ends in a newline in case the first line is a linker @comment, which
|
|
// should be at the beginning of a line.
|
|
var header = ("__coffeescriptShare = typeof __coffeescriptShare === 'object' " +
|
|
"? __coffeescriptShare : {}; " +
|
|
"var share = __coffeescriptShare;\n");
|
|
|
|
// If the file begins with "use strict", we need to keep that as the first
|
|
// statement.
|
|
return source.replace(/^(?:(['"])use strict\1;\n)?/, function (match) {
|
|
return match + header;
|
|
});
|
|
};
|
|
|
|
var handler = function (compileStep) {
|
|
var source = compileStep.read().toString('utf8');
|
|
var options = {
|
|
bare: true,
|
|
filename: compileStep.inputPath,
|
|
literate: path.extname(compileStep.inputPath) === '.litcoffee'
|
|
};
|
|
|
|
try {
|
|
var output = coffee.compile(source, options);
|
|
} catch (e) {
|
|
// XXX better error handling, once the Plugin interface support it
|
|
throw new Error(
|
|
compileStep.inputPath + ':' +
|
|
(e.location ? (e.location.first_line + ': ') : ' ') +
|
|
e.message
|
|
);
|
|
}
|
|
|
|
compileStep.addJavaScript({
|
|
path: compileStep.inputPath + ".js",
|
|
sourcePath: compileStep.inputPath,
|
|
data: output,
|
|
lineForLine: false,
|
|
linkerFileTransform: function (source, exports) {
|
|
return addSharedHeader(stripExportedVars(source, exports));
|
|
}
|
|
});
|
|
};
|
|
|
|
Plugin.registerSourceHandler("coffee", handler);
|
|
Plugin.registerSourceHandler("litcoffee", handler);
|
|
|