Commit 940ca4e1 authored by David Sveningsson's avatar David Sveningsson
Browse files

fix(meta): memory leak when loading meta table

refs #106
parent 455168fb
Pipeline #279119632 passed with stages
in 10 minutes and 56 seconds
......@@ -9,6 +9,7 @@ import { MetaCopyableProperty, MetaDataTable } from "../meta/element";
import { Plugin } from "../plugin";
import schema from "../schema/config.json";
import { TransformContext, Transformer, TRANSFORMER_API } from "../transform";
import { requireUncached } from "../utils";
import { ConfigData, RuleOptions, TransformMap } from "./config-data";
import defaultConfig from "./default";
import { ConfigError } from "./error";
......@@ -64,12 +65,8 @@ function mergeInternal(base: ConfigData, rhs: ConfigData): ConfigData {
function loadFromFile(filename: string): ConfigData {
let json;
try {
/* remove cached copy so we always load a fresh copy, important for editors
* which keep a long-running instance of [[HtmlValidate]] around. */
delete require.cache[require.resolve(filename)];
/* load using require as it can process both js and json */
json = require(filename); // eslint-disable-line import/no-dynamic-require
json = requireUncached(filename);
} catch (err) {
throw new ConfigError(`Failed to read configuration from "${filename}"`, err);
}
......
......@@ -5,6 +5,7 @@ import jsonMergePatch from "json-merge-patch";
import { HtmlElement } from "../dom";
import { SchemaValidationError, UserError } from "../error";
import { SchemaValidationPatch } from "../plugin";
import { requireUncached } from "../utils";
import schema from "../schema/elements.json";
import {
ElementTable,
......@@ -139,13 +140,8 @@ export class MetaTable {
*/
public loadFromFile(filename: string): void {
try {
/* remove cached copy so we always load a fresh copy, important for
* editors which keep a long-running instance of [[HtmlValidate]]
* around. */
delete require.cache[require.resolve(filename)];
/* load using require as it can process both js and json */
const data = require(filename); // eslint-disable-line import/no-dynamic-require
const data = requireUncached(filename);
this.loadFromObject(data, filename);
} catch (err) {
if (err instanceof SchemaValidationError) {
......
export { requireUncached } from "./require-uncached";
export { ruleExists } from "./rule-exists";
/**
* Similar to `require(..)` but removes the cached copy first.
*/
export function requireUncached(moduleId: string): any {
const filename = require.resolve(moduleId);
/* remove references from the parent module to prevent memory leak */
const m = require.cache[filename];
if (m && m.parent) {
const { parent } = m;
for (let i = parent.children.length - 1; i >= 0; i--) {
if (parent.children[i].id === filename) {
parent.children.splice(i, 1);
}
}
}
/* remove old module from cache */
delete require.cache[filename];
// eslint-disable-next-line import/no-dynamic-require
return require(filename);
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment