You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
121 lines
3.5 KiB
JavaScript
121 lines
3.5 KiB
JavaScript
var parseScope = require('lexical-scope');
|
|
var through = require('through');
|
|
var merge = require('xtend');
|
|
|
|
var path = require('path');
|
|
var fs = require('fs');
|
|
var processPath = require.resolve('process/browser.js');
|
|
|
|
var defaultVars = {
|
|
process: function () {
|
|
return 'require(' + JSON.stringify(processPath) + ')';
|
|
},
|
|
global: function () {
|
|
return 'typeof self !== "undefined" ? self : '
|
|
+ 'typeof window !== "undefined" ? window : {}'
|
|
;
|
|
},
|
|
Buffer: function () {
|
|
return 'require("buffer").Buffer';
|
|
},
|
|
__filename: function (file, basedir) {
|
|
var file = '/' + path.relative(basedir, file);
|
|
return JSON.stringify(file);
|
|
},
|
|
__dirname: function (file, basedir) {
|
|
var dir = path.dirname('/' + path.relative(basedir, file));
|
|
return JSON.stringify(dir);
|
|
}
|
|
};
|
|
|
|
module.exports = function (file, opts) {
|
|
if (/\.json$/i.test(file)) return through();
|
|
if (!opts) opts = {};
|
|
|
|
var basedir = opts.basedir || '/';
|
|
var vars = merge(defaultVars, opts.vars);
|
|
var varNames = Object.keys(vars);
|
|
|
|
var quick = RegExp(varNames.map(function (name) {
|
|
return '\\b' + name + '\\b';
|
|
}).join('|'));
|
|
|
|
var resolved = {};
|
|
var chunks = [];
|
|
|
|
return through(write, end);
|
|
|
|
function write (buf) { chunks.push(buf) }
|
|
|
|
function end () {
|
|
var self = this;
|
|
var source = Buffer.isBuffer(chunks[0])
|
|
? Buffer.concat(chunks).toString('utf8')
|
|
: chunks.join('')
|
|
;
|
|
source = source.replace(/^#![^\n]*\n/, '\n');
|
|
|
|
if (opts.always !== true && !quick.test(source)) {
|
|
this.queue(source);
|
|
this.queue(null);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
var scope = opts.always
|
|
? { globals: { implicit: varNames } }
|
|
: parseScope('(function(){\n' + source + '\n})()')
|
|
;
|
|
}
|
|
catch (err) {
|
|
var e = new SyntaxError(
|
|
(err.message || err) + ' while parsing ' + file
|
|
);
|
|
e.type = 'syntax';
|
|
e.filename = file;
|
|
return this.emit('error', e);
|
|
}
|
|
|
|
var globals = {};
|
|
|
|
varNames.forEach(function (name) {
|
|
if (scope.globals.implicit.indexOf(name) >= 0) {
|
|
var value = vars[name](file, basedir);
|
|
if (value) {
|
|
globals[name] = value;
|
|
self.emit('global', name);
|
|
}
|
|
}
|
|
});
|
|
|
|
this.queue(closeOver(globals, source));
|
|
this.queue(null);
|
|
}
|
|
};
|
|
|
|
module.exports.vars = defaultVars;
|
|
|
|
function closeOver (globals, src) {
|
|
var keys = Object.keys(globals);
|
|
if (keys.length === 0) return src;
|
|
var values = keys.map(function (key) { return globals[key] });
|
|
|
|
if (keys.length <= 3) {
|
|
return '(function (' + keys.join(',') + '){\n'
|
|
+ src + '\n}).call(this,' + values.join(',') + ')'
|
|
;
|
|
}
|
|
// necessary to make arguments[3..6] still work for workerify etc
|
|
// a,b,c,arguments[3..6],d,e,f...
|
|
var extra = [ '__argument0', '__argument1', '__argument2', '__argument3' ];
|
|
var names = keys.slice(0,3).concat(extra).concat(keys.slice(3));
|
|
values.splice(3, 0,
|
|
'arguments[3]','arguments[4]',
|
|
'arguments[5]','arguments[6]'
|
|
);
|
|
|
|
return '(function (' + names.join(',') + '){\n'
|
|
+ src + '\n}).call(this,' + values.join(',') + ')'
|
|
;
|
|
}
|