コード例 #1
0
export default function(code, id, mod1, mod2, sourceMap) {
  let ast;

  try {
    ast = parse(code, {
      ecmaVersion: 6,
      sourceType: 'module'
    });
  } catch (err) {
    err.message += ` in ${id}`;
    throw err;
  }
  // analyse scopes
  let scope = attachScopes(ast, 'scope');

  let imports = {};
  ast.body.forEach(node => {
    if (node.type === 'ImportDeclaration') {
      node.specifiers.forEach(specifier => {
        imports[specifier.local.name] = true;
      });
    }
  });

  const magicString = new MagicString(code);

  let newImports = {};

  function handleReference(node, name, keypath, parent) {
    if ((mod1.has(keypath) || mod2.has(keypath)) && !scope.contains(name) && !imports[name]) {
      if (mod2.has(keypath) && parent.__handled) {
        return;
      }
      let module = mod1.has(keypath) ? mod1.get(keypath) : mod2.get(keypath);
      let moduleName, hash;
      if (typeof module === 'string') {
        moduleName = module;
        hash = `${keypath}:${moduleName}:default`;
      } else {
        moduleName = module[0];
        hash = `${keypath}:${moduleName}:${module[1]}`;
      }
      // prevent module from importing itself
      if (moduleName === id) return;

      const importLocalName = name === keypath ? name : makeLegalIdentifier(`$inject_${keypath}`);

      if (!newImports[hash]) {
        newImports[hash] = `import ${typeof module === 'string' ? importLocalName : `{ ${module[1]} as ${importLocalName} }`} from ${JSON.stringify(moduleName)};`;
      }

      if (name !== keypath) {
        magicString.overwrite(node.start, node.end, importLocalName, true);
      }
      if (mod1.has(keypath)) {
        node.__handled = true;
      }
    }
  }

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

      if (node.scope) scope = node.scope;

      // special case – shorthand properties. because node.key === node.value,
      // we can't differentiate once we've descended into the node
      if (node.type === 'Property' && node.shorthand) {
        const name = node.key.name;
        handleReference(node, name, name);
        return this.skip();
      }

      if (isReference(node, parent)) {
        const {
          name,
          keypath
        } = flatten(node);
        handleReference(node, name, keypath, parent);
      }
    },
    leave(node) {
      if (node.scope) scope = scope.parent;
    }
  });

  const keys = Object.keys(newImports);
  if (!keys.length) return null;

  const importBlock = keys.map(hash => newImports[hash]).join('\n\n');
  magicString.prepend(importBlock + '\n\n');

  return {
    code: magicString.toString(),
    map: sourceMap ? magicString.generateMap() : null
  };
}
コード例 #2
0
export default function inject ( options ) {
	if ( !options ) throw new Error( 'Missing options' );

	const filter = createFilter( options.include, options.exclude );

	let modules;

	if ( options.modules ) {
		modules = options.modules;
	} else {
		modules = assign( {}, options );
		delete modules.include;
		delete modules.exclude;
	}

	// Fix paths on Windows
	if ( sep !== '/' ) {
		Object.keys( modules ).forEach( key => {
			const module = modules[ key ];

			modules[ key ] = isArray( module ) ?
				[ module[0].split( sep ).join( '/' ), module[1] ] :
				module.split( sep ).join( '/' );
		});
	}

	const firstpass = new RegExp( `(?:${Object.keys( modules ).map( escape ).join( '|' )})`, 'g' );
	const sourceMap = options.sourceMap !== false;

	return {
		transform ( code, id ) {
			if ( !filter( id ) ) return null;
			if ( code.search( firstpass ) == -1 ) return null;

			let ast;

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

			// analyse scopes
			let scope = attachScopes( ast, 'scope' );

			let imports = {};
			ast.body.forEach( node => {
				if ( node.type === 'ImportDeclaration' ) {
					node.specifiers.forEach( specifier => {
						imports[ specifier.local.name ] = true;
					});
				}
			});

			const magicString = new MagicString( code );

			let newImports = {};

			function handleReference ( node, name, keypath ) {
				if ( keypath in modules && !scope.contains( name ) && !imports[ name ] ) {
					let module = modules[ keypath ];
					if ( typeof module === 'string' ) module = [ module, 'default' ];

					// prevent module from importing itself
					if ( module[0] === id ) return;

					const hash = `${keypath}:${module[0]}:${module[1]}`;

					const importLocalName = name === keypath ? name : makeLegalIdentifier( `$inject_${keypath}` );

					if ( !newImports[ hash ] ) {
						newImports[ hash ] = `import { ${module[1]} as ${importLocalName} } from '${module[0]}';`;
					}

					if ( name !== keypath ) {
						magicString.overwrite( node.start, node.end, importLocalName, true );
					}
				}
			}

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

					if ( node.scope ) scope = node.scope;

					// special case – shorthand properties. because node.key === node.value,
					// we can't differentiate once we've descended into the node
					if ( node.type === 'Property' && node.shorthand ) {
						const name = node.key.name;
						handleReference( node, name, name );
						return this.skip();
					}

					if ( isReference( node, parent ) ) {
						const { name, keypath } = flatten( node );
						handleReference( node, name, keypath );
					}
				},
				leave ( node ) {
					if ( node.scope ) scope = scope.parent;
				}
			});

			const keys = Object.keys( newImports );
			if ( !keys.length ) return null;

			const importBlock = keys.map( hash => newImports[ hash ] ).join( '\n\n' );
			magicString.prepend( importBlock + '\n\n' );

			return {
				code: magicString.toString(),
				map: sourceMap ? magicString.generateMap() : null
			};
		}
	};
}
コード例 #3
0
var inject = function (code, id, mod1, mod2, sourceMap) {
  var ast = void 0;

  try {
    ast = parse(code, {
      ecmaVersion: 6,
      sourceType: 'module'
    });
  } catch (err) {
    err.message += ' in ' + id;
    throw err;
  }
  // analyse scopes
  var scope = attachScopes(ast, 'scope');

  var imports = {};
  ast.body.forEach(function (node) {
    if (node.type === 'ImportDeclaration') {
      node.specifiers.forEach(function (specifier) {
        imports[specifier.local.name] = true;
      });
    }
  });

  var magicString = new MagicString(code);

  var newImports = {};

  function handleReference(node, name, keypath, parent) {
    if ((mod1.has(keypath) || mod2.has(keypath)) && !scope.contains(name) && !imports[name]) {
      if (mod2.has(keypath) && parent.__handled) {
        return;
      }
      var module = mod1.has(keypath) ? mod1.get(keypath) : mod2.get(keypath);
      var moduleName = void 0,
          hash = void 0;
      if (typeof module === 'string') {
        moduleName = module;
        hash = keypath + ':' + moduleName + ':default';
      } else {
        moduleName = module[0];
        hash = keypath + ':' + moduleName + ':' + module[1];
      }
      // prevent module from importing itself
      if (moduleName === id) return;

      var importLocalName = name === keypath ? name : makeLegalIdentifier('$inject_' + keypath);

      if (!newImports[hash]) {
        newImports[hash] = 'import ' + (typeof module === 'string' ? importLocalName : '{ ' + module[1] + ' as ' + importLocalName + ' }') + ' from ' + JSON.stringify(moduleName) + ';';
      }

      if (name !== keypath) {
        magicString.overwrite(node.start, node.end, importLocalName, true);
      }
      if (mod1.has(keypath)) {
        node.__handled = true;
      }
    }
  }

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

      if (node.scope) scope = node.scope;

      // special case – shorthand properties. because node.key === node.value,
      // we can't differentiate once we've descended into the node
      if (node.type === 'Property' && node.shorthand) {
        var name = node.key.name;
        handleReference(node, name, name);
        return this.skip();
      }

      if (isReference(node, parent)) {
        var _flatten = flatten(node),
            _name = _flatten.name,
            keypath = _flatten.keypath;

        handleReference(node, _name, keypath, parent);
      }
    },
    leave: function leave(node) {
      if (node.scope) scope = scope.parent;
    }
  });

  var keys = Object.keys(newImports);
  if (!keys.length) return null;

  var importBlock = keys.map(function (hash) {
    return newImports[hash];
  }).join('\n\n');
  magicString.prepend(importBlock + '\n\n');

  return {
    code: magicString.toString(),
    map: sourceMap ? magicString.generateMap() : null
  };
};