Example #1
0
	render ( es, legacy ) {
		const magicString = this.magicString.clone();

		for ( const node of this.ast.body ) {
			node.render( magicString, es );
		}

		if ( this.namespace().needsNamespaceBlock ) {
			magicString.append( '\n\n' + this.namespace().renderBlock( es, legacy, '\t' ) ); // TODO use correct indentation
		}

		return magicString.trim();
	}
Example #2
0
export default function commonjs ( options = {} ) {
	const extensions = options.extensions || ['.js'];
	const filter = createFilter( options.include, options.exclude );
	const ignoreGlobal = options.ignoreGlobal;
	const firstpass = ignoreGlobal ? firstpassNoGlobal : firstpassGlobal;
	let bundleUsesGlobal = false;
	let bundleRequiresWrappers = false;

	const sourceMap = options.sourceMap !== false;

	let customNamedExports = {};
	if ( options.namedExports ) {
		Object.keys( options.namedExports ).forEach( id => {
			let resolvedId;

			try {
				resolvedId = nodeResolveSync( id, { basedir: process.cwd() });
			} catch ( err ) {
				resolvedId = resolve( id );
			}

			customNamedExports[ resolvedId ] = options.namedExports[ id ];
		});
	}

	return {
		resolveId ( importee, importer ) {
			if ( importee[0] !== '.' || !importer) return; // not our problem

			const resolved = resolve( dirname( importer ), importee );
			const candidates = getCandidates( resolved, extensions );

			for ( let i = 0; i < candidates.length; i += 1 ) {
				try {
					const stats = statSync( candidates[i] );
					if ( stats.isFile() ) return candidates[i];
				} catch ( err ) { /* noop */ }
			}
		},

		transform ( code, id ) {
			if ( !filter( id ) ) return null;
			if ( extensions.indexOf( extname( id ) ) === -1 ) return null;
			if ( !firstpass.test( code ) ) return null;

			let ast;

			try {
				ast = acorn.parse( code, {
					ecmaVersion: 6,
					sourceType: 'module'
				});
			} catch ( err ) {
				err.message += ` in ${id}`;
				throw err;
			}

			const magicString = new MagicString( code );

			let required = {};
			let uid = 0;

			let scope = attachScopes( ast, 'scope' );
			let uses = { module: false, exports: false, global: false };

			let namedExports = {};
			if ( customNamedExports[ id ] ) {
				customNamedExports[ id ].forEach( name => namedExports[ name ] = true );
			}

			let scopeDepth = 0;

			walk( ast, {
				enter ( node, parent ) {
					if ( node.scope ) scope = node.scope;
					if ( /^Function/.test( node.type ) ) scopeDepth += 1;

					if ( sourceMap ) {
						magicString.addSourcemapLocation( node.start );
						magicString.addSourcemapLocation( node.end );
					}

					// Is this an assignment to exports or module.exports?
					if ( node.type === 'AssignmentExpression' ) {
						if ( node.left.type !== 'MemberExpression' ) return;

						const flattened = flatten( node.left );
						if ( !flattened ) return;

						if ( scope.contains( flattened.name ) ) return;

						const match = exportsPattern.exec( flattened.keypath );
						if ( !match || flattened.keypath === 'exports' ) return;

						if ( flattened.keypath === 'module.exports' && node.right.type === 'ObjectExpression' ) {
							return node.right.properties.forEach( prop => {
								if ( prop.computed || prop.key.type !== 'Identifier' ) return;
								const name = prop.key.name;
								if ( name === makeLegalIdentifier( name ) ) namedExports[ name ] = true;
							});
						}

						if ( match[1] ) namedExports[ match[1] ] = true;

						return;
					}

					if ( node.type === 'Identifier' ) {
						if ( ( node.name in uses && !uses[ node.name ] ) && isReference( node, parent ) && !scope.contains( node.name ) ) uses[ node.name ] = true;
						return;
					}

					if ( node.type === 'ThisExpression' && scopeDepth === 0 && !ignoreGlobal ) {
						uses.global = true;
						magicString.overwrite( node.start, node.end, `__commonjs_global`, true );
						return;
					}

					if ( node.type !== 'CallExpression' ) return;
					if ( node.callee.name !== 'require' || scope.contains( 'require' ) ) return;
					if ( node.arguments.length !== 1 || node.arguments[0].type !== 'Literal' ) return; // TODO handle these weird cases?

					const source = node.arguments[0].value;

					let existing = required[ source ];
					let name;

					if ( !existing ) {
						name = `require$$${uid++}`;
						required[ source ] = { source, name, importsDefault: false };
					} else {
						name = required[ source ].name;
					}

					if ( parent.type !== 'ExpressionStatement' ) {
						required[ source ].importsDefault = true;
						magicString.overwrite( node.start, node.end, name );
					} else {
						// is a bare import, e.g. `require('foo');`
						magicString.remove( parent.start, parent.end );
					}
				},

				leave ( node ) {
					if ( node.scope ) scope = scope.parent;
					if ( /^Function/.test( node.type ) ) scopeDepth -= 1;
				}
			});

			const sources = Object.keys( required );

			if ( !sources.length && !uses.module && !uses.exports && !uses.global ) {
				if ( Object.keys( namedExports ).length ) {
					throw new Error( `Custom named exports were specified for ${id} but it does not appear to be a CommonJS module` );
				}
				return null; // not a CommonJS module
			}

			bundleRequiresWrappers = true;

			const name = getName( id );

			const importBlock = sources.length ?
				sources.map( source => {
					const { name, importsDefault } = required[ source ];
					return `import ${importsDefault ? `${name} from ` : ``}'${source}';`;
				}).join( '\n' ) :
				'';

			const args = `module${uses.exports || uses.global ? ', exports' : ''}${uses.global ? ', global' : ''}`;

			const intro = `\n\nvar ${name} = __commonjs(function (${args}) {\n`;
			let outro = `\n});\n\nexport default (${name} && typeof ${name} === 'object' && 'default' in ${name} ? ${name}['default'] : ${name});\n`;

			outro += Object.keys( namedExports )
				.filter( key => !blacklistedExports[ key ] )
				.map( x => `export var ${x} = ${name}.${x};` )
				.join( '\n' );

			magicString.trim()
				.prepend( importBlock + intro )
				.trim()
				.append( outro );

			code = magicString.toString();
			const map = sourceMap ? magicString.generateMap() : null;

			if ( uses.global ) bundleUsesGlobal = true;

			return { code, map };
		},

		intro () {
			var intros = [];

			if ( bundleUsesGlobal ) {
				intros.push( `var __commonjs_global = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}` );
			}

			if ( bundleRequiresWrappers ) {
				intros.push( `function __commonjs(fn, module) { return module = { exports: {} }, fn(module, module.exports${bundleUsesGlobal ? ', __commonjs_global' : ''}), module.exports; }\n` );
			}

			return intros.join( '\n' );
		}
	};
}
function transformCommonjs ( code, id, isEntry, ignoreGlobal, ignoreRequire, customNamedExports, sourceMap, allowDynamicRequire ) {
	var firstpass = ignoreGlobal ? firstpassNoGlobal : firstpassGlobal;
	if ( !firstpass.test( code ) ) { return null; }

	var ast = tryParse( code, id );

	// if there are top-level import/export declarations, this is ES not CommonJS
	for ( var i = 0, list = ast.body; i < list.length; i += 1 ) {
		var node = list[i];

		if ( importExportDeclaration.test( node.type ) ) { return null; }
	}

	var magicString = new MagicString( code );

	var required = {};
	// Because objects have no guaranteed ordering, yet we need it,
	// we need to keep track of the order in a array
	var sources = [];

	var uid = 0;

	var scope = attachScopes( ast, 'scope' );
	var uses = { module: false, exports: false, global: false, require: false };

	var lexicalDepth = 0;
	var programDepth = 0;

	var globals = new Set();

	var HELPERS_NAME = deconflict( scope, globals, 'commonjsHelpers' ); // TODO technically wrong since globals isn't populated yet, but ¯\_(ツ)_/¯

	var namedExports = {};

	// TODO handle transpiled modules
	var shouldWrap = /__esModule/.test( code );

	function isRequireStatement ( node ) {
		if ( !node ) { return; }
		if ( node.type !== 'CallExpression' ) { return; }
		if ( node.callee.name !== 'require' || scope.contains( 'require' ) ) { return; }
		if ( node.arguments.length !== 1 || node.arguments[0].type !== 'Literal' ) { return; } // TODO handle these weird cases?
		if ( ignoreRequire( node.arguments[0].value ) ) { return; }

		return true;
	}

	function getRequired ( node, name ) {
		var source = node.arguments[0].value;

		var existing = required[ source ];
		if ( existing === undefined ) {
			sources.push( source );

			if ( !name ) { name = "require$$" + (uid++); }
			required[ source ] = { source: source, name: name, importsDefault: false };
		}

		return required[ source ];
	}

	// do a first pass, see which names are assigned to. This is necessary to prevent
	// illegally replacing `var foo = require('foo')` with `import foo from 'foo'`,
	// where `foo` is later reassigned. (This happens in the wild. CommonJS, sigh)
	var assignedTo = new Set();
	walk( ast, {
		enter: function enter ( node ) {
			if ( node.type !== 'AssignmentExpression' ) { return; }
			if ( node.left.type === 'MemberExpression' ) { return; }

			extractNames( node.left ).forEach( function (name) {
				assignedTo.add( name );
			});
		}
	});

	walk( ast, {
		enter: function enter ( node, parent ) {
			if ( sourceMap ) {
				magicString.addSourcemapLocation( node.start );
				magicString.addSourcemapLocation( node.end );
			}

			// skip dead branches
			if ( parent && ( parent.type === 'IfStatement' || parent.type === 'ConditionalExpression' ) ) {
				if ( node === parent.consequent && isFalsy( parent.test ) ) { return this.skip(); }
				if ( node === parent.alternate && isTruthy( parent.test ) ) { return this.skip(); }
			}

			if ( node._skip ) { return this.skip(); }

			programDepth += 1;

			if ( node.scope ) { scope = node.scope; }
			if ( /^Function/.test( node.type ) ) { lexicalDepth += 1; }

			// rewrite `this` as `commonjsHelpers.commonjsGlobal`
			if ( node.type === 'ThisExpression' && lexicalDepth === 0 ) {
				uses.global = true;
				if ( !ignoreGlobal ) { magicString.overwrite( node.start, node.end, (HELPERS_NAME + ".commonjsGlobal"), true ); }
				return;
			}

			// rewrite `typeof module`, `typeof module.exports` and `typeof exports` (https://github.com/rollup/rollup-plugin-commonjs/issues/151)
			if ( node.type === 'UnaryExpression' && node.operator === 'typeof' ) {
				var flattened = flatten( node.argument );
				if ( !flattened ) { return; }

				if ( scope.contains( flattened.name ) ) { return; }

				if ( flattened.keypath === 'module.exports' || flattened.keypath === 'module' || flattened.keypath === 'exports' ) {
					magicString.overwrite( node.start, node.end, "'object'", false );
				}
			}

			// rewrite `require` (if not already handled) `global` and `define`, and handle free references to
			// `module` and `exports` as these mean we need to wrap the module in commonjsHelpers.createCommonjsModule
			if ( node.type === 'Identifier' ) {
				if ( isReference( node, parent ) && !scope.contains( node.name ) ) {
					if ( node.name in uses ) {
						if ( node.name === 'require' ) {
							if ( allowDynamicRequire ) { return; }
							magicString.overwrite( node.start, node.end, (HELPERS_NAME + ".commonjsRequire"), true );
						}

						uses[ node.name ] = true;
						if ( node.name === 'global' && !ignoreGlobal ) {
							magicString.overwrite( node.start, node.end, (HELPERS_NAME + ".commonjsGlobal"), true );
						}

						// if module or exports are used outside the context of an assignment
						// expression, we need to wrap the module
						if ( node.name === 'module' || node.name === 'exports' ) {
							shouldWrap = true;
						}
					}

					if ( node.name === 'define' ) {
						magicString.overwrite( node.start, node.end, 'undefined', true );
					}

					globals.add( node.name );
				}

				return;
			}

			// Is this an assignment to exports or module.exports?
			if ( node.type === 'AssignmentExpression' ) {
				if ( node.left.type !== 'MemberExpression' ) { return; }

				var flattened$1 = flatten( node.left );
				if ( !flattened$1 ) { return; }

				if ( scope.contains( flattened$1.name ) ) { return; }

				var match = exportsPattern.exec( flattened$1.keypath );
				if ( !match || flattened$1.keypath === 'exports' ) { return; }

				uses[ flattened$1.name ] = true;

				// we're dealing with `module.exports = ...` or `[module.]exports.foo = ...` –
				// if this isn't top-level, we'll need to wrap the module
				if ( programDepth > 3 ) { shouldWrap = true; }

				node.left._skip = true;

				if ( flattened$1.keypath === 'module.exports' && node.right.type === 'ObjectExpression' ) {
					return node.right.properties.forEach( function (prop) {
						if ( prop.computed || prop.key.type !== 'Identifier' ) { return; }
						var name = prop.key.name;
						if ( name === makeLegalIdentifier( name ) ) { namedExports[ name ] = true; }
					});
				}

				if ( match[1] ) { namedExports[ match[1] ] = true; }
				return;
			}

			// if this is `var x = require('x')`, we can do `import x from 'x'`
			if ( node.type === 'VariableDeclarator' && node.id.type === 'Identifier' && isRequireStatement( node.init ) ) {
				// for now, only do this for top-level requires. maybe fix this in future
				if ( scope.parent ) { return; }

				// edge case — CJS allows you to assign to imports. ES doesn't
				if ( assignedTo.has( node.id.name ) ) { return; }

				var r$1 = getRequired( node.init, node.id.name );
				r$1.importsDefault = true;

				if ( r$1.name === node.id.name ) {
					node._shouldRemove = true;
				}
			}

			if ( !isRequireStatement( node ) ) { return; }

			var r = getRequired( node );

			if ( parent.type === 'ExpressionStatement' ) {
				// is a bare import, e.g. `require('foo');`
				magicString.remove( parent.start, parent.end );
			} else {
				r.importsDefault = true;
				magicString.overwrite( node.start, node.end, r.name );
			}

			node.callee._skip = true;
		},

		leave: function leave ( node ) {
			programDepth -= 1;
			if ( node.scope ) { scope = scope.parent; }
			if ( /^Function/.test( node.type ) ) { lexicalDepth -= 1; }

			if ( node.type === 'VariableDeclaration' ) {
				var keepDeclaration = false;
				var c = node.declarations[0].start;

				for ( var i = 0; i < node.declarations.length; i += 1 ) {
					var declarator = node.declarations[i];

					if ( declarator._shouldRemove ) {
						magicString.remove( c, declarator.end );
					} else {
						if ( !keepDeclaration ) {
							magicString.remove( c, declarator.start );
							keepDeclaration = true;
						}

						c = declarator.end;
					}
				}

				if ( !keepDeclaration ) {
					magicString.remove( node.start, node.end );
				}
			}
		}
	});

	if ( !sources.length && !uses.module && !uses.exports && !uses.require && ( ignoreGlobal || !uses.global ) ) {
		if ( Object.keys( namedExports ).length ) {
			throw new Error( ("Custom named exports were specified for " + id + " but it does not appear to be a CommonJS module") );
		}
		return null; // not a CommonJS module
	}

	var includeHelpers = shouldWrap || uses.global || uses.require;
	var importBlock = ( includeHelpers ? [ ("import * as " + HELPERS_NAME + " from '" + HELPERS_ID + "';") ] : [] ).concat(
		sources.map( function (source) {
			// import the actual module before the proxy, so that we know
			// what kind of proxy to build
			return ("import '" + source + "';");
		}),
		sources.map( function (source) {
			var ref = required[ source ];
			var name = ref.name;
			var importsDefault = ref.importsDefault;
			return ("import " + (importsDefault ? (name + " from ") : "") + "'" + PREFIX + source + "';");
		})
	).join( '\n' ) + '\n\n';

	var namedExportDeclarations = [];
	var wrapperStart = '';
	var wrapperEnd = '';

	var moduleName = deconflict( scope, globals, getName( id ) );
	if ( !isEntry ) {
		var exportModuleExports = {
			str: ("export { " + moduleName + " as __moduleExports };"),
			name: '__moduleExports'
		};

		namedExportDeclarations.push( exportModuleExports );
	}

	var name = getName( id );

	function addExport ( x ) {
		var deconflicted = deconflict( scope, globals, name );

		var declaration = deconflicted === name ?
			("export var " + x + " = " + moduleName + "." + x + ";") :
			("var " + deconflicted + " = " + moduleName + "." + x + ";\nexport { " + deconflicted + " as " + x + " };");

		namedExportDeclarations.push({
			str: declaration,
			name: x
		});
	}

	if ( customNamedExports ) { customNamedExports.forEach( addExport ); }

	var defaultExportPropertyAssignments = [];
	var hasDefaultExport = false;

	if ( shouldWrap ) {
		var args = "module" + (uses.exports ? ', exports' : '');

		wrapperStart = "var " + moduleName + " = " + HELPERS_NAME + ".createCommonjsModule(function (" + args + ") {\n";
		wrapperEnd = "\n});";

		Object.keys( namedExports )
			.filter( function (key) { return !blacklist[ key ]; } )
			.forEach( addExport );
	} else {
		var names = [];

		ast.body.forEach( function (node) {
			if ( node.type === 'ExpressionStatement' && node.expression.type === 'AssignmentExpression' ) {
				var left = node.expression.left;
				var flattened = flatten( left );

				if ( !flattened ) { return; }

				var match = exportsPattern.exec( flattened.keypath );
				if ( !match ) { return; }

				if ( flattened.keypath === 'module.exports' ) {
					hasDefaultExport = true;
					magicString.overwrite( left.start, left.end, ("var " + moduleName) );
				} else {
					var name = match[1];
					var deconflicted = deconflict( scope, globals, name );

					names.push({ name: name, deconflicted: deconflicted });

					magicString.overwrite( node.start, left.end, ("var " + deconflicted) );

					var declaration = name === deconflicted ?
						("export { " + name + " };") :
						("export { " + deconflicted + " as " + name + " };");

					namedExportDeclarations.push({
						str: declaration,
						name: name
					});

					defaultExportPropertyAssignments.push( (moduleName + "." + name + " = " + deconflicted + ";") );
				}
			}
		});

		if ( !hasDefaultExport ) {
			wrapperEnd = "\n\nvar " + moduleName + " = {\n" + (names.map( function (ref) {
					var name = ref.name;
					var deconflicted = ref.deconflicted;

					return ("\t" + name + ": " + deconflicted);
			} ).join( ',\n' )) + "\n};";
		}
	}

	var defaultExport = /__esModule/.test( code ) ?
		("export default " + HELPERS_NAME + ".unwrapExports(" + moduleName + ");") :
		("export default " + moduleName + ";");

	var named = namedExportDeclarations
		.filter( function (x) { return x.name !== 'default' || !hasDefaultExport; } )
		.map( function (x) { return x.str; } );

	var exportBlock = '\n\n' + [ defaultExport ]
		.concat( named )
		.concat( hasDefaultExport ? defaultExportPropertyAssignments : [] )
		.join( '\n' );

	magicString.trim()
		.prepend( importBlock + wrapperStart )
		.trim()
		.append( wrapperEnd + exportBlock );

	code = magicString.toString();
	var map = sourceMap ? magicString.generateMap() : null;

	return { code: code, map: map };
}
Example #4
0
	render ( es ) {
		let magicString = this.magicString.clone();

		this.statements.forEach( statement => {
			if ( !statement.isIncluded ) {
				magicString.remove( statement.start, statement.next );
				return;
			}

			statement.stringLiteralRanges.forEach( range => magicString.indentExclusionRanges.push( range ) );

			// skip `export { foo, bar, baz }`
			if ( statement.node.type === 'ExportNamedDeclaration' ) {
				if ( statement.node.isSynthetic ) return;

				// skip `export { foo, bar, baz }`
				if ( statement.node.declaration === null ) {
					magicString.remove( statement.start, statement.next );
					return;
				}
			}

			// split up/remove var declarations as necessary
			if ( statement.node.type === 'VariableDeclaration' ) {
				const declarator = statement.node.declarations[0];

				if ( declarator.id.type === 'Identifier' ) {
					const declaration = this.declarations[ declarator.id.name ];

					if ( declaration.exportName && declaration.isReassigned ) { // `var foo = ...` becomes `exports.foo = ...`
						magicString.remove( statement.start, declarator.init ? declarator.start : statement.next );
						if ( !declarator.init ) return;
					}
				}

				else {
					// we handle destructuring differently, because whereas we can rewrite
					// `var foo = ...` as `exports.foo = ...`, in a case like `var { a, b } = c()`
					// where `a` or `b` is exported and reassigned, we have to append
					// `exports.a = a;` and `exports.b = b` instead
					extractNames( declarator.id ).forEach( name => {
						const declaration = this.declarations[ name ];

						if ( declaration.exportName && declaration.isReassigned ) {
							magicString.insertLeft( statement.end, `;\nexports.${name} = ${declaration.render( es )}` );
						}
					});
				}

				if ( statement.node.isSynthetic ) {
					// insert `var/let/const` if necessary
					magicString.insertRight( statement.start, `${statement.node.kind} ` );
					magicString.insertLeft( statement.end, ';' );
					magicString.overwrite( statement.end, statement.next, '\n' ); // TODO account for trailing newlines
				}
			}

			let toDeshadow = blank();

			statement.references.forEach( reference => {
				const { start, end } = reference;

				if ( reference.isUndefined ) {
					magicString.overwrite( start, end, 'undefined', true );
				}

				const declaration = reference.declaration;

				if ( declaration ) {
					const name = declaration.render( es );

					// the second part of this check is necessary because of
					// namespace optimisation – name of `foo.bar` could be `bar`
					if ( reference.name === name && name.length === end - start ) return;

					reference.rewritten = true;

					// prevent local variables from shadowing renamed references
					const identifier = name.match( /[^\.]+/ )[0];
					if ( reference.scope.contains( identifier ) ) {
						toDeshadow[ identifier ] = `${identifier}$$`; // TODO more robust mechanism
					}

					if ( reference.isShorthandProperty ) {
						magicString.insertLeft( end, `: ${name}` );
					} else {
						magicString.overwrite( start, end, name, true );
					}
				}
			});

			if ( keys( toDeshadow ).length ) {
				statement.references.forEach( reference => {
					if ( !reference.rewritten && reference.name in toDeshadow ) {
						const replacement = toDeshadow[ reference.name ];
						magicString.overwrite( reference.start, reference.end, reference.isShorthandProperty ? `${reference.name}: ${replacement}` : replacement, true );
					}
				});
			}

			// modify exports as necessary
			if ( statement.isExportDeclaration ) {
				// remove `export` from `export var foo = 42`
				// TODO: can we do something simpler here?
				// we just want to remove `export`, right?
				if ( statement.node.type === 'ExportNamedDeclaration' && statement.node.declaration.type === 'VariableDeclaration' ) {
					const name = extractNames( statement.node.declaration.declarations[ 0 ].id )[ 0 ];
					const declaration = this.declarations[ name ];

					// TODO is this even possible?
					if ( !declaration ) throw new Error( `Missing declaration for ${name}!` );

					let end;

					if ( es ) {
						end = statement.node.declaration.start;
					} else {
						if ( declaration.exportName && declaration.isReassigned ) {
							const declarator = statement.node.declaration.declarations[0];
							end = declarator.init ? declarator.start : statement.next;
						} else {
							end = statement.node.declaration.start;
						}
					}

					magicString.remove( statement.node.start, end );
				}

				else if ( statement.node.type === 'ExportAllDeclaration' ) {
					// TODO: remove once `export * from 'external'` is supported.
					magicString.remove( statement.start, statement.next );
				}

				// remove `export` from `export class Foo {...}` or `export default Foo`
				// TODO default exports need different treatment
				else if ( statement.node.declaration.id ) {
					magicString.remove( statement.node.start, statement.node.declaration.start );
				}

				else if ( statement.node.type === 'ExportDefaultDeclaration' ) {
					const defaultDeclaration = this.declarations.default;

					// prevent `var foo = foo`
					if ( defaultDeclaration.original && !defaultDeclaration.original.isReassigned ) {
						magicString.remove( statement.start, statement.next );
						return;
					}

					const defaultName = defaultDeclaration.render();

					// prevent `var undefined = sideEffectyDefault(foo)`
					if ( !defaultDeclaration.exportName && !defaultDeclaration.isUsed ) {
						magicString.remove( statement.start, statement.node.declaration.start );
						return;
					}

					// anonymous functions should be converted into declarations
					if ( statement.node.declaration.type === 'FunctionExpression' ) {
						magicString.overwrite( statement.node.start, statement.node.declaration.start + 8, `function ${defaultName}` );
					} else {
						magicString.overwrite( statement.node.start, statement.node.declaration.start, `${this.bundle.varOrConst} ${defaultName} = ` );
					}
				}

				else {
					throw new Error( 'Unhandled export' );
				}
			}
		});

		// add namespace block if necessary
		const namespace = this.declarations['*'];
		if ( namespace && namespace.needsNamespaceBlock ) {
			magicString.append( '\n\n' + namespace.renderBlock( magicString.getIndentString() ) );
		}

		return magicString.trim();
	}
        transform: function transform(code, id) {
            if (!filter(id)) return null;
            if (extensions.indexOf(path.extname(id)) === -1) return null;
            if (!firstpass.test(code)) return null;

            var ast = void 0;

            try {
                ast = acorn.parse(code, {
                    plugins: { es7: true },
                    ecmaVersion: 6,
                    sourceType: 'module'
                });
            } catch (err) {
                err.message += ' in ' + id;
                throw err;
            }

            var magicString = new MagicString(code);

            var required = {};
            var uid = 0;

            var scope = rollupPluginutils.attachScopes(ast, 'scope');
            var uses = { module: false, exports: false, global: false, es6Export: false };
            if (ignoreGlobal) {
                delete uses.global;
            }
            var usesRequire = false;
            var namedExports = {};
            if (customNamedExports[id]) {
                customNamedExports[id].forEach(function(name) {
                    return namedExports[name] = true;
                });
            }

            var scopeDepth = 0;

            estreeWalker.walk(ast, {
                enter: function enter(node, parent) {
                    if (node.type == "ExportAllDeclaration") uses.es6Export = true;
                    if (node.type == "ExportNamedDeclaration") uses.es6Export = true;
                    if (node.type == "ExportDefaultDeclaration") uses.es6Export = true;
                    if (node.scope) scope = node.scope;
                    if (/^Function/.test(node.type)) scopeDepth += 1;

                    if (sourceMap) {
                        magicString.addSourcemapLocation(node.start);
                        magicString.addSourcemapLocation(node.end);
                    }

                    // Is this an assignment to exports or module.exports?
                    if (node.type === 'AssignmentExpression') {
                        if (node.left.type !== 'MemberExpression') return;

                        var flattened = flatten(node.left);
                        if (!flattened) return;

                        if (scope.contains(flattened.name)) return;

                        var match = exportsPattern.exec(flattened.keypath);
                        if (!match || flattened.keypath === 'exports') return;

                        if (flattened.keypath === 'module.exports' && node.right.type === 'ObjectExpression') {
                            return node.right.properties.forEach(function(prop) {
                                if (prop.computed || prop.key.type !== 'Identifier') return;
                                var name = prop.key.name;
                                if (name === rollupPluginutils.makeLegalIdentifier(name)) namedExports[name] = true;
                            });
                        }

                        if (match[1]) namedExports[match[1]] = true;

                        return;
                    }

                    if (node.type === 'Identifier') {
                        if (node.name in uses && !uses[node.name] && isReference(node, parent) && !scope.contains(node.name)) {
                            if (parent && (parent.operator === 'typeof' || parent.type === 'ConditionalExpression')) {
                                return;
                            } else {
                                if (node.name === 'global') {
                                    magicString.overwrite(node.start, node.end, '__commonjs_global', true);
                                }
                                uses[node.name] = true;
                            }
                        }
                        return;
                    }

                    if (node.type === 'ThisExpression' && scopeDepth === 0 && !ignoreGlobal) {
                        uses.global = true;
                        magicString.overwrite(node.start, node.end, '__commonjs_global', true);
                        return;
                    }

                    if (node.type !== 'CallExpression') return;
                    if (node.callee.name !== 'require' || scope.contains('require')) return;
                    if (node.arguments.length !== 1 || node.arguments[0].type !== 'Literal') return; // TODO handle these weird cases?
                    usesRequire = true;
                    var source = node.arguments[0].value;

                    var existing = required[source];
                    var name = void 0;

                    if (!existing) {
                        name = 'require$$' + uid++;
                        required[source] = { source: source, name: name, importsDefault: false };
                    } else {
                        name = required[source].name;
                    }


                    if (parent.type !== 'ExpressionStatement') {
                        required[source].importsDefault = true;
                        magicString.overwrite(node.start, node.end, name);
                    } else {
                        // is a bare import, e.g. `require('foo');`
                        magicString.remove(parent.start, parent.end);
                    }
                },
                leave: function leave(node) {
                    if (node.scope) scope = scope.parent;
                    if (/^Function/.test(node.type)) scopeDepth -= 1;
                }
            });

            var sources = Object.keys(required);
            if (options.ignoreGlobal) {
                uses.global = false;
            }

            if (!sources.length && !uses.module && !uses.exports && !uses.global && !usesRequire) {
                if (Object.keys(namedExports).length) {
                    throw new Error('Custom named exports were specified for ' + id + ' but it does not appear to be a CommonJS module');
                }
                return null; // not a CommonJS module
            }

            var importBlock = sources.length ? sources.map(function(source) {
                var _required$source = required[source];
                var name = _required$source.name;
                var importsDefault = _required$source.importsDefault;

                return 'import ' + (importsDefault ? name + ' from ' : '') + '\'' + source + '\';';
            }).join('\n') : '';

            if (!uses.es6Export) {
                var intro = '\n\nvar module = {exports: {}};\n\nvar exports = module.exports;\n\n';
                var outro = '\n\nexport default __get_exports(module);\n';

                outro += Object.keys(namedExports).filter(function(key) {
                    return !blacklistedExports[key];
                }).map(function(x) {
                    return 'export var ' + x + ' = module.exports.' + x + ';';
                }).join('\n');


                magicString.trim().prepend(importBlock + intro).trim().append(outro);
            } else {
                magicString.trim().prepend(importBlock).trim();
                //                                  console.log(magicString.slice(parent.start, parent.end));
                //console.log(magicString.toString());
            }

            code = magicString.toString();
            var map = sourceMap ? magicString.generateMap() : null;

            if (uses.global) bundleUsesGlobal = true;
            return { code: code, map: map };
        },
