backoffice/node_modules/insert-module-globals/index.js

171 lines
5.5 KiB
JavaScript

var parseScope = require('lexical-scope');
var through = require('through2');
var merge = require('xtend');
var path = require('path');
var processPath = require.resolve('process/browser.js');
var isbufferPath = require.resolve('is-buffer')
var combineSourceMap = require('combine-source-map');
function getRelativeRequirePath(fullPath, fromPath) {
var relpath = path.relative(path.dirname(fromPath), fullPath);
// If fullPath is in the same directory as fromPath, relpath will
// result in something like "index.js". require() needs "./" prepended
// to these paths.
if (path.dirname(relpath) === '.') {
relpath = "./" + relpath;
}
// On Windows: Convert path separators to what require() expects
if (path.sep === '\\') {
relpath = relpath.replace(/\\/g, '/');
}
return relpath;
}
var defaultVars = {
process: function (file) {
var relpath = getRelativeRequirePath(processPath, file);
return 'require(' + JSON.stringify(relpath) + ')';
},
global: function () {
return 'typeof global !== "undefined" ? global : '
+ 'typeof self !== "undefined" ? self : '
+ 'typeof window !== "undefined" ? window : {}'
;
},
'Buffer.isBuffer': function (file) {
var relpath = getRelativeRequirePath(isbufferPath, file);
return 'require(' + JSON.stringify(relpath) + ')';
},
Buffer: function () {
return 'require("buffer").Buffer';
},
__filename: function (file, basedir) {
var filename = '/' + path.relative(basedir, file);
return JSON.stringify(filename);
},
__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).filter(function(name) {
return typeof vars[name] === 'function';
});
var quick = RegExp(varNames.map(function (name) {
return '\\b' + name + '\\b';
}).join('|'));
var chunks = [];
return through(write, end);
function write (chunk, enc, next) { chunks.push(chunk); next() }
function end () {
var self = this;
var source = Buffer.isBuffer(chunks[0])
? Buffer.concat(chunks).toString('utf8')
: chunks.join('')
;
source = source
.replace(/^\ufeff/, '')
.replace(/^#![^\n]*\n/, '\n');
if (opts.always !== true && !quick.test(source)) {
this.push(source);
this.push(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 (!/\./.test(name)) return;
var parts = name.split('.')
var prop = (scope.globals.implicitProperties || {})[parts[0]]
if (!prop || prop.length !== 1 || prop[0] !== parts[1]) return;
var value = vars[name](file, basedir);
if (!value) return;
globals[parts[0]] = '{'
+ JSON.stringify(parts[1]) + ':' + value + '}';
self.emit('global', name);
});
varNames.forEach(function (name) {
if (/\./.test(name)) return;
if (globals[name]) return;
if (scope.globals.implicit.indexOf(name) < 0) return;
var value = vars[name](file, basedir);
if (!value) return;
globals[name] = value;
self.emit('global', name);
});
this.push(closeOver(globals, source, file, opts));
this.push(null);
}
};
module.exports.vars = defaultVars;
function closeOver (globals, src, file, opts) {
var keys = Object.keys(globals);
if (keys.length === 0) return src;
var values = keys.map(function (key) { return globals[key] });
var wrappedSource;
if (keys.length <= 3) {
wrappedSource = '(function (' + keys.join(',') + '){\n'
+ src + '\n}).call(this,' + values.join(',') + ')'
;
}
else {
// 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]'
);
wrappedSource = '(function (' + names.join(',') + '){\n'
+ src + '\n}).call(this,' + values.join(',') + ')';
}
// Generate source maps if wanted. Including the right offset for
// the wrapped source.
if (!opts.debug) {
return wrappedSource;
}
var sourceFile = path.relative(opts.basedir, file)
.replace(/\\/g, '/');
var sourceMap = combineSourceMap.create().addFile(
{ sourceFile: sourceFile, source: src},
{ line: 1 });
return combineSourceMap.removeComments(wrappedSource) + "\n"
+ sourceMap.comment();
}