Skip to content

Commit

Permalink
fix(babel): several massive memory leaks
Browse files Browse the repository at this point in the history
  • Loading branch information
Anber committed Sep 1, 2023
1 parent df96d44 commit fa9ad89
Show file tree
Hide file tree
Showing 31 changed files with 428 additions and 308 deletions.
8 changes: 2 additions & 6 deletions packages/babel/src/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,14 @@ function hashContent(content: string) {
}

interface ICaches {
contentHashes: Map<string, string>;
entrypoints: Map<string, Entrypoint | IEvaluatedEntrypoint>;
}

type MapValue<T> = T extends Map<string, infer V> ? V : never;

const cacheLogger = linariaLogger.extend('cache');

const cacheNames = ['entrypoints', 'contentHashes'] as const;
const cacheNames = ['entrypoints'] as const;
type CacheNames = (typeof cacheNames)[number];

const loggers = cacheNames.reduce(
Expand All @@ -30,10 +29,7 @@ const loggers = cacheNames.reduce(
);

export class TransformCacheCollection {
protected readonly entrypoints: Map<
string,
Entrypoint | IEvaluatedEntrypoint
>;
public readonly entrypoints: Map<string, Entrypoint | IEvaluatedEntrypoint>;

private contentHashes = new Map<string, string>();

Expand Down
3 changes: 2 additions & 1 deletion packages/babel/src/evaluators/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ export default function evaluate(
const m = new Module(entrypoint, cache);

m.evaluate();
m.dispose();

return {
value: m.exports,
value: entrypoint.exports,
dependencies: m.dependencies,
};
}
8 changes: 5 additions & 3 deletions packages/babel/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ import type { PluginOptions } from './types';
export { slugify } from '@linaria/utils';

export { default as preeval } from './plugins/preeval';
export { default as withLinariaMetadata } from './utils/withLinariaMetadata';
export {
default as withLinariaMetadata,
getLinariaMetadata,
} from './utils/withLinariaMetadata';
export { default as Module, DefaultModuleImplementation } from './module';
export { default as transform } from './transform';
export * from './types';
Expand All @@ -30,11 +33,10 @@ export {
syncResolveImports,
} from './transform/generators/resolveImports';
export { default as loadLinariaOptions } from './transform/helpers/loadLinariaOptions';
export { StackOfMaps } from './transform/helpers/StackOfMaps';
export { withDefaultServices } from './transform/helpers/withDefaultServices';
export type { Services } from './transform/types';
export { default as isNode } from './utils/isNode';
export { default as getTagProcessor } from './utils/getTagProcessor';
export { getTagProcessor } from './utils/getTagProcessor';
export { default as getVisitorKeys } from './utils/getVisitorKeys';
export type { VisitorKeys } from './utils/getVisitorKeys';
export { default as peek } from './utils/peek';
Expand Down
38 changes: 31 additions & 7 deletions packages/babel/src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,12 @@ function resolve(
return resolved;
}

function assertDisposed(
entrypoint: Entrypoint | null
): asserts entrypoint is Entrypoint {
invariant(entrypoint, 'Module is disposed');
}

class Module {
public readonly callstack: string[] = [];

Expand Down Expand Up @@ -181,6 +187,7 @@ class Module {

const m = new Module(entrypoint, this.cache, this);
m.evaluate();
m.dispose();

return entrypoint.exports;
},
Expand All @@ -192,12 +199,15 @@ class Module {

public resolve = resolve.bind(this);

protected entrypoint: Entrypoint | null;

constructor(
protected entrypoint: Entrypoint,
entrypoint: Entrypoint,
private cache = new TransformCacheCollection(),
parentModule?: Module,
private moduleImpl: HiddenModuleMembers = DefaultModuleImplementation
) {
this.entrypoint = entrypoint;
this.idx = entrypoint.idx;
this.id = entrypoint.name;
this.filename = entrypoint.name;
Expand All @@ -207,9 +217,9 @@ class Module {
this.ignored = entrypoint.ignored ?? this.parentIsIgnored;

if (parentModule) {
this.callstack = [...parentModule.callstack, parentModule.filename];
this.callstack = [entrypoint.name, ...parentModule.callstack];
} else {
this.callstack = [];
this.callstack = [entrypoint.name];
}

this.extensions = entrypoint.pluginOptions.extensions;
Expand All @@ -218,19 +228,29 @@ class Module {
}

public get exports() {
assertDisposed(this.entrypoint);
return this.entrypoint.exports;
}

public set exports(value) {
assertDisposed(this.entrypoint);

this.entrypoint.exports = value;

this.debug(
'the whole exports was overridden with %O',
this.entrypoint.exportsValues
);
this.debug('the whole exports was overridden with %O', value);
}

dispose(): void {
assertDisposed(this.entrypoint);

this.debug('dispose');

this.entrypoint = null;
}

evaluate(): void {
assertDisposed(this.entrypoint);

let { entrypoint } = this;
// Evaluate could be called before the entrypoint was superseded.
// In this case, we need to find the latest entrypoint.
Expand Down Expand Up @@ -314,6 +334,8 @@ class Module {
only: string[],
log: Debugger
): Entrypoint | IEvaluatedEntrypoint | null {
assertDisposed(this.entrypoint);

const extension = path.extname(filename);
if (extension !== '.json' && !this.extensions.includes(extension)) {
return null;
Expand Down Expand Up @@ -421,6 +443,8 @@ class Module {
}

resolveDependency = (id: string): IEntrypointDependency => {
assertDisposed(this.entrypoint);

const cached = this.entrypoint.getDependency(id);
invariant(!(cached instanceof Promise), 'Dependency is not resolved yet');

Expand Down
5 changes: 4 additions & 1 deletion packages/babel/src/plugins/collector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import type { Identifier } from '@babel/types';

import { debug } from '@linaria/logger';
import type { StrictOptions, LinariaMetadata } from '@linaria/utils';
import { removeWithRelated } from '@linaria/utils';
import { invalidateTraversalCache, removeWithRelated } from '@linaria/utils';

import type { Core } from '../babel';
import type { IPluginState, ValueCache } from '../types';
Expand Down Expand Up @@ -86,5 +86,8 @@ export default function collectorPlugin(
debug('collect:end', file.opts.filename);
},
visitor: {},
post(file: BabelFile) {
invalidateTraversalCache(file.path);
},
};
}
3 changes: 3 additions & 0 deletions packages/babel/src/plugins/preeval.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
addIdentifierToLinariaPreval,
removeDangerousCode,
isFeatureEnabled,
invalidateTraversalCache,
} from '@linaria/utils';

import type { Core } from '../babel';
Expand Down Expand Up @@ -88,6 +89,8 @@ export default function preeval(

const log = createCustomDebug('preeval', getFileIdx(file.opts.filename!));

invalidateTraversalCache(file.path);

if (this.processors.length === 0) {
log('end', "We didn't find any Linaria template literals");

Expand Down
Loading

0 comments on commit fa9ad89

Please sign in to comment.