Skip to content

Commit e0dcfbd

Browse files
committed
Merge branch 'fix-perf' into release-2.10.1 (fixes #1058)
2 parents 83c85fc + 774ea8d commit e0dcfbd

2 files changed

Lines changed: 50 additions & 27 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel
1111
- Fixer for [`first`] ([#1046], thanks [@fengkfengk])
1212
- `allow-require` option for [`no-commonjs`] rule ([#880], thanks [@futpib])
1313

14+
### Fixed
15+
- memory/CPU regression where ASTs were held in memory ([#1058], thanks [@klimashkin]/[@lukeapage])
16+
1417
## [2.10.0] - 2018-03-29
1518
### Added
1619
- Autofixer for [`order`] rule ([#711], thanks [@tihonove])
@@ -530,6 +533,7 @@ for info on changes for earlier releases.
530533
[#314]: https://github.com/benmosher/eslint-plugin-import/pull/314
531534
[#912]: https://github.com/benmosher/eslint-plugin-import/pull/912
532535

536+
[#1058]: https://github.com/benmosher/eslint-plugin-import/issues/1058
533537
[#886]: https://github.com/benmosher/eslint-plugin-import/issues/886
534538
[#863]: https://github.com/benmosher/eslint-plugin-import/issues/863
535539
[#842]: https://github.com/benmosher/eslint-plugin-import/issues/842
@@ -702,3 +706,5 @@ for info on changes for earlier releases.
702706
[@danny-andrews]: https://github.com/dany-andrews
703707
[@fengkfengk]: https://github.com/fengkfengk
704708
[@futpib]: https://github.com/futpib
709+
[@klimashkin]: https://github.com/klimashkin
710+
[@lukeapage]: https://github.com/lukeapage

src/ExportMap.js

Lines changed: 44 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -265,20 +265,14 @@ ExportMap.get = function (source, context) {
265265
const path = resolve(source, context)
266266
if (path == null) return null
267267

268-
return ExportMap.for(path, context)
268+
return ExportMap.for(childContext(path, context))
269269
}
270270

271-
ExportMap.for = function (path, context) {
272-
let exportMap
271+
ExportMap.for = function (context) {
272+
const { path } = context
273273

274-
const cacheKey = hashObject({
275-
settings: context.settings,
276-
parserPath: context.parserPath,
277-
parserOptions: context.parserOptions,
278-
path,
279-
}).digest('hex')
280-
281-
exportMap = exportCache.get(cacheKey)
274+
const cacheKey = hashObject(context).digest('hex')
275+
let exportMap = exportCache.get(cacheKey)
282276

283277
// return cached ignore
284278
if (exportMap === null) return null
@@ -307,6 +301,7 @@ ExportMap.for = function (path, context) {
307301
return null
308302
}
309303

304+
log('cache miss', cacheKey, 'for path', path)
310305
exportMap = ExportMap.parse(path, content, context)
311306

312307
// ambiguous modules return null
@@ -355,14 +350,14 @@ ExportMap.parse = function (path, content, context) {
355350

356351
const namespaces = new Map()
357352

358-
function remotePath(node) {
359-
return resolve.relative(node.source.value, path, context.settings)
353+
function remotePath(value) {
354+
return resolve.relative(value, path, context.settings)
360355
}
361356

362-
function resolveImport(node) {
363-
const rp = remotePath(node)
357+
function resolveImport(value) {
358+
const rp = remotePath(value)
364359
if (rp == null) return null
365-
return ExportMap.for(rp, context)
360+
return ExportMap.for(childContext(rp, context))
366361
}
367362

368363
function getNamespace(identifier) {
@@ -385,12 +380,20 @@ ExportMap.parse = function (path, content, context) {
385380
function captureDependency(declaration) {
386381
if (declaration.source == null) return null
387382

388-
const p = remotePath(declaration)
389-
if (p == null || m.imports.has(p)) return p
390-
391-
const getter = () => ExportMap.for(p, context)
392-
m.imports.set(p, { getter, source: declaration.source })
393-
return p
383+
const p = remotePath(declaration.source.value)
384+
if (p == null) return null
385+
const existing = m.imports.get(p)
386+
if (existing != null) return existing.getter
387+
388+
const getter = () => ExportMap.for(childContext(p, context))
389+
m.imports.set(p, {
390+
getter,
391+
source: { // capturing actual node reference holds full AST in memory!
392+
value: declaration.source.value,
393+
loc: declaration.source.loc,
394+
},
395+
})
396+
return getter
394397
}
395398

396399

@@ -406,8 +409,8 @@ ExportMap.parse = function (path, content, context) {
406409
}
407410

408411
if (n.type === 'ExportAllDeclaration') {
409-
const p = captureDependency(n)
410-
if (p) m.dependencies.add(m.imports.get(p).getter)
412+
const getter = captureDependency(n)
413+
if (getter) m.dependencies.add(getter)
411414
return
412415
}
413416

@@ -416,7 +419,7 @@ ExportMap.parse = function (path, content, context) {
416419
captureDependency(n)
417420
let ns
418421
if (n.specifiers.some(s => s.type === 'ImportNamespaceSpecifier' && (ns = s))) {
419-
namespaces.set(ns.local.name, n)
422+
namespaces.set(ns.local.name, n.source.value)
420423
}
421424
return
422425
}
@@ -443,6 +446,7 @@ ExportMap.parse = function (path, content, context) {
443446
}
444447
}
445448

449+
const nsource = n.source && n.source.value
446450
n.specifiers.forEach((s) => {
447451
const exportMeta = {}
448452
let local
@@ -454,7 +458,7 @@ ExportMap.parse = function (path, content, context) {
454458
break
455459
case 'ExportNamespaceSpecifier':
456460
m.namespace.set(s.exported.name, Object.defineProperty(exportMeta, 'namespace', {
457-
get() { return resolveImport(n) },
461+
get() { return resolveImport(nsource) },
458462
}))
459463
return
460464
case 'ExportSpecifier':
@@ -469,7 +473,7 @@ ExportMap.parse = function (path, content, context) {
469473
}
470474

471475
// todo: JSDoc
472-
m.reexports.set(s.exported.name, { local, getImport: () => resolveImport(n) })
476+
m.reexports.set(s.exported.name, { local, getImport: () => resolveImport(nsource) })
473477
})
474478
}
475479
})
@@ -505,3 +509,16 @@ export function recursivePatternCapture(pattern, callback) {
505509
break
506510
}
507511
}
512+
513+
/**
514+
* don't hold full context object in memory, just grab what we need.
515+
*/
516+
function childContext(path, context) {
517+
const { settings, parserOptions, parserPath } = context
518+
return {
519+
settings,
520+
parserOptions,
521+
parserPath,
522+
path,
523+
}
524+
}

0 commit comments

Comments
 (0)