diff --git a/src/Bundle.js b/src/Bundle.js index 1c28ce3..07a788c 100644 --- a/src/Bundle.js +++ b/src/Bundle.js @@ -15,7 +15,7 @@ import transformBundle from './utils/transformBundle.js'; import collapseSourcemaps from './utils/collapseSourcemaps.js'; import SOURCEMAPPING_URL from './utils/sourceMappingURL.js'; import callIfFunction from './utils/callIfFunction.js'; -import { isRelative, resolve } from './utils/path.js'; +import { dirname, isRelative, relative, resolve } from './utils/path.js'; export default class Bundle { constructor ( options ) { @@ -28,6 +28,7 @@ export default class Bundle { }); this.entry = unixizePath( options.entry ); + this.entryId = null; this.entryModule = null; this.resolveId = first( @@ -71,7 +72,10 @@ export default class Bundle { // modules it imports, and import those, until we have all // of the entry module's dependencies return this.resolveId( this.entry, undefined ) - .then( id => this.fetchModule( id, undefined ) ) + .then( id => { + this.entryId = id; + return this.fetchModule( id, undefined ); + }) .then( entryModule => { this.entryModule = entryModule; @@ -189,16 +193,20 @@ export default class Bundle { const forcedExternal = externalName && ~this.external.indexOf( externalName ); if ( !resolvedId || forcedExternal ) { + let normalizedExternal = source; + if ( !forcedExternal ) { if ( isRelative( source ) ) throw new Error( `Could not resolve ${source} from ${module.id}` ); if ( !~this.external.indexOf( source ) ) this.onwarn( `Treating '${source}' as external dependency` ); + } else if ( resolvedId ) { + normalizedExternal = this.getPathRelativeToEntryDirname( resolvedId ); } - module.resolvedIds[ source ] = source; + module.resolvedIds[ source ] = normalizedExternal; - if ( !this.moduleById[ source ] ) { - const module = new ExternalModule( source ); + if ( !this.moduleById[ normalizedExternal ] ) { + const module = new ExternalModule( normalizedExternal ); this.externalModules.push( module ); - this.moduleById[ source ] = module; + this.moduleById[ normalizedExternal ] = module; } } @@ -214,6 +222,19 @@ export default class Bundle { }); } + getPathRelativeToEntryDirname ( resolvedId ) { + // Get a path relative to the resolved entry directory + const entryDirname = dirname( this.entryId ); + const relativeToEntry = relative( entryDirname, resolvedId ); + + if ( isRelative( relativeToEntry )) { + return relativeToEntry; + } + + // The path is missing the `./` prefix + return `./${relativeToEntry}`; + } + render ( options = {} ) { const format = options.format || 'es6'; diff --git a/test/function/relative-external-include-once-nested/_config.js b/test/function/relative-external-include-once-nested/_config.js new file mode 100644 index 0000000..07aa08e --- /dev/null +++ b/test/function/relative-external-include-once-nested/_config.js @@ -0,0 +1,18 @@ +var assert = require( 'assert' ); +var path = require( 'path' ); + +module.exports = { + description: 'includes a relative external module only once (nested version)', + options: { + external: path.join( __dirname, './first/foo.js' ) + }, + context: { + require: function ( required ) { + assert.equal( required, './first/foo.js' ); + return 1; + } + }, + exports: function ( exports ) { + assert.equal( exports, 3 ); + } +}; diff --git a/test/function/relative-external-include-once-nested/first/foo.js b/test/function/relative-external-include-once-nested/first/foo.js new file mode 100644 index 0000000..e69de29 diff --git a/test/function/relative-external-include-once-nested/first/module.js b/test/function/relative-external-include-once-nested/first/module.js new file mode 100644 index 0000000..a0aecca --- /dev/null +++ b/test/function/relative-external-include-once-nested/first/module.js @@ -0,0 +1,4 @@ +import foo from './foo'; +import second from './second/module'; + +export default foo + second; diff --git a/test/function/relative-external-include-once-nested/first/second/module.js b/test/function/relative-external-include-once-nested/first/second/module.js new file mode 100644 index 0000000..4fa8fdc --- /dev/null +++ b/test/function/relative-external-include-once-nested/first/second/module.js @@ -0,0 +1,3 @@ +import foo from '../foo'; + +export default foo; diff --git a/test/function/relative-external-include-once-nested/main.js b/test/function/relative-external-include-once-nested/main.js new file mode 100644 index 0000000..545e333 --- /dev/null +++ b/test/function/relative-external-include-once-nested/main.js @@ -0,0 +1,4 @@ +import foo from './first/foo'; +import first from './first/module'; + +export default foo + first; diff --git a/test/function/relative-external-include-once-two-external/_config.js b/test/function/relative-external-include-once-two-external/_config.js new file mode 100644 index 0000000..d83e72f --- /dev/null +++ b/test/function/relative-external-include-once-two-external/_config.js @@ -0,0 +1,22 @@ +var assert = require( 'assert' ); +var path = require( 'path' ); + + +module.exports = { + description: 'includes a relative external module only once (two external deps)', + options: { + external: [ + path.join( __dirname, './foo.js' ), + path.join( __dirname, './first/foo.js' ) + ] + }, + context: { + require: function ( required ) { + assert( [ './foo.js', './first/foo.js' ].indexOf(required) !== -1, 'required wrong module' ); + return required === './foo.js' ? 'a' : 'b'; + } + }, + exports: function ( exports ) { + assert( exports === 'ab' || exports === 'ba', 'two different modules should be required' ); + } +}; diff --git a/test/function/relative-external-include-once-two-external/first/foo.js b/test/function/relative-external-include-once-two-external/first/foo.js new file mode 100644 index 0000000..e69de29 diff --git a/test/function/relative-external-include-once-two-external/first/module.js b/test/function/relative-external-include-once-two-external/first/module.js new file mode 100644 index 0000000..4ad6554 --- /dev/null +++ b/test/function/relative-external-include-once-two-external/first/module.js @@ -0,0 +1,3 @@ +import foo from './foo'; + +export default foo; diff --git a/test/function/relative-external-include-once-two-external/foo.js b/test/function/relative-external-include-once-two-external/foo.js new file mode 100644 index 0000000..e69de29 diff --git a/test/function/relative-external-include-once-two-external/main.js b/test/function/relative-external-include-once-two-external/main.js new file mode 100644 index 0000000..dff375c --- /dev/null +++ b/test/function/relative-external-include-once-two-external/main.js @@ -0,0 +1,4 @@ +import foo from './foo'; +import first from './first/module'; + +export default foo + first; diff --git a/test/function/relative-external-include-once-up/_config.js b/test/function/relative-external-include-once-up/_config.js new file mode 100644 index 0000000..15821ba --- /dev/null +++ b/test/function/relative-external-include-once-up/_config.js @@ -0,0 +1,19 @@ +var assert = require( 'assert' ); +var path = require( 'path' ); + +module.exports = { + description: 'includes a relative external module only once (from upper directory too)', + options: { + entry: path.join( __dirname, 'first', 'main.js' ), + external: path.join( __dirname, './foo.js' ) + }, + context: { + require: function ( required ) { + assert.equal( required, '../foo.js' ); + return 1; + } + }, + exports: function ( exports ) { + assert.equal( exports, 3 ); + } +}; diff --git a/test/function/relative-external-include-once-up/first/main.js b/test/function/relative-external-include-once-up/first/main.js new file mode 100644 index 0000000..a07e358 --- /dev/null +++ b/test/function/relative-external-include-once-up/first/main.js @@ -0,0 +1,4 @@ +import foo from '../foo'; +import first from './module'; + +export default foo + first; diff --git a/test/function/relative-external-include-once-up/first/module.js b/test/function/relative-external-include-once-up/first/module.js new file mode 100644 index 0000000..0798b47 --- /dev/null +++ b/test/function/relative-external-include-once-up/first/module.js @@ -0,0 +1,4 @@ +import foo from '../foo'; +import second from './second/module'; + +export default foo + second; diff --git a/test/function/relative-external-include-once-up/first/second/module.js b/test/function/relative-external-include-once-up/first/second/module.js new file mode 100644 index 0000000..b643f0c --- /dev/null +++ b/test/function/relative-external-include-once-up/first/second/module.js @@ -0,0 +1,3 @@ +import foo from '../../foo'; + +export default foo; diff --git a/test/function/relative-external-include-once-up/foo.js b/test/function/relative-external-include-once-up/foo.js new file mode 100644 index 0000000..e69de29 diff --git a/test/function/relative-external-include-once/_config.js b/test/function/relative-external-include-once/_config.js new file mode 100644 index 0000000..4349dc1 --- /dev/null +++ b/test/function/relative-external-include-once/_config.js @@ -0,0 +1,18 @@ +var assert = require( 'assert' ); +var path = require( 'path' ); + +module.exports = { + description: 'includes a relative external module only once', + options: { + external: path.join( __dirname, './foo.js' ) + }, + context: { + require: function ( required ) { + assert.equal( required, './foo.js' ); + return 1; + } + }, + exports: function ( exports ) { + assert.equal( exports, 3 ); + } +}; diff --git a/test/function/relative-external-include-once/first/module.js b/test/function/relative-external-include-once/first/module.js new file mode 100644 index 0000000..0798b47 --- /dev/null +++ b/test/function/relative-external-include-once/first/module.js @@ -0,0 +1,4 @@ +import foo from '../foo'; +import second from './second/module'; + +export default foo + second; diff --git a/test/function/relative-external-include-once/first/second/module.js b/test/function/relative-external-include-once/first/second/module.js new file mode 100644 index 0000000..b643f0c --- /dev/null +++ b/test/function/relative-external-include-once/first/second/module.js @@ -0,0 +1,3 @@ +import foo from '../../foo'; + +export default foo; diff --git a/test/function/relative-external-include-once/foo.js b/test/function/relative-external-include-once/foo.js new file mode 100644 index 0000000..e69de29 diff --git a/test/function/relative-external-include-once/main.js b/test/function/relative-external-include-once/main.js new file mode 100644 index 0000000..dff375c --- /dev/null +++ b/test/function/relative-external-include-once/main.js @@ -0,0 +1,4 @@ +import foo from './foo'; +import first from './first/module'; + +export default foo + first; diff --git a/test/test.js b/test/test.js index 39a81fc..358e390 100644 --- a/test/test.js +++ b/test/test.js @@ -133,9 +133,9 @@ describe( 'rollup', function () { var config = loadConfig( FUNCTION + '/' + dir + '/_config.js' ); ( config.skip ? it.skip : config.solo ? it.only : it )( dir, function () { - var options = extend( {}, config.options, { + var options = extend( { entry: FUNCTION + '/' + dir + '/main.js' - }); + }, config.options ); if ( config.solo ) console.group( dir );