diff --git a/src/Module.js b/src/Module.js index 205b38b..fc3ebd1 100644 --- a/src/Module.js +++ b/src/Module.js @@ -1,6 +1,6 @@ import { parse } from 'acorn/src/index.js'; import MagicString from 'magic-string'; -import { assign, blank, keys } from './utils/object.js'; +import { assign, blank, deepClone, keys } from './utils/object.js'; import { basename, extname } from './utils/path.js'; import getLocation from './utils/getLocation.js'; import makeLegalIdentifier from './utils/makeLegalIdentifier.js'; @@ -35,6 +35,7 @@ export default class Module { this.comments = []; this.ast = ast || tryParse( code, this.comments, bundle.acornOptions, id ); // TODO what happens to comments if AST is provided? + this.astClone = deepClone( this.ast ); this.bundle = bundle; this.id = id; @@ -316,8 +317,7 @@ export default class Module { id: this.id, code: this.code, originalCode: this.originalCode, - // TODO reinstate AST caching (rewrite broke it, because AST is enhanced) - // ast: this.ast, + ast: this.astClone, sourceMapChain: this.sourceMapChain, resolvedIds: this.resolvedIds }; diff --git a/src/utils/object.js b/src/utils/object.js index 4234de3..947c8e1 100644 --- a/src/utils/object.js +++ b/src/utils/object.js @@ -17,3 +17,24 @@ export function assign ( target, ...sources ) { return target; } + +const isArray = Array.isArray; + +// used for cloning ASTs. Not for use with cyclical structures! +export function deepClone ( obj ) { + if ( !obj ) return obj; + if ( typeof obj !== 'object' ) return obj; + + if ( isArray( obj ) ) { + const clone = new Array( obj.length ); + for ( let i = 0; i < obj.length; i += 1 ) clone[i] = deepClone( obj[i] ); + return clone; + } + + const clone = {}; + for ( const key in obj ) { + clone[ key ] = deepClone( obj[ key ] ); + } + + return clone; +} diff --git a/test/test.js b/test/test.js index 615742f..9697e6e 100644 --- a/test/test.js +++ b/test/test.js @@ -6,6 +6,7 @@ const sander = require( 'sander' ); const assert = require( 'assert' ); const { exec } = require( 'child_process' ); const buble = require( 'buble' ); +const acorn = require( 'acorn' ); const rollup = require( '../dist/rollup' ); const FUNCTION = path.resolve( __dirname, 'function' ); @@ -587,6 +588,21 @@ describe( 'rollup', function () { assert.equal( executeBundle( bundle ), 21 ); }); }); + + it( 'keeps ASTs between runs', () => { + return rollup.rollup({ + entry: 'entry', + plugins: [ plugin ] + }).then( bundle => { + const asts = {}; + bundle.modules.forEach( module => { + asts[ module.id ] = module.ast; + }); + + assert.deepEqual( asts.entry, acorn.parse( modules.entry, { sourceType: 'module' }) ); + assert.deepEqual( asts.foo, acorn.parse( modules.foo, { sourceType: 'module' }) ); + }); + }); }); describe( 'hooks', () => {