index.js 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875
  1. var path = require('path');
  2. var mdeps = require('module-deps');
  3. var depsSort = require('deps-sort');
  4. var bpack = require('browser-pack');
  5. var insertGlobals = require('insert-module-globals');
  6. var syntaxError = require('syntax-error');
  7. var builtins = require('./lib/builtins.js');
  8. var splicer = require('labeled-stream-splicer');
  9. var through = require('through2');
  10. var concat = require('concat-stream');
  11. var inherits = require('inherits');
  12. var EventEmitter = require('events').EventEmitter;
  13. var xtend = require('xtend');
  14. var isArray = Array.isArray;
  15. var defined = require('defined');
  16. var has = require('has');
  17. var sanitize = require('htmlescape').sanitize;
  18. var shasum = require('shasum-object');
  19. var bresolve = require('browser-resolve');
  20. var resolve = require('resolve');
  21. var readonly = require('read-only-stream');
  22. module.exports = Browserify;
  23. inherits(Browserify, EventEmitter);
  24. var fs = require('fs');
  25. var path = require('path');
  26. var cachedPathRelative = require('cached-path-relative');
  27. var paths = {
  28. empty: path.join(__dirname, 'lib/_empty.js')
  29. };
  30. function Browserify (files, opts) {
  31. var self = this;
  32. if (!(this instanceof Browserify)) return new Browserify(files, opts);
  33. if (!opts) opts = {};
  34. if (typeof files === 'string' || isArray(files) || isStream(files)) {
  35. opts = xtend(opts, { entries: [].concat(opts.entries || [], files) });
  36. }
  37. else opts = xtend(files, opts);
  38. if (opts.node) {
  39. opts.bare = true;
  40. opts.browserField = false;
  41. }
  42. if (opts.bare) {
  43. opts.builtins = false;
  44. opts.commondir = false;
  45. if (opts.insertGlobalVars === undefined) {
  46. opts.insertGlobalVars = {}
  47. Object.keys(insertGlobals.vars).forEach(function (name) {
  48. if (name !== '__dirname' && name !== '__filename') {
  49. opts.insertGlobalVars[name] = undefined;
  50. }
  51. })
  52. }
  53. }
  54. self._options = opts;
  55. if (opts.noparse) opts.noParse = opts.noparse;
  56. if (opts.basedir !== undefined && typeof opts.basedir !== 'string') {
  57. throw new Error('opts.basedir must be either undefined or a string.');
  58. }
  59. opts.dedupe = opts.dedupe === false ? false : true;
  60. self._external = [];
  61. self._exclude = [];
  62. self._ignore = [];
  63. self._expose = {};
  64. self._hashes = {};
  65. self._pending = 0;
  66. self._transformOrder = 0;
  67. self._transformPending = 0;
  68. self._transforms = [];
  69. self._entryOrder = 0;
  70. self._ticked = false;
  71. var browserField = opts.browserField
  72. self._bresolve = browserField === false
  73. ? function (id, opts, cb) {
  74. if (!opts.basedir) opts.basedir = path.dirname(opts.filename)
  75. resolve(id, opts, cb)
  76. }
  77. : typeof browserField === 'string'
  78. ? function (id, opts, cb) {
  79. opts.browser = browserField
  80. bresolve(id, opts, cb)
  81. }
  82. : bresolve
  83. ;
  84. self._syntaxCache = {};
  85. var ignoreTransform = [].concat(opts.ignoreTransform).filter(Boolean);
  86. self._filterTransform = function (tr) {
  87. if (isArray(tr)) {
  88. return ignoreTransform.indexOf(tr[0]) === -1;
  89. }
  90. return ignoreTransform.indexOf(tr) === -1;
  91. };
  92. self.pipeline = self._createPipeline(opts);
  93. [].concat(opts.transform).filter(Boolean).filter(self._filterTransform)
  94. .forEach(function (tr) {
  95. self.transform(tr);
  96. });
  97. [].concat(opts.entries).filter(Boolean).forEach(function (file) {
  98. self.add(file, { basedir: opts.basedir });
  99. });
  100. [].concat(opts.require).filter(Boolean).forEach(function (file) {
  101. self.require(file, { basedir: opts.basedir });
  102. });
  103. [].concat(opts.plugin).filter(Boolean).forEach(function (p) {
  104. self.plugin(p, { basedir: opts.basedir });
  105. });
  106. }
  107. Browserify.prototype.require = function (file, opts) {
  108. var self = this;
  109. if (isArray(file)) {
  110. file.forEach(function (x) {
  111. if (typeof x === 'object') {
  112. self.require(x.file, xtend(opts, x));
  113. }
  114. else self.require(x, opts);
  115. });
  116. return this;
  117. }
  118. if (!opts) opts = {};
  119. var basedir = defined(opts.basedir, self._options.basedir, process.cwd());
  120. var expose = opts.expose;
  121. if (file === expose && /^[\.]/.test(expose)) {
  122. expose = '/' + relativePath(basedir, expose);
  123. }
  124. if (expose === undefined && this._options.exposeAll) {
  125. expose = true;
  126. }
  127. if (expose === true) {
  128. expose = '/' + relativePath(basedir, file);
  129. }
  130. if (isStream(file)) {
  131. self._pending ++;
  132. var order = self._entryOrder ++;
  133. file.pipe(concat(function (buf) {
  134. var filename = opts.file || file.file || path.join(
  135. basedir,
  136. '_stream_' + order + '.js'
  137. );
  138. var id = file.id || expose || filename;
  139. if (expose || opts.entry === false) {
  140. self._expose[id] = filename;
  141. }
  142. if (!opts.entry && self._options.exports === undefined) {
  143. self._bpack.hasExports = true;
  144. }
  145. var rec = {
  146. source: buf.toString('utf8'),
  147. entry: defined(opts.entry, false),
  148. file: filename,
  149. id: id
  150. };
  151. if (rec.entry) rec.order = order;
  152. if (rec.transform === false) rec.transform = false;
  153. self.pipeline.write(rec);
  154. if (-- self._pending === 0) self.emit('_ready');
  155. }));
  156. return this;
  157. }
  158. var row;
  159. if (typeof file === 'object') {
  160. row = xtend(file, opts);
  161. }
  162. else if (!opts.entry && isExternalModule(file)) {
  163. // external module or builtin
  164. row = xtend(opts, { id: expose || file, file: file });
  165. }
  166. else {
  167. row = xtend(opts, { file: path.resolve(basedir, file) });
  168. }
  169. if (!row.id) {
  170. row.id = expose || row.file;
  171. }
  172. if (expose || !row.entry) {
  173. // Make this available to mdeps so that it can assign the value when it
  174. // resolves the pathname.
  175. row.expose = row.id;
  176. }
  177. if (opts.external) return self.external(file, opts);
  178. if (row.entry === undefined) row.entry = false;
  179. if (!row.entry && self._options.exports === undefined) {
  180. self._bpack.hasExports = true;
  181. }
  182. if (row.entry) row.order = self._entryOrder ++;
  183. if (opts.transform === false) row.transform = false;
  184. self.pipeline.write(row);
  185. return self;
  186. };
  187. Browserify.prototype.add = function (file, opts) {
  188. var self = this;
  189. if (!opts) opts = {};
  190. if (isArray(file)) {
  191. file.forEach(function (x) { self.add(x, opts) });
  192. return this;
  193. }
  194. return this.require(file, xtend({ entry: true, expose: false }, opts));
  195. };
  196. Browserify.prototype.external = function (file, opts) {
  197. var self = this;
  198. if (isArray(file)) {
  199. file.forEach(function (f) {
  200. if (typeof f === 'object') {
  201. self.external(f, xtend(opts, f));
  202. }
  203. else self.external(f, opts)
  204. });
  205. return this;
  206. }
  207. if (file && typeof file === 'object' && typeof file.bundle === 'function') {
  208. var b = file;
  209. self._pending ++;
  210. var bdeps = {};
  211. var blabels = {};
  212. b.on('label', function (prev, id) {
  213. self._external.push(id);
  214. if (prev !== id) {
  215. blabels[prev] = id;
  216. self._external.push(prev);
  217. }
  218. });
  219. b.pipeline.get('deps').push(through.obj(function (row, enc, next) {
  220. bdeps = xtend(bdeps, row.deps);
  221. this.push(row);
  222. next();
  223. }));
  224. self.on('dep', function (row) {
  225. Object.keys(row.deps).forEach(function (key) {
  226. var prev = bdeps[key];
  227. if (prev) {
  228. var id = blabels[prev];
  229. if (id) {
  230. row.indexDeps[key] = id;
  231. }
  232. }
  233. });
  234. });
  235. b.pipeline.get('label').once('end', function () {
  236. if (-- self._pending === 0) self.emit('_ready');
  237. });
  238. return this;
  239. }
  240. if (!opts) opts = {};
  241. var basedir = defined(opts.basedir, process.cwd());
  242. this._external.push(file);
  243. this._external.push('/' + relativePath(basedir, file));
  244. return this;
  245. };
  246. Browserify.prototype.exclude = function (file, opts) {
  247. if (!opts) opts = {};
  248. if (isArray(file)) {
  249. var self = this;
  250. file.forEach(function(file) {
  251. self.exclude(file, opts);
  252. });
  253. return this;
  254. }
  255. var basedir = defined(opts.basedir, process.cwd());
  256. this._exclude.push(file);
  257. this._exclude.push('/' + relativePath(basedir, file));
  258. return this;
  259. };
  260. Browserify.prototype.ignore = function (file, opts) {
  261. if (!opts) opts = {};
  262. if (isArray(file)) {
  263. var self = this;
  264. file.forEach(function(file) {
  265. self.ignore(file, opts);
  266. });
  267. return this;
  268. }
  269. var basedir = defined(opts.basedir, process.cwd());
  270. // Handle relative paths
  271. if (file[0] === '.') {
  272. this._ignore.push(path.resolve(basedir, file));
  273. }
  274. else {
  275. this._ignore.push(file);
  276. }
  277. return this;
  278. };
  279. Browserify.prototype.transform = function (tr, opts) {
  280. var self = this;
  281. if (typeof opts === 'function' || typeof opts === 'string') {
  282. tr = [ opts, tr ];
  283. }
  284. if (isArray(tr)) {
  285. opts = tr[1];
  286. tr = tr[0];
  287. }
  288. //if the bundler is ignoring this transform
  289. if (typeof tr === 'string' && !self._filterTransform(tr)) {
  290. return this;
  291. }
  292. function resolved () {
  293. self._transforms[order] = rec;
  294. -- self._pending;
  295. if (-- self._transformPending === 0) {
  296. self._transforms.forEach(function (transform) {
  297. self.pipeline.write(transform);
  298. });
  299. if (self._pending === 0) {
  300. self.emit('_ready');
  301. }
  302. }
  303. }
  304. if (!opts) opts = {};
  305. opts._flags = '_flags' in opts ? opts._flags : self._options;
  306. var basedir = defined(opts.basedir, this._options.basedir, process.cwd());
  307. var order = self._transformOrder ++;
  308. self._pending ++;
  309. self._transformPending ++;
  310. var rec = {
  311. transform: tr,
  312. options: opts,
  313. global: opts.global
  314. };
  315. if (typeof tr === 'string') {
  316. var topts = {
  317. basedir: basedir,
  318. paths: (self._options.paths || []).map(function (p) {
  319. return path.resolve(basedir, p);
  320. })
  321. };
  322. resolve(tr, topts, function (err, res) {
  323. if (err) return self.emit('error', err);
  324. rec.transform = res;
  325. resolved();
  326. });
  327. }
  328. else process.nextTick(resolved);
  329. return this;
  330. };
  331. Browserify.prototype.plugin = function (p, opts) {
  332. if (isArray(p)) {
  333. opts = p[1];
  334. p = p[0];
  335. }
  336. if (!opts) opts = {};
  337. var basedir = defined(opts.basedir, this._options.basedir, process.cwd());
  338. if (typeof p === 'function') {
  339. p(this, opts);
  340. }
  341. else {
  342. var pfile = resolve.sync(String(p), { basedir: basedir })
  343. var f = require(pfile);
  344. if (typeof f !== 'function') {
  345. throw new Error('plugin ' + p + ' should export a function');
  346. }
  347. f(this, opts);
  348. }
  349. return this;
  350. };
  351. Browserify.prototype._createPipeline = function (opts) {
  352. var self = this;
  353. if (!opts) opts = {};
  354. this._mdeps = this._createDeps(opts);
  355. this._mdeps.on('file', function (file, id) {
  356. pipeline.emit('file', file, id);
  357. self.emit('file', file, id);
  358. });
  359. this._mdeps.on('package', function (pkg) {
  360. pipeline.emit('package', pkg);
  361. self.emit('package', pkg);
  362. });
  363. this._mdeps.on('transform', function (tr, file) {
  364. pipeline.emit('transform', tr, file);
  365. self.emit('transform', tr, file);
  366. });
  367. var dopts = {
  368. index: !opts.fullPaths && !opts.exposeAll,
  369. dedupe: opts.dedupe,
  370. expose: this._expose
  371. };
  372. this._bpack = bpack(xtend(opts, { raw: true }));
  373. var pipeline = splicer.obj([
  374. 'record', [ this._recorder() ],
  375. 'deps', [ this._mdeps ],
  376. 'json', [ this._json() ],
  377. 'unbom', [ this._unbom() ],
  378. 'unshebang', [ this._unshebang() ],
  379. 'syntax', [ this._syntax() ],
  380. 'sort', [ depsSort(dopts) ],
  381. 'dedupe', [ this._dedupe() ],
  382. 'label', [ this._label(opts) ],
  383. 'emit-deps', [ this._emitDeps() ],
  384. 'debug', [ this._debug(opts) ],
  385. 'pack', [ this._bpack ],
  386. 'wrap', []
  387. ]);
  388. if (opts.exposeAll) {
  389. var basedir = defined(opts.basedir, process.cwd());
  390. pipeline.get('deps').push(through.obj(function (row, enc, next) {
  391. if (self._external.indexOf(row.id) >= 0) return next();
  392. if (self._external.indexOf(row.file) >= 0) return next();
  393. if (isAbsolutePath(row.id)) {
  394. row.id = '/' + relativePath(basedir, row.file);
  395. }
  396. Object.keys(row.deps || {}).forEach(function (key) {
  397. row.deps[key] = '/' + relativePath(basedir, row.deps[key]);
  398. });
  399. this.push(row);
  400. next();
  401. }));
  402. }
  403. return pipeline;
  404. };
  405. Browserify.prototype._createDeps = function (opts) {
  406. var self = this;
  407. var mopts = xtend(opts);
  408. var basedir = defined(opts.basedir, process.cwd());
  409. // Let mdeps populate these values since it will be resolving file paths
  410. // anyway.
  411. mopts.expose = this._expose;
  412. mopts.extensions = [ '.js', '.json' ].concat(mopts.extensions || []);
  413. self._extensions = mopts.extensions;
  414. mopts.transform = [];
  415. mopts.transformKey = defined(opts.transformKey, [ 'browserify', 'transform' ]);
  416. mopts.postFilter = function (id, file, pkg) {
  417. if (opts.postFilter && !opts.postFilter(id, file, pkg)) return false;
  418. if (self._external.indexOf(file) >= 0) return false;
  419. if (self._exclude.indexOf(file) >= 0) return false;
  420. //filter transforms on module dependencies
  421. if (pkg && pkg.browserify && pkg.browserify.transform) {
  422. //In edge cases it may be a string
  423. pkg.browserify.transform = [].concat(pkg.browserify.transform)
  424. .filter(Boolean)
  425. .filter(self._filterTransform);
  426. }
  427. return true;
  428. };
  429. mopts.filter = function (id) {
  430. if (opts.filter && !opts.filter(id)) return false;
  431. if (self._external.indexOf(id) >= 0) return false;
  432. if (self._exclude.indexOf(id) >= 0) return false;
  433. if (opts.bundleExternal === false && isExternalModule(id)) {
  434. return false;
  435. }
  436. return true;
  437. };
  438. mopts.resolve = function (id, parent, cb) {
  439. if (self._ignore.indexOf(id) >= 0) return cb(null, paths.empty, {});
  440. self._bresolve(id, parent, function (err, file, pkg) {
  441. if (file && self._ignore.indexOf(file) >= 0) {
  442. return cb(null, paths.empty, {});
  443. }
  444. if (file && self._ignore.length) {
  445. var nm = file.replace(/\\/g, '/').split('/node_modules/')[1];
  446. if (nm) {
  447. nm = nm.split('/')[0];
  448. if (self._ignore.indexOf(nm) >= 0) {
  449. return cb(null, paths.empty, {});
  450. }
  451. }
  452. }
  453. if (file) {
  454. var ex = '/' + relativePath(basedir, file);
  455. if (self._external.indexOf(ex) >= 0) {
  456. return cb(null, ex);
  457. }
  458. if (self._exclude.indexOf(ex) >= 0) {
  459. return cb(null, ex);
  460. }
  461. if (self._ignore.indexOf(ex) >= 0) {
  462. return cb(null, paths.empty, {});
  463. }
  464. }
  465. if (err) cb(err, file, pkg)
  466. else if (file) {
  467. if (opts.preserveSymlinks && parent.id !== self._mdeps.top.id) {
  468. return cb(err, path.resolve(file), pkg, file)
  469. }
  470. fs.realpath(file, function (err, res) {
  471. cb(err, res, pkg, file);
  472. });
  473. } else cb(err, null, pkg)
  474. });
  475. };
  476. if (opts.builtins === false) {
  477. mopts.modules = {};
  478. self._exclude.push.apply(self._exclude, Object.keys(builtins));
  479. }
  480. else if (opts.builtins && isArray(opts.builtins)) {
  481. mopts.modules = {};
  482. opts.builtins.forEach(function (key) {
  483. mopts.modules[key] = builtins[key];
  484. });
  485. }
  486. else if (opts.builtins && typeof opts.builtins === 'object') {
  487. mopts.modules = opts.builtins;
  488. }
  489. else mopts.modules = xtend(builtins);
  490. Object.keys(builtins).forEach(function (key) {
  491. if (!has(mopts.modules, key)) self._exclude.push(key);
  492. });
  493. mopts.globalTransform = [];
  494. if (!this._bundled) {
  495. this.once('bundle', function () {
  496. self.pipeline.write({
  497. transform: globalTr,
  498. global: true,
  499. options: {}
  500. });
  501. });
  502. }
  503. var no = [].concat(opts.noParse).filter(Boolean);
  504. var absno = no.filter(function(x) {
  505. return typeof x === 'string';
  506. }).map(function (x) {
  507. return path.resolve(basedir, x);
  508. });
  509. function globalTr (file) {
  510. if (opts.detectGlobals === false) return through();
  511. if (opts.noParse === true) return through();
  512. if (no.indexOf(file) >= 0) return through();
  513. if (absno.indexOf(file) >= 0) return through();
  514. var parts = file.replace(/\\/g, '/').split('/node_modules/');
  515. for (var i = 0; i < no.length; i++) {
  516. if (typeof no[i] === 'function' && no[i](file)) {
  517. return through();
  518. }
  519. else if (no[i] === parts[parts.length-1].split('/')[0]) {
  520. return through();
  521. }
  522. else if (no[i] === parts[parts.length-1]) {
  523. return through();
  524. }
  525. }
  526. if (opts.commondir === false && opts.builtins === false) {
  527. opts.insertGlobalVars = xtend({
  528. __dirname: function(file, basedir) {
  529. var dir = path.dirname(path.relative(basedir, file));
  530. return 'require("path").join(__dirname,' + dir.split(path.sep).map(JSON.stringify).join(',') + ')';
  531. },
  532. __filename: function(file, basedir) {
  533. var filename = path.relative(basedir, file);
  534. return 'require("path").join(__dirname,' + filename.split(path.sep).map(JSON.stringify).join(',') + ')';
  535. }
  536. }, opts.insertGlobalVars);
  537. }
  538. var vars = xtend({
  539. process: function () { return "require('_process')" },
  540. }, opts.insertGlobalVars);
  541. if (opts.bundleExternal === false) {
  542. vars.process = undefined;
  543. vars.buffer = undefined;
  544. }
  545. return insertGlobals(file, xtend(opts, {
  546. debug: opts.debug,
  547. always: opts.insertGlobals,
  548. basedir: opts.commondir === false && isArray(opts.builtins)
  549. ? '/'
  550. : opts.basedir || process.cwd()
  551. ,
  552. vars: vars
  553. }));
  554. }
  555. return mdeps(mopts);
  556. };
  557. Browserify.prototype._recorder = function (opts) {
  558. var self = this;
  559. var ended = false;
  560. this._recorded = [];
  561. if (!this._ticked) {
  562. process.nextTick(function () {
  563. self._ticked = true;
  564. self._recorded.forEach(function (row) {
  565. stream.push(row);
  566. });
  567. if (ended) stream.push(null);
  568. });
  569. }
  570. var stream = through.obj(write, end);
  571. return stream;
  572. function write (row, enc, next) {
  573. self._recorded.push(row);
  574. if (self._ticked) this.push(row);
  575. next();
  576. }
  577. function end () {
  578. ended = true;
  579. if (self._ticked) this.push(null);
  580. }
  581. };
  582. Browserify.prototype._json = function () {
  583. return through.obj(function (row, enc, next) {
  584. if (/\.json$/.test(row.file)) {
  585. var sanitizedString = sanitize(row.source);
  586. try {
  587. // check json validity
  588. JSON.parse(sanitizedString);
  589. row.source = 'module.exports=' + sanitizedString;
  590. } catch (err) {
  591. err.message = 'While parsing ' + (row.file || row.id) + ': ' + err.message
  592. this.emit('error', err);
  593. return;
  594. }
  595. }
  596. this.push(row);
  597. next();
  598. });
  599. };
  600. Browserify.prototype._unbom = function () {
  601. return through.obj(function (row, enc, next) {
  602. if (/^\ufeff/.test(row.source)) {
  603. row.source = row.source.replace(/^\ufeff/, '');
  604. }
  605. this.push(row);
  606. next();
  607. });
  608. };
  609. Browserify.prototype._unshebang = function () {
  610. return through.obj(function (row, enc, next) {
  611. if (/^#!/.test(row.source)) {
  612. row.source = row.source.replace(/^#![^\n]*\n/, '');
  613. }
  614. this.push(row);
  615. next();
  616. });
  617. };
  618. Browserify.prototype._syntax = function () {
  619. var self = this;
  620. return through.obj(function (row, enc, next) {
  621. var h = shasum(row.source);
  622. if (typeof self._syntaxCache[h] === 'undefined') {
  623. var err = syntaxError(row.source, row.file || row.id);
  624. if (err) return this.emit('error', err);
  625. self._syntaxCache[h] = true;
  626. }
  627. this.push(row);
  628. next();
  629. });
  630. };
  631. Browserify.prototype._dedupe = function () {
  632. return through.obj(function (row, enc, next) {
  633. if (!row.dedupeIndex && row.dedupe) {
  634. row.source = 'arguments[4]['
  635. + JSON.stringify(row.dedupe)
  636. + '][0].apply(exports,arguments)'
  637. ;
  638. row.nomap = true;
  639. }
  640. else if (row.dedupeIndex) {
  641. row.source = 'arguments[4]['
  642. + JSON.stringify(row.dedupeIndex)
  643. + '][0].apply(exports,arguments)'
  644. ;
  645. row.nomap = true;
  646. }
  647. if (row.dedupeIndex && row.indexDeps) {
  648. row.indexDeps.dup = row.dedupeIndex;
  649. }
  650. this.push(row);
  651. next();
  652. });
  653. };
  654. Browserify.prototype._label = function (opts) {
  655. var self = this;
  656. var basedir = defined(opts.basedir, process.cwd());
  657. return through.obj(function (row, enc, next) {
  658. var prev = row.id;
  659. if (self._external.indexOf(row.id) >= 0) return next();
  660. if (self._external.indexOf('/' + relativePath(basedir, row.id)) >= 0) {
  661. return next();
  662. }
  663. if (self._external.indexOf(row.file) >= 0) return next();
  664. if (row.index) row.id = row.index;
  665. self.emit('label', prev, row.id);
  666. if (row.indexDeps) row.deps = row.indexDeps || {};
  667. Object.keys(row.deps).forEach(function (key) {
  668. if (self._expose[key]) {
  669. row.deps[key] = key;
  670. return;
  671. }
  672. var afile = path.resolve(path.dirname(row.file), key);
  673. var rfile = '/' + relativePath(basedir, afile);
  674. if (self._external.indexOf(rfile) >= 0) {
  675. row.deps[key] = rfile;
  676. }
  677. if (self._external.indexOf(afile) >= 0) {
  678. row.deps[key] = rfile;
  679. }
  680. if (self._external.indexOf(key) >= 0) {
  681. row.deps[key] = key;
  682. return;
  683. }
  684. for (var i = 0; i < self._extensions.length; i++) {
  685. var ex = self._extensions[i];
  686. if (self._external.indexOf(rfile + ex) >= 0) {
  687. row.deps[key] = rfile + ex;
  688. break;
  689. }
  690. }
  691. });
  692. if (row.entry || row.expose) {
  693. self._bpack.standaloneModule = row.id;
  694. }
  695. this.push(row);
  696. next();
  697. });
  698. };
  699. Browserify.prototype._emitDeps = function () {
  700. var self = this;
  701. return through.obj(function (row, enc, next) {
  702. self.emit('dep', row);
  703. this.push(row);
  704. next();
  705. })
  706. };
  707. Browserify.prototype._debug = function (opts) {
  708. var basedir = defined(opts.basedir, process.cwd());
  709. return through.obj(function (row, enc, next) {
  710. if (opts.debug) {
  711. row.sourceRoot = 'file://localhost';
  712. row.sourceFile = relativePath(basedir, row.file);
  713. }
  714. this.push(row);
  715. next();
  716. });
  717. };
  718. Browserify.prototype.reset = function (opts) {
  719. if (!opts) opts = {};
  720. var hadExports = this._bpack.hasExports;
  721. this.pipeline = this._createPipeline(xtend(opts, this._options));
  722. this._bpack.hasExports = hadExports;
  723. this._entryOrder = 0;
  724. this._bundled = false;
  725. this.emit('reset');
  726. };
  727. Browserify.prototype.bundle = function (cb) {
  728. var self = this;
  729. if (cb && typeof cb === 'object') {
  730. throw new Error(
  731. 'bundle() no longer accepts option arguments.\n'
  732. + 'Move all option arguments to the browserify() constructor.'
  733. );
  734. }
  735. if (this._bundled) {
  736. var recorded = this._recorded;
  737. this.reset();
  738. recorded.forEach(function (x) {
  739. self.pipeline.write(x);
  740. });
  741. }
  742. var output = readonly(this.pipeline);
  743. if (cb) {
  744. output.on('error', cb);
  745. output.pipe(concat(function (body) {
  746. cb(null, body);
  747. }));
  748. }
  749. function ready () {
  750. self.emit('bundle', output);
  751. self.pipeline.end();
  752. }
  753. if (this._pending === 0) ready();
  754. else this.once('_ready', ready);
  755. this._bundled = true;
  756. return output;
  757. };
  758. function isStream (s) { return s && typeof s.pipe === 'function' }
  759. function isAbsolutePath (file) {
  760. var regexp = process.platform === 'win32' ?
  761. /^\w:/ :
  762. /^\//;
  763. return regexp.test(file);
  764. }
  765. function isExternalModule (file) {
  766. var regexp = process.platform === 'win32' ?
  767. /^(\.|\w:)/ :
  768. /^[\/.]/;
  769. return !regexp.test(file);
  770. }
  771. function relativePath (from, to) {
  772. // Replace \ with / for OS-independent behavior
  773. return cachedPathRelative(from, to).replace(/\\/g, '/');
  774. }