UNPKG

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