|
|
@ -1,8 +1,9 @@ |
|
|
|
import { decode } from 'sourcemap-codec'; |
|
|
|
import { locate } from 'locate-character'; |
|
|
|
import error from './error.js'; |
|
|
|
import relativeId from './relativeId.js'; |
|
|
|
import getCodeFrame from './getCodeFrame.js'; |
|
|
|
|
|
|
|
export default function transform ( source, id, plugins ) { |
|
|
|
export default function transform ( bundle, source, id, plugins ) { |
|
|
|
const sourceMapChain = []; |
|
|
|
|
|
|
|
const originalSourceMap = typeof source.map === 'string' ? JSON.parse( source.map ) : source.map; |
|
|
@ -13,13 +14,57 @@ export default function transform ( source, id, plugins ) { |
|
|
|
|
|
|
|
const originalCode = source.code; |
|
|
|
let ast = source.ast; |
|
|
|
let errored = false; |
|
|
|
|
|
|
|
return plugins.reduce( ( promise, plugin ) => { |
|
|
|
return promise.then( previous => { |
|
|
|
if ( !plugin.transform ) return previous; |
|
|
|
let promise = Promise.resolve( source.code ); |
|
|
|
|
|
|
|
plugins.forEach( plugin => { |
|
|
|
if ( !plugin.transform ) return; |
|
|
|
|
|
|
|
promise = promise.then( previous => { |
|
|
|
function augment ( object, pos, code ) { |
|
|
|
if ( typeof object === 'string' ) { |
|
|
|
object = { message: object }; |
|
|
|
} |
|
|
|
|
|
|
|
if ( !object.code ) object.code = code; |
|
|
|
|
|
|
|
if ( pos !== undefined ) { |
|
|
|
object.pos = pos; |
|
|
|
const { line, column } = locate( previous, pos, { offsetLine: 1 }); |
|
|
|
object.loc = { file: id, line, column }; |
|
|
|
object.frame = getCodeFrame( previous, line, column ); |
|
|
|
} |
|
|
|
|
|
|
|
return object; |
|
|
|
} |
|
|
|
|
|
|
|
let err; |
|
|
|
|
|
|
|
const context = { |
|
|
|
warn: ( warning, pos ) => { |
|
|
|
warning = augment( warning, pos, 'PLUGIN_WARNING' ); |
|
|
|
warning.plugin = plugin.name; |
|
|
|
warning.id = id; |
|
|
|
bundle.warn( warning ); |
|
|
|
}, |
|
|
|
|
|
|
|
error ( e, pos ) { |
|
|
|
err = augment( e, pos, 'PLUGIN_ERROR' ); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
let transformed; |
|
|
|
|
|
|
|
try { |
|
|
|
transformed = plugin.transform.call( context, previous, id ); |
|
|
|
} catch ( err ) { |
|
|
|
context.error( err ); |
|
|
|
} |
|
|
|
|
|
|
|
return Promise.resolve( transformed ) |
|
|
|
.then( result => { |
|
|
|
if ( err ) throw err; |
|
|
|
|
|
|
|
return Promise.resolve( plugin.transform( previous, id ) ).then( result => { |
|
|
|
if ( result == null ) return previous; |
|
|
|
|
|
|
|
if ( typeof result === 'string' ) { |
|
|
@ -29,6 +74,7 @@ export default function transform ( source, id, plugins ) { |
|
|
|
map: null |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
// `result.map` can only be a string if `result` isn't
|
|
|
|
else if ( typeof result.map === 'string' ) { |
|
|
|
result.map = JSON.parse( result.map ); |
|
|
@ -42,23 +88,14 @@ export default function transform ( source, id, plugins ) { |
|
|
|
ast = result.ast; |
|
|
|
|
|
|
|
return result.code; |
|
|
|
}); |
|
|
|
}).catch( err => { |
|
|
|
// TODO this all seems a bit hacky
|
|
|
|
if ( errored ) throw err; |
|
|
|
errored = true; |
|
|
|
|
|
|
|
}) |
|
|
|
.catch( err => { |
|
|
|
err.plugin = plugin.name; |
|
|
|
throw err; |
|
|
|
err.id = id; |
|
|
|
error( err ); |
|
|
|
}); |
|
|
|
}, Promise.resolve( source.code ) ) |
|
|
|
.catch( err => { |
|
|
|
error({ |
|
|
|
code: 'BAD_TRANSFORMER', |
|
|
|
message: `Error transforming ${relativeId( id )}${err.plugin ? ` with '${err.plugin}' plugin` : ''}: ${err.message}`, |
|
|
|
plugin: err.plugin, |
|
|
|
id |
|
|
|
}); |
|
|
|
}) |
|
|
|
.then( code => ({ code, originalCode, originalSourceMap, ast, sourceMapChain }) ); |
|
|
|
}); |
|
|
|
|
|
|
|
return promise.then( code => ({ code, originalCode, originalSourceMap, ast, sourceMapChain }) ); |
|
|
|
} |
|
|
|