export function transformCommonjs(
	parse,
	code,
	id,
	isEntry,
	ignoreGlobal,
	ignoreRequire,
	customNamedExports,
	sourceMap,
	allowDynamicRequire,
	astCache
) {
	const ast = astCache || tryParse(parse, code, id);

	const magicString = new MagicString(code);

	const required = {};
	// Because objects have no guaranteed ordering, yet we need it,
	// we need to keep track of the order in a array
	const sources = [];

	let uid = 0;

	let scope = attachScopes(ast, 'scope');
	const uses = { module: false, exports: false, global: false, require: false };

	let lexicalDepth = 0;
	let programDepth = 0;

	const globals = new Set();

	const HELPERS_NAME = deconflict(scope, globals, 'commonjsHelpers'); // TODO technically wrong since globals isn't populated yet, but ¯\_(ツ)_/¯

	const namedExports = {};

	// TODO handle transpiled modules
	let shouldWrap = /__esModule/.test(code);

	function isRequireStatement(node) {
		if (!node) return;
		if (node.type !== 'CallExpression') return;
		if (node.callee.name !== 'require' || scope.contains('require')) return;
		if (node.arguments.length === 0) return; // Weird case of require() without arguments
		return true;
	}

	function hasDynamicArguments(node) {
		return (
			node.arguments.length > 1 ||
			(node.arguments[0].type !== 'Literal' &&
				(node.arguments[0].type !== 'TemplateLiteral' || node.arguments[0].expressions.length > 0))
		);
	}

	function isStaticRequireStatement(node) {
		if (!isRequireStatement(node)) return;
		if (hasDynamicArguments(node)) return;
		if (ignoreRequire(node.arguments[0].value)) return;
		return true;
	}

	function getRequireStringArg(node) {
		return node.arguments[0].type === 'Literal'
			? node.arguments[0].value
			: node.arguments[0].quasis[0].value.cooked;
	}

	function getRequired(node, name) {
		const sourceId = getRequireStringArg(node);
		const existing = required[sourceId];
		if (existing === undefined) {
			if (!name) {
				do name = `require$$${uid++}`;
				while (scope.contains(name));
			}

			sources.push(sourceId);
			required[sourceId] = { source: sourceId, name, importsDefault: false };
		}

		return required[sourceId];
	}

	// do a first pass, see which names are assigned to. This is necessary to prevent
	// illegally replacing `var foo = require('foo')` with `import foo from 'foo'`,
	// where `foo` is later reassigned. (This happens in the wild. CommonJS, sigh)
	const assignedTo = new Set();
	walk(ast, {
		enter(node) {
			if (node.type !== 'AssignmentExpression') return;
			if (node.left.type === 'MemberExpression') return;

			extractNames(node.left).forEach(name => {
				assignedTo.add(name);
			});
		}
	});

	walk(ast, {
		enter(node, parent) {
			if (sourceMap) {
				magicString.addSourcemapLocation(node.start);
				magicString.addSourcemapLocation(node.end);
			}

			// skip dead branches
			if (parent && (parent.type === 'IfStatement' || parent.type === 'ConditionalExpression')) {
				if (node === parent.consequent && isFalsy(parent.test)) return this.skip();
				if (node === parent.alternate && isTruthy(parent.test)) return this.skip();
			}

			if (node._skip) return this.skip();

			programDepth += 1;

			if (node.scope) scope = node.scope;
			if (functionType.test(node.type)) lexicalDepth += 1;

			// if toplevel return, we need to wrap it
			if (node.type === 'ReturnStatement' && lexicalDepth === 0) {
				shouldWrap = true;
			}

			// rewrite `this` as `commonjsHelpers.commonjsGlobal`
			if (node.type === 'ThisExpression' && lexicalDepth === 0) {
				uses.global = true;
				if (!ignoreGlobal)
					magicString.overwrite(node.start, node.end, `${HELPERS_NAME}.commonjsGlobal`, {
						storeName: true
					});
				return;
			}

			// rewrite `typeof module`, `typeof module.exports` and `typeof exports` (https://github.com/rollup/rollup-plugin-commonjs/issues/151)
			if (node.type === 'UnaryExpression' && node.operator === 'typeof') {
				const flattened = flatten(node.argument);
				if (!flattened) return;

				if (scope.contains(flattened.name)) return;

				if (
					flattened.keypath === 'module.exports' ||
					flattened.keypath === 'module' ||
					flattened.keypath === 'exports'
				) {
					magicString.overwrite(node.start, node.end, `'object'`, { storeName: false });
				}
			}

			// rewrite `require` (if not already handled) `global` and `define`, and handle free references to
			// `module` and `exports` as these mean we need to wrap the module in commonjsHelpers.createCommonjsModule
			if (node.type === 'Identifier') {
				if (isReference(node, parent) && !scope.contains(node.name)) {
					if (node.name in uses) {
						if (node.name === 'require') {
							if (allowDynamicRequire) return;
							magicString.overwrite(node.start, node.end, `${HELPERS_NAME}.commonjsRequire`, {
								storeName: true
							});
						}

						uses[node.name] = true;
						if (node.name === 'global' && !ignoreGlobal) {
							magicString.overwrite(node.start, node.end, `${HELPERS_NAME}.commonjsGlobal`, {
								storeName: true
							});
						}

						// if module or exports are used outside the context of an assignment
						// expression, we need to wrap the module
						if (node.name === 'module' || node.name === 'exports') {
							shouldWrap = true;
						}
					}

					if (node.name === 'define') {
						magicString.overwrite(node.start, node.end, 'undefined', { storeName: true });
					}

					globals.add(node.name);
				}

				return;
			}

			// Is this an assignment to exports or module.exports?
			if (node.type === 'AssignmentExpression') {
				if (node.left.type !== 'MemberExpression') return;

				const flattened = flatten(node.left);
				if (!flattened) return;

				if (scope.contains(flattened.name)) return;

				const match = exportsPattern.exec(flattened.keypath);
				if (!match || flattened.keypath === 'exports') return;

				uses[flattened.name] = true;

				// we're dealing with `module.exports = ...` or `[module.]exports.foo = ...` –
				// if this isn't top-level, we'll need to wrap the module
				if (programDepth > 3) shouldWrap = true;

				node.left._skip = true;

				if (flattened.keypath === 'module.exports' && node.right.type === 'ObjectExpression') {
					return node.right.properties.forEach(prop => {
						if (prop.computed || prop.key.type !== 'Identifier') return;
						const name = prop.key.name;
						if (name === makeLegalIdentifier(name)) namedExports[name] = true;
					});
				}

				if (match[1]) namedExports[match[1]] = true;
				return;
			}

			// if this is `var x = require('x')`, we can do `import x from 'x'`
			if (
				node.type === 'VariableDeclarator' &&
				node.id.type === 'Identifier' &&
				isStaticRequireStatement(node.init)
			) {
				// for now, only do this for top-level requires. maybe fix this in future
				if (scope.parent) return;

				// edge case — CJS allows you to assign to imports. ES doesn't
				if (assignedTo.has(node.id.name)) return;

				const required = getRequired(node.init, node.id.name);
				required.importsDefault = true;

				if (required.name === node.id.name) {
					node._shouldRemove = true;
				}
			}

			if (!isStaticRequireStatement(node)) return;

			const required = getRequired(node);

			if (parent.type === 'ExpressionStatement') {
				// is a bare import, e.g. `require('foo');`
				magicString.remove(parent.start, parent.end);
			} else {
				required.importsDefault = true;
				magicString.overwrite(node.start, node.end, required.name);
			}

			node.callee._skip = true;
		},

		leave(node) {
			programDepth -= 1;
			if (node.scope) scope = scope.parent;
			if (functionType.test(node.type)) lexicalDepth -= 1;

			if (node.type === 'VariableDeclaration') {
				let keepDeclaration = false;
				let c = node.declarations[0].start;

				for (let i = 0; i < node.declarations.length; i += 1) {
					const declarator = node.declarations[i];

					if (declarator._shouldRemove) {
						magicString.remove(c, declarator.end);
					} else {
						if (!keepDeclaration) {
							magicString.remove(c, declarator.start);
							keepDeclaration = true;
						}

						c = declarator.end;
					}
				}

				if (!keepDeclaration) {
					magicString.remove(node.start, node.end);
				}
			}
		}
	});

	if (
		!sources.length &&
		!uses.module &&
		!uses.exports &&
		!uses.require &&
		(ignoreGlobal || !uses.global)
	) {
		if (Object.keys(namedExports).length) {
			throw new Error(
				`Custom named exports were specified for ${id} but it does not appear to be a CommonJS module`
			);
		}
		return null; // not a CommonJS module
	}

	const includeHelpers = shouldWrap || uses.global || uses.require;
	const importBlock =
		(includeHelpers ? [`import * as ${HELPERS_NAME} from '${HELPERS_ID}';`] : [])
			.concat(
				sources.map(source => {
					// import the actual module before the proxy, so that we know
					// what kind of proxy to build
					return `import '${source}';`;
				}),
				sources.map(source => {
					const { name, importsDefault } = required[source];
					return `import ${importsDefault ? `${name} from ` : ``}'${PROXY_PREFIX}${source}';`;
				})
			)
			.join('\n') + '\n\n';

	const namedExportDeclarations = [];
	let wrapperStart = '';
	let wrapperEnd = '';

	const moduleName = deconflict(scope, globals, getName(id));
	if (!isEntry) {
		const exportModuleExports = {
			str: `export { ${moduleName} as __moduleExports };`,
			name: '__moduleExports'
		};

		namedExportDeclarations.push(exportModuleExports);
	}

	const name = getName(id);

	function addExport(x) {
		const deconflicted = deconflict(scope, globals, name);

		const declaration =
			deconflicted === name
				? `export var ${x} = ${moduleName}.${x};`
				: `var ${deconflicted} = ${moduleName}.${x};\nexport { ${deconflicted} as ${x} };`;

		namedExportDeclarations.push({
			str: declaration,
			name: x
		});
	}

	if (customNamedExports) customNamedExports.forEach(addExport);

	const defaultExportPropertyAssignments = [];
	let hasDefaultExport = false;

	if (shouldWrap) {
		const args = `module${uses.exports ? ', exports' : ''}`;

		wrapperStart = `var ${moduleName} = ${HELPERS_NAME}.createCommonjsModule(function (${args}) {\n`;
		wrapperEnd = `\n});`;
	} else {
		const names = [];

		ast.body.forEach(node => {
			if (node.type === 'ExpressionStatement' && node.expression.type === 'AssignmentExpression') {
				const left = node.expression.left;
				const flattened = flatten(left);

				if (!flattened) return;

				const match = exportsPattern.exec(flattened.keypath);
				if (!match) return;

				if (flattened.keypath === 'module.exports') {
					hasDefaultExport = true;
					magicString.overwrite(left.start, left.end, `var ${moduleName}`);
				} else {
					const name = match[1];
					const deconflicted = deconflict(scope, globals, name);

					names.push({ name, deconflicted });

					magicString.overwrite(node.start, left.end, `var ${deconflicted}`);

					const declaration =
						name === deconflicted
							? `export { ${name} };`
							: `export { ${deconflicted} as ${name} };`;

					if (name !== 'default') {
						namedExportDeclarations.push({
							str: declaration,
							name
						});
						delete namedExports[name];
					}

					defaultExportPropertyAssignments.push(`${moduleName}.${name} = ${deconflicted};`);
				}
			}
		});

		if (!hasDefaultExport) {
			wrapperEnd = `\n\nvar ${moduleName} = {\n${names
				.map(({ name, deconflicted }) => `\t${name}: ${deconflicted}`)
				.join(',\n')}\n};`;
		}
	}
	Object.keys(namedExports)
		.filter(key => !blacklist[key])
		.forEach(addExport);

	const defaultExport = /__esModule/.test(code)
		? `export default ${HELPERS_NAME}.unwrapExports(${moduleName});`
		: `export default ${moduleName};`;

	const named = namedExportDeclarations
		.filter(x => x.name !== 'default' || !hasDefaultExport)
		.map(x => x.str);

	const exportBlock =
		'\n\n' +
		[defaultExport]
			.concat(named)
			.concat(hasDefaultExport ? defaultExportPropertyAssignments : [])
			.join('\n');

	magicString
		.trim()
		.prepend(importBlock + wrapperStart)
		.trim()
		.append(wrapperEnd + exportBlock);

	code = magicString.toString();
	const map = sourceMap ? magicString.generateMap() : null;

	return { code, map };
}