UNPKG

45.9 kBJavaScriptView Raw
1'use strict';
2
3var _path = require('path');
4var sander = require('sander');
5var MagicString = require('magic-string');
6MagicString = ('default' in MagicString ? MagicString['default'] : MagicString);
7var acorn = require('acorn');
8
9var keys = Object.keys;
10
11var hasOwnProp = Object.prototype.hasOwnProperty;function has(obj, prop) {
12 return hasOwnProp.call(obj, prop);
13}
14
15function blank() {
16 return Object.create(null);
17}
18
19function sequence(arr, callback) {
20 var len = arr.length;
21 var results = new Array(len);
22
23 var promise = sander.Promise.resolve();
24
25 function next(i) {
26 return promise.then(function () {
27 return callback(arr[i], i);
28 }).then(function (result) {
29 return results[i] = result;
30 });
31 }
32
33 var i = undefined;
34
35 for (i = 0; i < len; i += 1) {
36 promise = next(i);
37 }
38
39 return promise.then(function () {
40 return results;
41 });
42}
43
44function getName(x) {
45 return x.name;
46}
47
48function quoteId(x) {
49 return "'" + x.id + "'";
50}
51
52function req(x) {
53 return "require('" + x.id + "')";
54}
55
56function isImportDeclaration(statement) {
57 return statement.isImportDeclaration;
58}
59
60function isExportDeclaration(statement) {
61 return statement.isExportDeclaration;
62}
63
64function getLocation(source, charIndex) {
65 var lines = source.split('\n');
66 var len = lines.length;
67
68 var lineStart = 0;
69 var i = undefined;
70
71 for (i = 0; i < len; i += 1) {
72 var line = lines[i];
73 var lineEnd = lineStart + line.length + 1; // +1 for newline
74
75 if (lineEnd > charIndex) {
76 return { line: i + 1, column: charIndex - lineStart };
77 }
78
79 lineStart = lineEnd;
80 }
81
82 throw new Error('Could not determine location of character');
83}
84
85var shouldSkip = undefined;
86var shouldAbort = undefined;
87function walk(ast, _ref) {
88 var enter = _ref.enter;
89 var leave = _ref.leave;
90
91 shouldAbort = false;
92 visit(ast, null, enter, leave);
93}
94
95var context = {
96 skip: function () {
97 return shouldSkip = true;
98 },
99 abort: function () {
100 return shouldAbort = true;
101 }
102};
103
104var childKeys = {};
105
106var toString = Object.prototype.toString;
107
108function isArray(thing) {
109 return toString.call(thing) === '[object Array]';
110}
111
112function visit(node, parent, enter, leave) {
113 if (!node || shouldAbort) return;
114
115 if (enter) {
116 shouldSkip = false;
117 enter.call(context, node, parent);
118 if (shouldSkip || shouldAbort) return;
119 }
120
121 var keys = childKeys[node.type] || (childKeys[node.type] = Object.keys(node).filter(function (key) {
122 return typeof node[key] === 'object';
123 }));
124
125 var key = undefined,
126 value = undefined,
127 i = undefined,
128 j = undefined;
129
130 i = keys.length;
131 while (i--) {
132 key = keys[i];
133 value = node[key];
134
135 if (isArray(value)) {
136 j = value.length;
137 while (j--) {
138 visit(value[j], node, enter, leave);
139 }
140 } else if (value && value.type) {
141 visit(value, node, enter, leave);
142 }
143 }
144
145 if (leave && !shouldAbort) {
146 leave(node, parent);
147 }
148}
149
150function Scope___classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
151
152var Scope = (function () {
153 function Scope(options) {
154 Scope___classCallCheck(this, Scope);
155
156 options = options || {};
157
158 this.parent = options.parent;
159 this.depth = this.parent ? this.parent.depth + 1 : 0;
160 this.names = options.params || [];
161 this.isBlockScope = !!options.block;
162 }
163
164 Scope.prototype.add = function add(name, isBlockDeclaration) {
165 if (!isBlockDeclaration && this.isBlockScope) {
166 // it's a `var` or function declaration, and this
167 // is a block scope, so we need to go up
168 this.parent.add(name, isBlockDeclaration);
169 } else {
170 this.names.push(name);
171 }
172 };
173
174 Scope.prototype.contains = function contains(name) {
175 return !!this.findDefiningScope(name);
176 };
177
178 Scope.prototype.findDefiningScope = function findDefiningScope(name) {
179 if (~this.names.indexOf(name)) {
180 return this;
181 }
182
183 if (this.parent) {
184 return this.parent.findDefiningScope(name);
185 }
186
187 return null;
188 };
189
190 return Scope;
191})();
192
193function Statement___classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
194
195var Statement__emptyArrayPromise = Promise.resolve([]);
196
197var Statement = (function () {
198 function Statement(node, magicString, module) {
199 Statement___classCallCheck(this, Statement);
200
201 this.node = node;
202 this.module = module;
203 this.magicString = magicString;
204
205 this.scope = new Scope();
206 this.defines = {};
207 this.modifies = {};
208 this.dependsOn = {};
209
210 this.isIncluded = false;
211
212 this.leadingComments = [];
213 this.trailingComment = null;
214 this.margin = [0, 0];
215
216 // some facts about this statement...
217 this.isImportDeclaration = node.type === 'ImportDeclaration';
218 this.isExportDeclaration = /^Export/.test(node.type);
219 }
220
221 Statement.prototype.analyse = function analyse() {
222 var _this = this;
223
224 if (this.isImportDeclaration) return; // nothing to analyse
225
226 var statement = this; // TODO use arrow functions instead
227 var magicString = this.magicString;
228
229 var scope = this.scope;
230
231 function addToScope(declarator) {
232 var name = declarator.id.name;
233 scope.add(name, false);
234
235 if (!scope.parent) {
236 statement.defines[name] = true;
237 }
238 }
239
240 function addToBlockScope(declarator) {
241 var name = declarator.id.name;
242 scope.add(name, true);
243
244 if (!scope.parent) {
245 statement.defines[name] = true;
246 }
247 }
248
249 walk(this.node, {
250 enter: function (node) {
251 var newScope = undefined;
252
253 magicString.addSourcemapLocation(node.start);
254
255 switch (node.type) {
256 case 'FunctionExpression':
257 case 'FunctionDeclaration':
258 case 'ArrowFunctionExpression':
259 var names = node.params.map(getName);
260
261 if (node.type === 'FunctionDeclaration') {
262 addToScope(node);
263 } else if (node.type === 'FunctionExpression' && node.id) {
264 names.push(node.id.name);
265 }
266
267 newScope = new Scope({
268 parent: scope,
269 params: names, // TODO rest params?
270 block: false
271 });
272
273 break;
274
275 case 'BlockStatement':
276 newScope = new Scope({
277 parent: scope,
278 block: true
279 });
280
281 break;
282
283 case 'CatchClause':
284 newScope = new Scope({
285 parent: scope,
286 params: [node.param.name],
287 block: true
288 });
289
290 break;
291
292 case 'VariableDeclaration':
293 node.declarations.forEach(node.kind === 'let' ? addToBlockScope : addToScope); // TODO const?
294 break;
295
296 case 'ClassDeclaration':
297 addToScope(node);
298 break;
299 }
300
301 if (newScope) {
302 Object.defineProperty(node, '_scope', { value: newScope });
303 scope = newScope;
304 }
305 },
306 leave: function (node) {
307 if (node._scope) {
308 scope = scope.parent;
309 }
310 }
311 });
312
313 if (!this.isImportDeclaration) {
314 walk(this.node, {
315 enter: function (node, parent) {
316 if (node._scope) scope = node._scope;
317
318 _this.checkForReads(scope, node, parent);
319 _this.checkForWrites(scope, node);
320 },
321 leave: function (node) {
322 if (node._scope) scope = scope.parent;
323 }
324 });
325 }
326 };
327
328 Statement.prototype.checkForReads = function checkForReads(scope, node, parent) {
329 if (node.type === 'Identifier') {
330 // disregard the `bar` in `foo.bar` - these appear as Identifier nodes
331 if (parent.type === 'MemberExpression' && node !== parent.object) {
332 return;
333 }
334
335 // disregard the `bar` in { bar: foo }
336 if (parent.type === 'Property' && node !== parent.value) {
337 return;
338 }
339
340 var definingScope = scope.findDefiningScope(node.name);
341
342 if ((!definingScope || definingScope.depth === 0) && !this.defines[node.name]) {
343 this.dependsOn[node.name] = true;
344 }
345 }
346 };
347
348 Statement.prototype.checkForWrites = function checkForWrites(scope, node) {
349 var _this2 = this;
350
351 var addNode = function (node, disallowImportReassignments) {
352 var depth = 0; // determine whether we're illegally modifying a binding or namespace
353
354 while (node.type === 'MemberExpression') {
355 node = node.object;
356 depth += 1;
357 }
358
359 // disallow assignments/updates to imported bindings and namespaces
360 if (disallowImportReassignments) {
361 var importSpecifier = _this2.module.imports[node.name];
362
363 if (importSpecifier && !scope.contains(node.name)) {
364 var minDepth = importSpecifier.name === '*' ? 2 : // cannot do e.g. `namespace.foo = bar`
365 1; // cannot do e.g. `foo = bar`, but `foo.bar = bar` is fine
366
367 if (depth < minDepth) {
368 var err = new Error('Illegal reassignment to import \'' + node.name + '\'');
369 err.file = _this2.module.path;
370 err.loc = getLocation(_this2.module.magicString.toString(), node.start);
371 throw err;
372 }
373 }
374 }
375
376 if (node.type !== 'Identifier') {
377 return;
378 }
379
380 _this2.modifies[node.name] = true;
381 };
382
383 if (node.type === 'AssignmentExpression') {
384 addNode(node.left, true);
385 } else if (node.type === 'UpdateExpression') {
386 addNode(node.argument, true);
387 } else if (node.type === 'CallExpression') {
388 node.arguments.forEach(function (arg) {
389 return addNode(arg, false);
390 });
391 }
392 };
393
394 Statement.prototype.expand = function expand() {
395 var _this3 = this;
396
397 if (this.isIncluded) return Statement__emptyArrayPromise;
398 this.isIncluded = true;
399
400 var result = [];
401
402 // We have a statement, and it hasn't been included yet. First, include
403 // the statements it depends on
404 var dependencies = Object.keys(this.dependsOn);
405
406 return sequence(dependencies, function (name) {
407 return _this3.module.define(name).then(function (definition) {
408 result.push.apply(result, definition);
409 });
410 })
411
412 // then include the statement itself
413 .then(function () {
414 result.push(_this3);
415 })
416
417 // then include any statements that could modify the
418 // thing(s) this statement defines
419 .then(function () {
420 return sequence(keys(_this3.defines), function (name) {
421 var modifications = has(_this3.module.modifications, name) && _this3.module.modifications[name];
422
423 if (modifications) {
424 return sequence(modifications, function (statement) {
425 if (!statement.isIncluded) {
426 return statement.expand().then(function (statements) {
427 result.push.apply(result, statements);
428 });
429 }
430 });
431 }
432 });
433 })
434
435 // the `result` is an array of statements needed to define `name`
436 .then(function () {
437 return result;
438 });
439 };
440
441 Statement.prototype.replaceIdentifiers = function replaceIdentifiers(names) {
442 var magicString = this.magicString.clone().trim();
443 var replacementStack = [names];
444 var nameList = keys(names);
445
446 var deshadowList = [];
447 nameList.forEach(function (name) {
448 var replacement = names[name];
449 deshadowList.push(replacement.split('.')[0]);
450 });
451
452 if (nameList.length > 0) {
453 walk(this.node, {
454 enter: function (node, parent) {
455 var _this4 = this;
456
457 var scope = node._scope;
458
459 if (scope) {
460 var _ret = (function () {
461 var newNames = {};
462 var hasReplacements = undefined;
463
464 keys(names).forEach(function (key) {
465 if (! ~scope.names.indexOf(key)) {
466 newNames[key] = names[key];
467 hasReplacements = true;
468 }
469 });
470
471 deshadowList.forEach(function (name) {
472 if (~scope.names.indexOf(name)) {
473 newNames[name] = name + '$$'; // TODO better mechanism
474 hasReplacements = true;
475 }
476 });
477
478 if (!hasReplacements) {
479 return {
480 v: _this4.skip()
481 };
482 }
483
484 names = newNames;
485 replacementStack.push(newNames);
486 })();
487
488 if (typeof _ret === 'object') return _ret.v;
489 }
490
491 // We want to rewrite identifiers (that aren't property names)
492 if (node.type !== 'Identifier') return;
493 if (parent.type === 'MemberExpression' && !parent.computed && node !== parent.object) return;
494 if (parent.type === 'Property' && node !== parent.value) return;
495 // TODO others...?
496
497 var name = has(names, node.name) && names[node.name];
498
499 if (name && name !== node.name) {
500 magicString.overwrite(node.start, node.end, name);
501 }
502 },
503
504 leave: function (node) {
505 if (node._scope) {
506 replacementStack.pop();
507 names = replacementStack[replacementStack.length - 1];
508 }
509 }
510 });
511 }
512
513 return magicString;
514 };
515
516 return Statement;
517})();
518
519var _analyse = analyse;
520
521function analyse(magicString, module) {
522 // first we need to generate comprehensive scope info
523 var previousStatement = null;
524 var commentIndex = 0;
525
526 module.statements.forEach(function (statement) {
527 var node = statement.node;
528
529 var trailing = !!previousStatement;
530
531 // TODO surely this can be neater
532 // attach leading comment
533 do {
534 var comment = module.comments[commentIndex];
535
536 // prevent comments inside the previous statement being
537 // appended to it
538 if (previousStatement) {
539 while (comment && comment.start < previousStatement.node.end) {
540 commentIndex += 1;
541 comment = module.comments[commentIndex];
542 }
543 }
544
545 if (!comment || comment.end > node.start) break;
546
547 // attach any trailing comment to the previous statement
548 if (trailing && !/\n/.test(module.source.slice(previousStatement.node.end, comment.start))) {
549 previousStatement.trailingComment = comment;
550 }
551
552 // then attach leading comments to this statement
553 else {
554 statement.leadingComments.push(comment);
555 }
556
557 commentIndex += 1;
558 trailing = false;
559 } while (module.comments[commentIndex]);
560
561 // determine margin
562 var previousEnd = previousStatement ? (previousStatement.trailingComment || previousStatement.node).end : 0;
563 var start = (statement.leadingComments[0] || node).start;
564
565 var gap = magicString.original.slice(previousEnd, start);
566 var margin = gap.split('\n').length;
567
568 if (previousStatement) previousStatement.margin[1] = margin;
569 statement.margin[0] = margin;
570
571 statement.analyse();
572
573 previousStatement = statement;
574 });
575}
576
577var reservedWords = 'break case class catch const continue debugger default delete do else export extends finally for function if import in instanceof let new return super switch this throw try typeof var void while with yield enum await implements package protected static interface private public'.split(' ');
578var builtins = 'Infinity NaN undefined null true false eval uneval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Symbol Error EvalError InternalError RangeError ReferenceError SyntaxError TypeError URIError Number Math Date String RegExp Array Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array Map Set WeakMap WeakSet SIMD ArrayBuffer DataView JSON Promise Generator GeneratorFunction Reflect Proxy Intl'.split(' ');
579
580var blacklisted = {};
581reservedWords.concat(builtins).forEach(function (word) {
582 return blacklisted[word] = true;
583});
584function makeLegalIdentifier(str) {
585 str = str.replace(/[^$_a-zA-Z0-9]/g, '_');
586 if (/\d/.test(str[0]) || blacklisted[str]) str = '_' + str;
587
588 return str;
589}
590
591function Module___classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
592
593var Module__emptyArrayPromise = sander.Promise.resolve([]);
594
595var Module = (function () {
596 function Module(_ref) {
597 var _this = this;
598
599 var path = _ref.path;
600 var source = _ref.source;
601 var bundle = _ref.bundle;
602
603 Module___classCallCheck(this, Module);
604
605 this.source = source;
606
607 this.bundle = bundle;
608 this.path = path;
609 this.relativePath = _path.relative(bundle.base, path).slice(0, -3); // remove .js
610
611 this.magicString = new MagicString(source, {
612 filename: path
613 });
614
615 this.suggestedNames = {};
616 this.comments = [];
617
618 // Try to extract a list of top-level statements/declarations. If
619 // the parse fails, attach file info and abort
620 try {
621 var ast = acorn.parse(source, {
622 ecmaVersion: 6,
623 sourceType: 'module',
624 onComment: function (block, text, start, end) {
625 return _this.comments.push({ block: block, text: text, start: start, end: end });
626 }
627 });
628
629 walk(ast, {
630 enter: function (node) {
631 _this.magicString.addSourcemapLocation(node.start);
632 }
633 });
634
635 this.statements = ast.body.map(function (node) {
636 var magicString = _this.magicString.snip(node.start, node.end);
637 return new Statement(node, magicString, _this);
638 });
639 } catch (err) {
640 err.code = 'PARSE_ERROR';
641 err.file = path;
642 throw err;
643 }
644
645 this.importDeclarations = this.statements.filter(isImportDeclaration);
646 this.exportDeclarations = this.statements.filter(isExportDeclaration);
647
648 this.analyse();
649 }
650
651 Module.prototype.analyse = function analyse() {
652 var _this2 = this;
653
654 // imports and exports, indexed by ID
655 this.imports = {};
656 this.exports = {};
657
658 this.importDeclarations.forEach(function (statement) {
659 var node = statement.node;
660 var source = node.source.value;
661
662 node.specifiers.forEach(function (specifier) {
663 var isDefault = specifier.type === 'ImportDefaultSpecifier';
664 var isNamespace = specifier.type === 'ImportNamespaceSpecifier';
665
666 var localName = specifier.local.name;
667 var name = isDefault ? 'default' : isNamespace ? '*' : specifier.imported.name;
668
669 if (has(_this2.imports, localName)) {
670 var err = new Error('Duplicated import \'' + localName + '\'');
671 err.file = _this2.path;
672 err.loc = getLocation(_this2.source, specifier.start);
673 throw err;
674 }
675
676 _this2.imports[localName] = {
677 source: source,
678 name: name,
679 localName: localName
680 };
681 });
682 });
683
684 this.exportDeclarations.forEach(function (statement) {
685 var node = statement.node;
686 var source = node.source && node.source.value;
687
688 // export default function foo () {}
689 // export default foo;
690 // export default 42;
691 if (node.type === 'ExportDefaultDeclaration') {
692 var isDeclaration = /Declaration$/.test(node.declaration.type);
693
694 _this2.exports.default = {
695 statement: statement,
696 name: 'default',
697 localName: isDeclaration ? node.declaration.id.name : 'default',
698 isDeclaration: isDeclaration
699 };
700 }
701
702 // export { foo, bar, baz }
703 // export var foo = 42;
704 // export function foo () {}
705 else if (node.type === 'ExportNamedDeclaration') {
706 if (node.specifiers.length) {
707 // export { foo, bar, baz }
708 node.specifiers.forEach(function (specifier) {
709 var localName = specifier.local.name;
710 var exportedName = specifier.exported.name;
711
712 _this2.exports[exportedName] = {
713 localName: localName,
714 exportedName: exportedName
715 };
716
717 // export { foo } from './foo';
718 if (source) {
719 _this2.imports[localName] = {
720 source: source,
721 localName: localName,
722 name: localName
723 };
724 }
725 });
726 } else {
727 var declaration = node.declaration;
728
729 var _name = undefined;
730
731 if (declaration.type === 'VariableDeclaration') {
732 // export var foo = 42
733 _name = declaration.declarations[0].id.name;
734 } else {
735 // export function foo () {}
736 _name = declaration.id.name;
737 }
738
739 _this2.exports[_name] = {
740 statement: statement,
741 localName: _name,
742 expression: declaration
743 };
744 }
745 }
746 });
747
748 _analyse(this.magicString, this);
749
750 this.canonicalNames = {};
751
752 this.definitions = {};
753 this.definitionPromises = {};
754 this.modifications = {};
755
756 this.statements.forEach(function (statement) {
757 Object.keys(statement.defines).forEach(function (name) {
758 _this2.definitions[name] = statement;
759 });
760
761 Object.keys(statement.modifies).forEach(function (name) {
762 if (!has(_this2.modifications, name)) {
763 _this2.modifications[name] = [];
764 }
765
766 _this2.modifications[name].push(statement);
767 });
768 });
769 };
770
771 Module.prototype.getCanonicalName = function getCanonicalName(localName) {
772 if (has(this.suggestedNames, localName)) {
773 localName = this.suggestedNames[localName];
774 }
775
776 if (!has(this.canonicalNames, localName)) {
777 var canonicalName = undefined;
778
779 if (has(this.imports, localName)) {
780 var importDeclaration = this.imports[localName];
781 var _module = importDeclaration.module;
782
783 if (importDeclaration.name === '*') {
784 canonicalName = _module.suggestedNames['*'];
785 } else {
786 var exporterLocalName = undefined;
787
788 if (_module.isExternal) {
789 exporterLocalName = importDeclaration.name;
790 } else {
791 var exportDeclaration = _module.exports[importDeclaration.name];
792 exporterLocalName = exportDeclaration.localName;
793 }
794
795 canonicalName = _module.getCanonicalName(exporterLocalName);
796 }
797 } else {
798 canonicalName = localName;
799 }
800
801 this.canonicalNames[localName] = canonicalName;
802 }
803
804 return this.canonicalNames[localName];
805 };
806
807 Module.prototype.define = function define(name) {
808 var _this3 = this;
809
810 // shortcut cycles. TODO this won't work everywhere...
811 if (has(this.definitionPromises, name)) {
812 return Module__emptyArrayPromise;
813 }
814
815 var promise = undefined;
816
817 // The definition for this name is in a different module
818 if (has(this.imports, name)) {
819 (function () {
820 var importDeclaration = _this3.imports[name];
821
822 promise = _this3.bundle.fetchModule(importDeclaration.source, _this3.path).then(function (module) {
823 importDeclaration.module = module;
824
825 // suggest names. TODO should this apply to non default/* imports?
826 if (importDeclaration.name === 'default') {
827 // TODO this seems ropey
828 var localName = importDeclaration.localName;
829 var suggestion = has(_this3.suggestedNames, localName) ? _this3.suggestedNames[localName] : localName;
830
831 // special case - the module has its own import by this name
832 while (!module.isExternal && has(module.imports, suggestion)) {
833 suggestion = '_' + suggestion;
834 }
835
836 module.suggestName('default', suggestion);
837 } else if (importDeclaration.name === '*') {
838 var localName = importDeclaration.localName;
839 var suggestion = has(_this3.suggestedNames, localName) ? _this3.suggestedNames[localName] : localName;
840 module.suggestName('*', suggestion);
841 module.suggestName('default', '' + suggestion + '__default');
842 }
843
844 if (module.isExternal) {
845 if (importDeclaration.name === 'default') {
846 module.needsDefault = true;
847 } else {
848 module.needsNamed = true;
849 }
850
851 module.importedByBundle.push(importDeclaration);
852 return Module__emptyArrayPromise;
853 }
854
855 if (importDeclaration.name === '*') {
856 // we need to create an internal namespace
857 if (! ~_this3.bundle.internalNamespaceModules.indexOf(module)) {
858 _this3.bundle.internalNamespaceModules.push(module);
859 }
860
861 return module.expandAllStatements();
862 }
863
864 var exportDeclaration = module.exports[importDeclaration.name];
865
866 if (!exportDeclaration) {
867 throw new Error('Module ' + module.path + ' does not export ' + importDeclaration.name + ' (imported by ' + _this3.path + ')');
868 }
869
870 return module.define(exportDeclaration.localName);
871 });
872 })();
873 }
874
875 // The definition is in this module
876 else if (name === 'default' && this.exports.default.isDeclaration) {
877 // We have something like `export default foo` - so we just start again,
878 // searching for `foo` instead of default
879 promise = this.define(this.exports.default.name);
880 } else {
881 var statement = undefined;
882
883 if (name === 'default') {
884 statement = this.exports.default.statement;
885 } else {
886 statement = this.definitions[name];
887 }
888
889 if (statement && !statement.isIncluded) {
890 promise = statement.expand();
891 }
892 }
893
894 this.definitionPromises[name] = promise || Module__emptyArrayPromise;
895 return this.definitionPromises[name];
896 };
897
898 Module.prototype.expandAllStatements = function expandAllStatements(isEntryModule) {
899 var _this4 = this;
900
901 var allStatements = [];
902
903 return sequence(this.statements, function (statement) {
904 // A statement may have already been included, in which case we need to
905 // curb rollup's enthusiasm and move it down here. It remains to be seen
906 // if this approach is bulletproof
907 if (statement.isIncluded) {
908 var index = allStatements.indexOf(statement);
909 if (~index) {
910 allStatements.splice(index, 1);
911 allStatements.push(statement);
912 }
913
914 return;
915 }
916
917 // skip import declarations...
918 if (statement.isImportDeclaration) {
919 // ...unless they're empty, in which case assume we're importing them for the side-effects
920 // THIS IS NOT FOOLPROOF. Probably need /*rollup: include */ or similar
921 if (!statement.node.specifiers.length) {
922 return _this4.bundle.fetchModule(statement.node.source.value, _this4.path).then(function (module) {
923 statement.module = module; // TODO what is this for? what does it do? why not _module?
924 return module.expandAllStatements();
925 }).then(function (statements) {
926 allStatements.push.apply(allStatements, statements);
927 });
928 }
929
930 return;
931 }
932
933 // skip `export { foo, bar, baz }`...
934 if (statement.node.type === 'ExportNamedDeclaration' && statement.node.specifiers.length) {
935 // ...but ensure they are defined, if this is the entry module
936 if (isEntryModule) {
937 return statement.expand().then(function (statements) {
938 allStatements.push.apply(allStatements, statements);
939 });
940 }
941
942 return;
943 }
944
945 // include everything else
946 return statement.expand().then(function (statements) {
947 allStatements.push.apply(allStatements, statements);
948 });
949 }).then(function () {
950 return allStatements;
951 });
952 };
953
954 Module.prototype.rename = function rename(name, replacement) {
955 this.canonicalNames[name] = replacement;
956 };
957
958 Module.prototype.suggestName = function suggestName(exportName, suggestion) {
959 if (!this.suggestedNames[exportName]) {
960 this.suggestedNames[exportName] = makeLegalIdentifier(suggestion);
961 }
962 };
963
964 return Module;
965})();
966
967function ExternalModule___classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
968
969var ExternalModule = (function () {
970 function ExternalModule(id) {
971 ExternalModule___classCallCheck(this, ExternalModule);
972
973 this.id = id;
974 this.name = null;
975
976 this.isExternal = true;
977 this.importedByBundle = [];
978
979 this.canonicalNames = {};
980 this.suggestedNames = {};
981
982 this.needsDefault = false;
983 this.needsNamed = false;
984 }
985
986 ExternalModule.prototype.getCanonicalName = function getCanonicalName(name) {
987 if (name === 'default') {
988 return this.needsNamed ? '' + this.name + '__default' : this.name;
989 }
990
991 if (name === '*') {
992 return this.name;
993 }
994
995 // TODO this depends on the output format... works for CJS etc but not ES6
996 return '' + this.name + '.' + name;
997 };
998
999 ExternalModule.prototype.rename = function rename(name, replacement) {
1000 this.canonicalNames[name] = replacement;
1001 };
1002
1003 ExternalModule.prototype.suggestName = function suggestName(exportName, suggestion) {
1004 if (!this.suggestedNames[exportName]) {
1005 this.suggestedNames[exportName] = suggestion;
1006 }
1007 };
1008
1009 return ExternalModule;
1010})();
1011
1012function amd(bundle, magicString, exportMode, options) {
1013 var deps = bundle.externalModules.map(quoteId);
1014 var args = bundle.externalModules.map(getName);
1015
1016 if (exportMode === 'named') {
1017 args.unshift('exports');
1018 deps.unshift('\'exports\'');
1019 }
1020
1021 var params = (has(options, 'moduleId') ? '[\'' + options.moduleId + '\'], ' : '') + (deps.length ? '[' + deps.join(', ') + '], ' : '');
1022
1023 var intro = 'define(' + params + 'function (' + args.join(', ') + ') { \'use strict\';\n\n';
1024
1025 var exports = bundle.entryModule.exports;
1026
1027 var exportBlock = undefined;
1028
1029 if (exportMode === 'default') {
1030 exportBlock = 'return ' + bundle.entryModule.getCanonicalName('default') + ';';
1031 } else {
1032 exportBlock = Object.keys(exports).map(function (name) {
1033 return 'exports.' + name + ' = ' + exports[name].localName + ';';
1034 }).join('\n');
1035 }
1036
1037 if (exportBlock) {
1038 magicString.append('\n\n' + exportBlock);
1039 }
1040
1041 return magicString.trim().indent().append('\n\n});').prepend(intro);
1042}
1043
1044function cjs(bundle, magicString, exportMode) {
1045 var intro = '\'use strict\';\n\n';
1046
1047 // TODO handle empty imports, once they're supported
1048 var importBlock = bundle.externalModules.map(function (module) {
1049 var requireStatement = 'var ' + module.name + ' = require(\'' + module.id + '\');';
1050
1051 if (module.needsDefault) {
1052 requireStatement += '\n' + (module.needsNamed ? 'var ' + module.name + '__default = ' : '' + module.name + ' = ') + ('\'default\' in ' + module.name + ' ? ' + module.name + '[\'default\'] : ' + module.name + ';');
1053 }
1054
1055 return requireStatement;
1056 }).join('\n');
1057
1058 if (importBlock) {
1059 intro += importBlock + '\n\n';
1060 }
1061
1062 magicString.prepend(intro);
1063
1064 var exportBlock = undefined;
1065 if (exportMode === 'default' && bundle.entryModule.exports.default) {
1066 exportBlock = 'module.exports = ' + bundle.entryModule.getCanonicalName('default') + ';';
1067 } else if (exportMode === 'named') {
1068 exportBlock = keys(bundle.entryModule.exports).map(function (key) {
1069 var specifier = bundle.entryModule.exports[key];
1070 var name = bundle.entryModule.getCanonicalName(specifier.localName);
1071
1072 return 'exports.' + key + ' = ' + name + ';';
1073 }).join('\n');
1074 }
1075
1076 if (exportBlock) {
1077 magicString.append('\n\n' + exportBlock);
1078 }
1079
1080 return magicString;
1081}
1082
1083function es6(bundle, magicString, exportMode, options) {
1084 var introBlock = ''; // TODO...
1085
1086 var exports = bundle.entryModule.exports;
1087 var exportBlock = keys(exports).map(function (exportedName) {
1088 var specifier = exports[exportedName];
1089
1090 var canonicalName = bundle.entryModule.getCanonicalName(specifier.localName);
1091
1092 if (exportedName === 'default') {
1093 return 'export default ' + canonicalName + ';';
1094 }
1095
1096 return exportedName === canonicalName ? 'export { ' + exportedName + ' };' : 'export { ' + canonicalName + ' as ' + exportedName + ' };';
1097 }).join('\n');
1098
1099 if (exportBlock) {
1100 magicString.append('\n\n' + exportBlock);
1101 }
1102
1103 return magicString.trim();
1104}
1105
1106function iife(bundle, magicString, exportMode, options) {
1107 var globalNames = options.globals || {};
1108
1109 var dependencies = bundle.externalModules.map(function (module) {
1110 return has(globalNames, module.id) ? globalNames[module.id] : module.name;
1111 });
1112
1113 var args = bundle.externalModules.map(getName);
1114
1115 if (exportMode !== 'none' && !options.moduleName) {
1116 throw new Error('You must supply options.moduleName for IIFE bundles');
1117 }
1118
1119 if (exportMode === 'named') {
1120 dependencies.unshift('(window.' + options.moduleName + ' = {})');
1121 args.unshift('exports');
1122 }
1123
1124 var intro = '(function (' + args + ') { \'use strict\';\n\n';
1125 var outro = '\n\n})(' + dependencies + ');';
1126
1127 if (exportMode === 'default') {
1128 intro = 'var ' + options.moduleName + ' = ' + intro;
1129 magicString.append('\n\nreturn ' + bundle.entryModule.getCanonicalName('default') + ';');
1130 }
1131
1132 return magicString.indent().prepend(intro).append(outro);
1133}
1134
1135function umd(bundle, magicString, exportMode, options) {
1136 var indentStr = magicString.getIndentString();
1137
1138 var globalNames = options.globals || {};
1139
1140 var amdDeps = bundle.externalModules.map(quoteId);
1141 var cjsDeps = bundle.externalModules.map(req);
1142 var globalDeps = bundle.externalModules.map(function (module) {
1143 return has(globalNames, module.id) ? globalNames[module.id] : module.name;
1144 });
1145
1146 var args = bundle.externalModules.map(getName);
1147
1148 if (exportMode === 'named') {
1149 amdDeps.unshift('\'exports\'');
1150 cjsDeps.unshift('\'exports\'');
1151 globalDeps.unshift('(global.' + options.moduleName + ' = {})');
1152
1153 args.unshift('exports');
1154 }
1155
1156 var amdParams = (has(options, 'moduleId') ? '[\'' + options.moduleId + '\'], ' : '') + (amdDeps.length ? '[' + amdDeps.join(', ') + '], ' : '');
1157
1158 var defaultExport = exportMode === 'default' ? 'global.' + options.moduleName + ' = ' : '';
1159
1160 var intro = ('(function (global, factory) {\n\t\t\ttypeof exports === \'object\' && typeof module !== \'undefined\' ? factory(' + cjsDeps.join(', ') + ') :\n\t\t\ttypeof define === \'function\' && define.amd ? define(' + amdParams + 'factory) :\n\t\t\t' + defaultExport + 'factory(' + globalDeps + ');\n\t\t}(this, function (' + args + ') { \'use strict\';\n\n\t\t').replace(/^\t\t/gm, '').replace(/^\t/gm, indentStr);
1161
1162 var exports = bundle.entryModule.exports;
1163
1164 var exportBlock = undefined;
1165
1166 if (exportMode === 'default') {
1167 var canonicalName = bundle.entryModule.getCanonicalName('default');
1168 exportBlock = 'return ' + canonicalName + ';';
1169 } else {
1170 exportBlock = Object.keys(exports).map(function (name) {
1171 var canonicalName = bundle.entryModule.getCanonicalName(exports[name].localName);
1172 return 'exports.' + name + ' = ' + canonicalName + ';';
1173 }).join('\n');
1174 }
1175
1176 if (exportBlock) {
1177 magicString.append('\n\n' + exportBlock);
1178 }
1179
1180 return magicString.trim().indent().append('\n\n}));').prepend(intro);
1181}
1182
1183var finalisers = { amd: amd, cjs: cjs, es6: es6, iife: iife, umd: umd };
1184
1185function ensureArray(thing) {
1186 if (Array.isArray(thing)) return thing;
1187 if (thing == undefined) return [];
1188 return [thing];
1189}
1190
1191function defaultResolver(importee, importer, options) {
1192 // absolute paths are left untouched
1193 if (_path.isAbsolute(importee)) return importee;
1194
1195 // we try to resolve external modules
1196 if (importee[0] !== '.') {
1197 // unless we want to keep it external, that is
1198 if (~options.external.indexOf(importee)) return null;
1199
1200 return options.resolveExternal(importee, importer, options);
1201 }
1202
1203 return _path.resolve(_path.dirname(importer), importee).replace(/\.js$/, '') + '.js';
1204}
1205
1206function defaultExternalResolver(id, importer, options) {
1207 // for now, only node_modules is supported, and only jsnext:main
1208 var parsed = _path.parse(importer);
1209 var dir = parsed.dir;
1210
1211 while (dir !== parsed.root) {
1212 var pkgPath = _path.resolve(dir, 'node_modules', id, 'package.json');
1213 var pkgJson = undefined;
1214
1215 try {
1216 pkgJson = sander.readFileSync(pkgPath).toString();
1217 } catch (err) {}
1218
1219 if (pkgJson) {
1220 var pkg = undefined;
1221
1222 try {
1223 pkg = JSON.parse(pkgJson);
1224 } catch (err) {
1225 throw new Error('Malformed JSON: ' + pkgPath);
1226 }
1227
1228 var main = pkg['jsnext:main'];
1229
1230 if (!main) {
1231 throw new Error('Package ' + id + ' does not have a jsnext:main field, and so cannot be included in your rollup. Try adding it as an external module instead (e.g. options.external = [\'' + id + '\']). See https://github.com/rollup/rollup/wiki/jsnext:main for more info');
1232 }
1233
1234 return _path.resolve(_path.dirname(pkgPath), main).replace(/\.js$/, '') + '.js';
1235 }
1236
1237 dir = _path.dirname(dir);
1238 }
1239
1240 throw new Error('Could not find package ' + id + ' (required by ' + importer + ')');
1241}
1242
1243// noop
1244
1245function defaultLoader(path, options) {
1246 // TODO support plugins e.g. !css and !json?
1247 var source = sander.readFileSync(path, { encoding: 'utf-8' });
1248
1249 return options.transform.reduce(function (source, transformer) {
1250 return transformer(source, path);
1251 }, source);
1252}
1253
1254function Bundle___classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
1255
1256function badExports(option, keys) {
1257 throw new Error('\'' + option + '\' was specified for options.exports, but entry module has following exports: ' + keys.join(', '));
1258}
1259
1260var Bundle = (function () {
1261 function Bundle(options) {
1262 Bundle___classCallCheck(this, Bundle);
1263
1264 this.entryPath = _path.resolve(options.entry).replace(/\.js$/, '') + '.js';
1265 this.base = _path.dirname(this.entryPath);
1266
1267 this.resolvePath = options.resolvePath || defaultResolver;
1268 this.load = options.load || defaultLoader;
1269
1270 this.resolvePathOptions = {
1271 external: ensureArray(options.external),
1272 resolveExternal: options.resolveExternal || defaultExternalResolver
1273 };
1274
1275 this.loadOptions = {
1276 transform: ensureArray(options.transform)
1277 };
1278
1279 this.entryModule = null;
1280 this.modulePromises = {};
1281 this.statements = [];
1282 this.externalModules = [];
1283 this.defaultExportName = null;
1284 this.internalNamespaceModules = [];
1285 }
1286
1287 Bundle.prototype.fetchModule = function fetchModule(importee, importer) {
1288 var _this = this;
1289
1290 return sander.Promise.resolve(importer === null ? importee : this.resolvePath(importee, importer, this.resolvePathOptions)).then(function (path) {
1291 if (!path) {
1292 // external module
1293 if (!has(_this.modulePromises, importee)) {
1294 var _module = new ExternalModule(importee);
1295 _this.externalModules.push(_module);
1296 _this.modulePromises[importee] = sander.Promise.resolve(_module);
1297 }
1298
1299 return _this.modulePromises[importee];
1300 }
1301
1302 if (!has(_this.modulePromises, path)) {
1303 _this.modulePromises[path] = sander.Promise.resolve(_this.load(path, _this.loadOptions)).then(function (source) {
1304 var module = new Module({
1305 path: path,
1306 source: source,
1307 bundle: _this
1308 });
1309
1310 return module;
1311 });
1312 }
1313
1314 return _this.modulePromises[path];
1315 });
1316 };
1317
1318 Bundle.prototype.build = function build() {
1319 var _this2 = this;
1320
1321 // bring in top-level AST nodes from the entry module
1322 return this.fetchModule(this.entryPath, null).then(function (entryModule) {
1323 _this2.entryModule = entryModule;
1324
1325 if (entryModule.exports.default) {
1326 (function () {
1327 var defaultExportName = makeLegalIdentifier(_path.basename(_this2.entryPath).slice(0, -_path.extname(_this2.entryPath).length));
1328
1329 var topLevelNames = [];
1330 entryModule.statements.forEach(function (statement) {
1331 keys(statement.defines).forEach(function (name) {
1332 return topLevelNames.push(name);
1333 });
1334 });
1335
1336 while (~topLevelNames.indexOf(defaultExportName)) {
1337 defaultExportName = '_' + defaultExportName;
1338 }
1339
1340 entryModule.suggestName('default', defaultExportName);
1341 })();
1342 }
1343
1344 return entryModule.expandAllStatements(true);
1345 }).then(function (statements) {
1346 _this2.statements = statements;
1347 _this2.deconflict();
1348 });
1349 };
1350
1351 Bundle.prototype.deconflict = function deconflict() {
1352 var definers = {};
1353 var conflicts = {};
1354
1355 // Discover conflicts (i.e. two statements in separate modules both define `foo`)
1356 this.statements.forEach(function (statement) {
1357 var module = statement.module;
1358 var names = keys(statement.defines);
1359
1360 // with default exports that are expressions (`export default 42`),
1361 // we need to ensure that the name chosen for the expression does
1362 // not conflict
1363 if (statement.node.type === 'ExportDefaultDeclaration') {
1364 var _name = module.getCanonicalName('default');
1365
1366 var isProxy = statement.node.declaration && statement.node.declaration.type === 'Identifier';
1367 var shouldDeconflict = !isProxy || module.getCanonicalName(statement.node.declaration.name) !== _name;
1368
1369 if (shouldDeconflict && ! ~names.indexOf(_name)) {
1370 names.push(_name);
1371 }
1372 }
1373
1374 names.forEach(function (name) {
1375 if (has(definers, name)) {
1376 conflicts[name] = true;
1377 } else {
1378 definers[name] = [];
1379 }
1380
1381 // TODO in good js, there shouldn't be duplicate definitions
1382 // per module... but some people write bad js
1383 definers[name].push(module);
1384 });
1385 });
1386
1387 // Assign names to external modules
1388 this.externalModules.forEach(function (module) {
1389 // TODO is this right?
1390 var name = makeLegalIdentifier(module.suggestedNames['*'] || module.suggestedNames.default || module.id);
1391
1392 if (has(definers, name)) {
1393 conflicts[name] = true;
1394 } else {
1395 definers[name] = [];
1396 }
1397
1398 definers[name].push(module);
1399 module.name = name;
1400 });
1401
1402 // Rename conflicting identifiers so they can live in the same scope
1403 keys(conflicts).forEach(function (name) {
1404 var modules = definers[name];
1405
1406 modules.pop(); // the module closest to the entryModule gets away with keeping things as they are
1407
1408 modules.forEach(function (module) {
1409 var replacement = getSafeName(name);
1410 module.rename(name, replacement);
1411 });
1412 });
1413
1414 function getSafeName(name) {
1415 while (has(conflicts, name)) {
1416 name = '_' + name;
1417 }
1418
1419 conflicts[name] = true;
1420 return name;
1421 }
1422 };
1423
1424 Bundle.prototype.generate = function generate() {
1425 var options = arguments[0] === undefined ? {} : arguments[0];
1426
1427 var magicString = new MagicString.Bundle({ separator: '' });
1428
1429 // Determine export mode - 'default', 'named', 'none'
1430 var exportMode = this.getExportMode(options.exports);
1431
1432 var previousMargin = 0;
1433
1434 // Apply new names and add to the output bundle
1435 this.statements.forEach(function (statement) {
1436 var replacements = {};
1437
1438 keys(statement.dependsOn).concat(keys(statement.defines)).forEach(function (name) {
1439 var canonicalName = statement.module.getCanonicalName(name);
1440
1441 if (name !== canonicalName) {
1442 replacements[name] = canonicalName;
1443 }
1444 });
1445
1446 var source = statement.replaceIdentifiers(replacements);
1447
1448 // modify exports as necessary
1449 if (statement.isExportDeclaration) {
1450 // skip `export { foo, bar, baz }`
1451 if (statement.node.type === 'ExportNamedDeclaration' && statement.node.specifiers.length) {
1452 return;
1453 }
1454
1455 // remove `export` from `export var foo = 42`
1456 if (statement.node.type === 'ExportNamedDeclaration' && statement.node.declaration.type === 'VariableDeclaration') {
1457 source.remove(statement.node.start, statement.node.declaration.start);
1458 }
1459
1460 // remove `export` from `export class Foo {...}` or `export default Foo`
1461 // TODO default exports need different treatment
1462 else if (statement.node.declaration.id) {
1463 source.remove(statement.node.start, statement.node.declaration.start);
1464 } else if (statement.node.type === 'ExportDefaultDeclaration') {
1465 var _module2 = statement.module;
1466 var canonicalName = _module2.getCanonicalName('default');
1467
1468 if (statement.node.declaration.type === 'Identifier' && canonicalName === _module2.getCanonicalName(statement.node.declaration.name)) {
1469 return;
1470 }
1471
1472 source.overwrite(statement.node.start, statement.node.declaration.start, 'var ' + canonicalName + ' = ');
1473 } else {
1474 throw new Error('Unhandled export');
1475 }
1476 }
1477
1478 // add leading comments
1479 if (statement.leadingComments.length) {
1480 var commentBlock = statement.leadingComments.map(function (comment) {
1481 return comment.block ? '/*' + comment.text + '*/' : '//' + comment.text;
1482 }).join('\n');
1483
1484 magicString.addSource(new MagicString(commentBlock));
1485 }
1486
1487 // add margin
1488 var margin = Math.max(statement.margin[0], previousMargin);
1489 var newLines = new Array(margin).join('\n');
1490
1491 // add the statement itself
1492 magicString.addSource({
1493 content: source,
1494 separator: newLines
1495 });
1496
1497 // add trailing comments
1498 var comment = statement.trailingComment;
1499 if (comment) {
1500 var commentBlock = comment.block ? ' /*' + comment.text + '*/' : ' //' + comment.text;
1501
1502 magicString.append(commentBlock);
1503 }
1504
1505 previousMargin = statement.margin[1];
1506 });
1507
1508 // prepend bundle with internal namespaces
1509 var indentString = magicString.getIndentString();
1510 var namespaceBlock = this.internalNamespaceModules.map(function (module) {
1511 var exportKeys = keys(module.exports);
1512
1513 return 'var ' + module.getCanonicalName('*') + ' = {\n' + exportKeys.map(function (key) {
1514 return '' + indentString + 'get ' + key + ' () { return ' + module.getCanonicalName(key) + '; }';
1515 }).join(',\n') + '\n};\n\n';
1516 }).join('');
1517
1518 magicString.prepend(namespaceBlock);
1519
1520 var finalise = finalisers[options.format || 'es6'];
1521
1522 if (!finalise) {
1523 throw new Error('You must specify an output type - valid options are ' + keys(finalisers).join(', '));
1524 }
1525
1526 magicString = finalise(this, magicString.trim(), exportMode, options);
1527
1528 var code = magicString.toString();
1529 var map = null;
1530
1531 if (options.sourceMap) {
1532 (function () {
1533 map = magicString.generateMap({
1534 includeContent: true,
1535 file: options.sourceMapFile || options.dest
1536 // TODO
1537 });
1538
1539 // make sources relative. TODO fix this upstream?
1540 var dir = _path.dirname(map.file);
1541 map.sources = map.sources.map(function (source) {
1542 return source ? _path.relative(dir, source) : null;
1543 });
1544 })();
1545 }
1546
1547 return { code: code, map: map };
1548 };
1549
1550 Bundle.prototype.getExportMode = function getExportMode(exportMode) {
1551 var exportKeys = keys(this.entryModule.exports);
1552
1553 if (exportMode === 'default') {
1554 if (exportKeys.length !== 1 || exportKeys[0] !== 'default') {
1555 badExports('default', exportKeys);
1556 }
1557 } else if (exportMode === 'none' && exportKeys.length) {
1558 badExports('none', exportKeys);
1559 }
1560
1561 if (!exportMode || exportMode === 'auto') {
1562 if (exportKeys.length === 0) {
1563 exportMode = 'none';
1564 } else if (exportKeys.length === 1 && exportKeys[0] === 'default') {
1565 exportMode = 'default';
1566 } else {
1567 exportMode = 'named';
1568 }
1569 }
1570
1571 if (!/(?:default|named|none)/.test(exportMode)) {
1572 throw new Error('options.exports must be \'default\', \'named\', \'none\', \'auto\', or left unspecified (defaults to \'auto\')');
1573 }
1574
1575 return exportMode;
1576 };
1577
1578 return Bundle;
1579})();
1580
1581var SOURCEMAPPING_URL = 'sourceMa';
1582SOURCEMAPPING_URL += 'ppingURL';
1583function rollup(options) {
1584 if (!options || !options.entry) {
1585 throw new Error('You must supply options.entry to rollup');
1586 }
1587
1588 var bundle = new Bundle(options);
1589
1590 return bundle.build().then(function () {
1591 return {
1592 generate: function (options) {
1593 return bundle.generate(options);
1594 },
1595 write: function (options) {
1596 if (!options || !options.dest) {
1597 throw new Error('You must supply options.dest to bundle.write');
1598 }
1599
1600 var dest = options.dest;
1601
1602 var _bundle$generate = bundle.generate(options);
1603
1604 var code = _bundle$generate.code;
1605 var map = _bundle$generate.map;
1606
1607 var promises = [sander.writeFile(dest, code)];
1608
1609 if (options.sourceMap) {
1610 var url = undefined;
1611
1612 if (options.sourceMap === 'inline') {
1613 url = map.toUrl();
1614 } else {
1615 url = '' + _path.basename(dest) + '.map';
1616 promises.push(sander.writeFile(dest + '.map', map.toString()));
1617 }
1618
1619 code += '\n//# ' + SOURCEMAPPING_URL + '=' + url;
1620 }
1621
1622 return Promise.all(promises);
1623 }
1624 };
1625 });
1626}
1627
1628exports.rollup = rollup;
1629//# sourceMappingURL=rollup.js.map