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.
typesetting/pitfall/pdfkit/node_modules/browserify/index.js

812 lines
24 KiB
JavaScript

var crypto = require('crypto');
var through2 = require('through2');
var pipeline = require('stream-combiner');
var concatStream = require('concat-stream');
var checkSyntax = require('syntax-error');
var parents = require('parents');
var deepEqual = require('deep-equal');
var defined = require('defined');
var builtins = require('./lib/builtins.js');
var builtinsList = require('builtins');
var mdeps = require('module-deps');
var browserPack = require('browser-pack');
var depSorter = require('deps-sort');
var browserResolve = require('browser-resolve');
var nodeResolve = require('resolve');
var insertGlobals = require('insert-module-globals');
var umd = require('umd');
var derequire = require('derequire');
var commondir = require('commondir');
var merge = require('xtend');
var path = require('path');
var inherits = require('inherits');
var EventEmitter = require('events').EventEmitter;
var fs = require('fs');
var copy = require('shallow-copy');
var emptyModulePath = path.join(__dirname, 'lib/_empty.js');
var excludeModulePath = path.join(__dirname, 'lib/_exclude.js');
var processPath = require.resolve('process/browser.js');
module.exports = function (opts, xopts) {
if (opts === undefined) opts = {};
if (typeof opts === 'string') opts = { entries: [ opts ] };
if (isStream(opts)) opts = { entries: [ opts ] };
if (Array.isArray(opts)) opts = { entries: opts };
if (xopts) Object.keys(xopts).forEach(function (key) {
opts[key] = xopts[key];
});
var b = new Browserify(opts);
[].concat(opts.entries).filter(Boolean).forEach(b.add.bind(b));
return b;
};
function hash(what) {
return crypto.createHash('md5').update(what).digest('base64').slice(0, 6);
}
inherits(Browserify, EventEmitter);
function Browserify (opts) {
var self = this;
self.files = [];
self.exports = {};
self._pending = 0;
self._entries = [];
self._ignore = {};
self._exclude = {};
self._external = {};
self._expose = {};
self._mapped = {};
self._plugins = [];
self._transforms = [];
self._globalTransforms = [];
self._extensions = [ '.js', '.json' ]
.concat(opts.extensions).filter(Boolean)
;
self._noParse = [];
self._pkgcache = {};
self._exposeAll = opts.exposeAll;
self._ignoreMissing = opts.ignoreMissing;
self._basedir = opts.basedir;
self._delegateResolve = opts.resolve || browserResolve;
var sep = /^win/i.test(process.platform) ? ';' : ':';
self._paths = opts.paths || (process.env.NODE_PATH || '').split(sep);
self._fullPaths = !!opts.fullPaths;
self._browserPack = opts.pack || function (params) {
params.raw = true;
params.sourceMapPrefix = '//#';
return browserPack(params);
};
if (typeof opts.builtins === 'boolean') {
self._builtins = opts.builtins ? builtins : {};
}
else if (Array.isArray(opts.builtins)) {
self._builtins = {};
opts.builtins.forEach(function (name) {
if (builtins.hasOwnProperty(name)) {
self._builtins[name] = builtins[name];
}
});
}
else if (typeof opts.builtins === 'object') {
self._builtins = opts.builtins;
}
else {
self._builtins = builtins;
}
builtinsList.forEach(function (key) {
if (!self._builtins.hasOwnProperty(key)) {
self._exclude[key] = true;
}
});
self._commondir = opts.commondir;
self._bundleExternal = opts.bundleExternal !== false;
var noParse = [].concat(opts.noParse).filter(Boolean);
noParse.forEach(this.noParse.bind(this));
}
Browserify.prototype._hash = function (id) {
var basedir = this._basedir;
if (!basedir) basedir = process.cwd();
return hash(path.relative(basedir, id));
};
Browserify.prototype.noParse = function(file) {
var self = this;
var cwd = process.cwd();
var top = { id: cwd, filename: cwd + '/_fake.js', paths: [] };
self._noParse.push(file, path.resolve(file));
self._pending ++;
self._resolve(file, top, function (err, r) {
if (r) self._noParse.push(r);
if (--self._pending === 0) self.emit('_ready');
});
return this;
};
Browserify.prototype.add = function (file) {
this.require(file, { entry: true });
return this;
};
Browserify.prototype.require = function (id, opts) {
var self = this;
if (isStream(id)) {
self.files.push(id);
if (opts.entry) self._entries.push(id.path);
return self;
}
else if (Array.isArray(id)) {
id.forEach(function(id) { self.require(id, opts) });
return self;
}
if (opts === undefined) opts = { expose: id };
self._pending ++;
var basedir = opts.basedir || self._basedir || process.cwd();
var fromfile = basedir + '/_fake.js';
var params = {
filename: fromfile,
modules: self._builtins,
packageFilter: packageFilter,
extensions: self._extensions,
paths: opts.paths || self._paths
};
var order;
if (opts.entry) {
order = self._entries.length;
self._entries.push(null);
}
self._delegateResolve(id, params, function (err, file) {
if ((err || !file) && !opts.external) {
if (err) return self.emit('error', err);
if (!file) return self.emit('error', notFound(id, fromfile));
}
if (opts.expose) {
self.exports[file] = self._hash(file);
if (typeof opts.expose === 'string') {
self._expose[file] = opts.expose;
self._mapped[opts.expose] = file;
}
}
if (opts.external) {
if (file) self._external[file] = true;
else {
self._external[id] = true;
if (self._basedir) {
self._external[path.resolve(self._basedir, id)] = true;
}
else self._external[path.resolve(id)] = true;
}
}
else {
self.files.push(file);
}
if (opts.entry) self._entries[order] = file;
if (--self._pending === 0) self.emit('_ready');
});
return self;
};
// DEPRECATED
Browserify.prototype.expose = function (name, file) {
this.exports[file] = name;
this.files.push(file);
};
Browserify.prototype.external = function (id, opts) {
var self = this;
if (!opts) opts = {};
if (!opts.basedir) opts.basedir = self._basedir;
if (!opts.globalTransform) opts.globalTransform = self._globalTransforms;
if (isBrowserify(id)) {
self._pending++;
function captureDeps() {
var d = mdeps(id.files, opts);
d.on('error', self.emit.bind(self, 'error'));
d.pipe(through2.obj(write, end));
function write (row, encoding, callback) {
self.external(row.id);
callback();
}
function end (callback) {
if (--self._pending === 0) self.emit('_ready');
callback();
}
}
if (id._pending === 0) return captureDeps();
return id.once('_ready', captureDeps);
}
else if (Array.isArray(id)) {
id.forEach(function(id) { self.external(id, opts) });
return self;
}
opts.external = true;
if (!opts.parse) {
this.noParse(id);
if (opts.expose) this.noParse(opts.expose);
}
return this.require(id, opts);
};
Browserify.prototype.ignore = function (file) {
this._ignore[file] = true;
if (this._basedir) {
this._ignore[path.resolve(this._basedir, file)] = true;
}
else this._ignore[path.resolve(file)] = true;
return this;
};
Browserify.prototype.exclude = function (file) {
this.ignore(file);
this._exclude[file] = true;
if (this._basedir) {
this._exclude[path.resolve(this._basedir, file)] = true;
}
else this._exclude[path.resolve(file)] = true;
return this;
};
Browserify.prototype.bundle = function (opts, cb) {
var self = this;
if (typeof opts === 'function') {
cb = opts;
opts = {};
}
if (!opts) opts = {};
if (opts.insertGlobals === undefined) opts.insertGlobals = false;
if (opts.detectGlobals === undefined) opts.detectGlobals = true;
if (opts.ignoreMissing === undefined) opts.ignoreMissing = false;
if (opts.standalone === undefined) opts.standalone = false;
self._ignoreMissing = opts.ignoreMissing;
opts.resolve = self._resolve.bind(self);
opts.transform = self._transforms;
var basedir = opts.basedir || self._basedir;
if (!basedir && self._commondir === false) {
basedir = '/';
}
else if (!basedir && self.files.length === 1) {
basedir = path.dirname(self.files[0]);
}
else if (!basedir && (self.files.length === 0 || isStream(self.files[0]))) {
basedir = process.cwd();
}
else if (!basedir) basedir = commondir(self.files);
if (opts.detectGlobals || opts.insertGlobals) {
opts.globalTransform = [ function (file) {
if (self._noParse.indexOf(file) >= 0) {
return through2();
}
var inserter = insertGlobals(file, {
always: opts.insertGlobals,
vars: merge({
process: function () {
return 'require('
+ JSON.stringify(self._hash(processPath))
+ ')';
}
}, opts.insertGlobalVars),
basedir: basedir
});
inserter.on('global', function (name) {
if (name !== 'process') return;
self._mapped[self._hash(processPath)] = processPath;
});
return inserter;
} ].concat(self._globalTransforms);
}
else opts.globalTransform = self._globalTransforms;
opts.noParse = self._noParse;
opts.transformKey = [ 'browserify', 'transform' ];
var parentFilter = opts.packageFilter;
opts.packageFilter = function (pkg, x) {
if (parentFilter) pkg = parentFilter(pkg || {}, x);
return packageFilter(pkg || {}, x);
};
if (cb) cb = (function (f) {
return function () {
if (f) f.apply(this, arguments);
f = null;
};
})(cb);
if (self._pending) {
var tr = through2();
self.on('_ready', function () {
var b = self.bundle(opts, cb);
b.on('transform', tr.emit.bind(tr, 'transform'));
if (!cb) b.on('error', tr.emit.bind(tr, 'error'));
b.pipe(tr);
});
if (cb) tr.resume();
return tr;
}
if (opts.standalone && self._entries.length !== 1) {
process.nextTick(function () {
p.emit('error', 'standalone only works with a single entry point');
});
}
var prevCache = opts.cache && copy(opts.cache);
var d = (opts.deps || self.deps.bind(self))(opts);
var p = self.pack(opts);
if (cb) {
p.on('error', cb);
p.pipe(concatStream({ encoding: 'string' }, function (src) {
cb(null, opts.standalone ? derequire(src) : src);
}));
p.resume();
}
d.on('error', p.emit.bind(p, 'error'));
d.on('transform', p.emit.bind(p, 'transform'));
d.pipe(p);
if (opts.standalone) {
var output = through2();
p.pipe(concatStream({ encoding: 'string' }, function (body) {
output.end(derequire(body));
}));
return output;
}
self.emit('bundle', p);
p.on('end', function () {
process.nextTick(function () {
p.emit('close');
});
});
return p;
};
Browserify.prototype.transform = function (opts, t) {
if (t === undefined) {
t = opts;
opts = {};
}
if (typeof opts === 'string' || typeof opts === 'function') {
var t_ = t;
t = opts;
opts = t;
}
if (!opts) opts = {};
if (typeof t === 'string') {
try {
t = /^\./.test(t)
? require(path.resolve(t))
: require(t)
;
}
catch (err) {
t = require(nodeResolve.sync(
t, { basedir: this._basedir || process.cwd() }
));
}
}
t = (function (t) {
return function (file) { return t.call(this, file, opts) };
})(t);
if (opts.global) {
this._globalTransforms.push(t);
}
else this._transforms.push(t);
return this;
};
Browserify.prototype.plugin = function (plugin, opts) {
if (typeof plugin === 'function') {
this._plugins.push({ plugin: plugin, opts: opts });
plugin(this, opts);
return this;
}
try {
var r = nodeResolve.sync(plugin, {
basedir: path.resolve(this._basedir || process.cwd())
});
}
catch (e) {
try {
r = nodeResolve.sync(plugin, {
basedir: commondir(this._entries)
});
}
catch (e) {
this.emit('error', new Error('failed to load plugin ' + plugin));
}
}
var m = require(r);
if (typeof m !== 'function') {
this.emit('error', new Error('plugin ' + plugin + ' exported a '
+ (typeof m) + ', expected a function'
));
return this;
}
this._plugins.push({ plugin: m, opts: opts });
m(this, opts);
return this;
};
Browserify.prototype.deps = function (opts) {
var self = this;
if (!opts) opts = {};
if (self._pending) {
var tr = through2.obj();
self.on('_ready', function () {
self.deps(opts).pipe(tr);
});
return tr;
}
opts.modules = self._builtins;
opts.extensions = self._extensions;
opts.transforms = self._transforms;
if (!opts.basedir) opts.basedir = self._basedir;
var d = mdeps(self.files, opts);
var index = 0;
var tr = d.pipe(through2.obj(write));
d.on('error', tr.emit.bind(tr, 'error'));
d.on('transform', tr.emit.bind(tr, 'transform'));
return tr;
function write (row, encoding, callback) {
if (row.id === excludeModulePath) return callback();
if (self._exclude[row.id]) return callback();
self.emit('dep', row);
if (row.id === emptyModulePath) {
row.source = '';
}
if (/^\ufeff/.test(row.source)) {
row.source = row.source.replace(/^\ufeff/, '');
}
row.deps = Object.keys(row.deps).reduce(function (acc, key) {
if (!self._exclude[key] && !self._external[key]
&& !self._external[row.id] && row.deps[key] !== excludeModulePath) {
acc[key] = row.deps[key];
}
return acc;
}, {});
if (self._expose[row.id]) {
this.push({
id: row.id,
exposed: self._expose[row.id],
deps: {},
source: 'module.exports=require(\''
+ self._hash(row.id) + '\');',
nomap: true
});
}
if (self.exports[row.id]) row.exposed = self.exports[row.id];
if (self._exposeAll) {
row.exposed = self._hash(row.id);
}
// skip adding this file if it is external
if (self._external[row.id]) {
return callback();
}
if (/\.json$/.test(row.id)) {
row = copy(row);
row.source = 'module.exports=' + row.source;
}
var ix = self._entries.indexOf(row.id);
if (row.entry === undefined || self.exports[row.id]) {
row.entry = ix >= 0;
}
if (ix >= 0) row.order = ix;
this.push(row);
callback();
}
};
Browserify.prototype.pack = function (opts) {
if (!opts) opts = {};
var self = this;
var packer = self._browserPack(opts);
var mainModule;
var hashes = {}, depList = {}, depHash = {};
var input = through2.obj(function (row_, encoding, callback) {
var row = copy(row_);
if (opts.debug) {
row.sourceRoot = 'file://localhost';
row.sourceFile = row.id.replace(/\\/g, '/');
}
var dup = hashes[row.hash];
if (dup && sameDeps(depList[dup._id], row.deps)) {
row.source = 'module.exports=require('
+ JSON.stringify(dup.id)
+ ')'
;
row.nomap = true;
}
else if (dup) {
row.source = 'arguments[4]['
+ JSON.stringify(dup.id)
+ '][0].apply(exports,arguments)'
;
}
else hashes[row.hash] = { _id: row.id, id: getId(row) };
if (/^#!/.test(row.source)) row.source = '//' + row.source;
var err = checkSyntax(row.source, row.id);
if (err) return callback(err);
var newId = getId(row);
this.emit('id', newId, row.id);
row.id = getId(row);
if (row.entry) mainModule = mainModule || row.id;
var deps = {};
Object.keys(row.deps || {}).forEach(function (key) {
var file = row.deps[key];
var index = row.indexDeps && row.indexDeps[key];
if (self._exposeAll) {
index = self._hash(file);
}
deps[key] = getId({ id: file, index: index });
});
row.deps = deps;
this.push(row);
callback();
});
function getId (row) {
if (row.exposed) {
return row.exposed;
}
else if (self._external[row.id] || self.exports[row.id]) {
return self._hash(row.id);
}
else if (self._expose[row.id]) {
return row.id;
}
else if (self._fullPaths) {
return row.id;
}
else if (row.index === undefined) {
return row.id;
}
else return row.index;
}
var first = true;
var hasExports = Object.keys(self.exports).length;
var output = through2(write, end);
var sort = depSorter({ index: true });
input.on('data', function (row) { self.emit('row', row) });
return pipeline(through2.obj(hasher), sort, input, packer, output);
function write (buf, encoding, callback) {
if (first) writePrelude.call(this);
first = false;
this.push(buf);
callback();
}
function end (callback) {
if (first) writePrelude.call(this);
if (opts.standalone) {
this.push(
'\n(' + JSON.stringify(mainModule) + ')'
+ umd.postlude(opts.standalone)
);
}
if (opts.debug) this.push('\n');
callback();
}
function writePrelude () {
if (!first) return;
if (opts.standalone) {
return this.push(umd.prelude(opts.standalone).trim() + 'return ');
}
if (hasExports) this.push(
(opts.externalRequireName || 'require') + '='
);
}
function hasher (row, encoding, callback) {
row.hash = hash(row.source);
depList[row.id] = row.deps;
depHash[row.id] = row.hash;
this.push(row);
callback();
}
function sameDeps (a, b, limit) {
var keys = Object.keys(a);
if (keys.length !== Object.keys(b).length) return false;
for (var i = 0; i < keys.length; i++) {
var k = keys[i], ka = a[k], kb = b[k];
var ha = depHash[ka];
var hb = depHash[kb];
var da = depList[ka];
var db = depList[kb];
if (ka === kb) continue;
if (ha !== hb || (!limit && !sameDeps(da, db, 1))) {
return false;
}
}
return true;
}
};
var packageFilter = function (info) {
if (info && typeof info.browserify === 'string' && !info.browser) {
info.browser = info.browserify;
delete info.browserify;
}
return info;
};
Browserify.prototype._resolve = function (id, parent, cb) {
var self = this;
if (!self._bundleExternal && id[0] !== '/' && id[0] !== '.') {
return cb(null, excludeModulePath);
}
if (self._exclude[id]) return cb(null, excludeModulePath);
if (self._ignore[id]) return cb(null, emptyModulePath);
var result = function (file, pkg, x) {
if (self._pending === 0) {
self.emit('file', file, id, parent);
}
if (pkg) {
cb(null, file, pkg, x);
self.emit('package', file, pkg);
}
else findPackage(path.dirname(file), function (err, pkgfile, pkg) {
if (err) return cb(err)
if (pkg && typeof pkg === 'object') {
var pkg_ = copy(pkg);
if (typeof pkg_.browserify === 'string' && !pkg_.browser) {
pkg.browser = pkg_.browserify;
}
if (typeof pkg_.browserify === 'object') {
pkg.browserify = pkg_.browserify;
}
}
cb(null, file, pkg, x);
self.emit('package', file, pkg);
})
};
if (self._mapped[id]) return result(self._mapped[id]);
parent.modules = self._builtins;
parent.extensions = self._extensions;
parent.paths = self._paths;
if (self._external[id]) return cb(null, emptyModulePath);
return self._delegateResolve(id, parent, function(err, file, pkg) {
var cannotFind = /Cannot find module/.test(err && err.message);
if (err && !cannotFind) return cb(err);
if (!file && (self._external[id] || self._external[file])) {
return cb(null, emptyModulePath);
}
else if (!file && self._ignoreMissing) {
self.emit('missing', id, parent);
return cb(null, emptyModulePath);
}
else if (!file) {
return cb(notFound(id, parent.filename))
}
if (self._exclude[file]) return cb(null, excludeModulePath);
if (self._ignore[file]) return cb(null, emptyModulePath);
if (self._external[file]) return result(file, pkg, true);
result(file, pkg);
});
function findPackage (basedir, cb) {
var dirs = parents(basedir);
(function next () {
var dir = dirs.shift();
if (dir === 'node_modules' || dir === undefined) {
return cb(null, null, null);
}
var pkgfile = path.join(dir, 'package.json');
if (self._pkgcache[pkgfile]) {
cb(null, pkgfile, self._pkgcache[pkgfile]);
}
else readPackage(pkgfile, function (err, pkg) {
self._pkgcache[pkgfile] = pkg;
if (err) return next()
else cb(null, pkgfile, pkg)
});
})();
}
function readPackage (pkgfile, cb) {
fs.readFile(pkgfile, function (err, src) {
if (err) return cb(err);
try { var pkg = JSON.parse(src) }
catch (e) {}
cb(null, pkg);
});
}
};
function isBrowserify (x) {
return x && typeof x === 'object' && typeof x.bundle === 'function';
}
function isStream (x) {
return x && typeof x === 'object' && typeof x.pipe === 'function';
}
function notFound (id, parent) {
var err = new Error('module '
+ JSON.stringify(id) + ' not found from '
+ JSON.stringify(parent)
);
err.type = 'not found';
err.filename = id;
err.parent = parent;
return err;
}