module: fix stat cache
The current caching logic broke by [0] because it used destructuring on the module arguments. Since the exported property is a primitive counting it up or down would not have any effect anymore in the module that required that property. The original implementation would cache all stat calls caused during bootstrap. Afterwards it would clear the cache and lazy require calls during runtime would create a new cascading cache for the then loaded modules and clear the cache again. This behavior is now restored. This is difficult to test without exposing a lot of information and therfore the existing tests have been removed (as they could not detect the issue). With the broken implementation it caused each module compilation to reset the cache and therefore minimizing the effect drastically. [0] https://github.com/nodejs/node/pull/19177 PR-URL: https://github.com/nodejs/node/pull/26266 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
3fce5cf439
commit
410eb97bce
@ -11,12 +11,7 @@ function makeRequireFunction(mod) {
|
|||||||
const Module = mod.constructor;
|
const Module = mod.constructor;
|
||||||
|
|
||||||
function require(path) {
|
function require(path) {
|
||||||
try {
|
return mod.require(path);
|
||||||
exports.requireDepth += 1;
|
|
||||||
return mod.require(path);
|
|
||||||
} finally {
|
|
||||||
exports.requireDepth -= 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function resolve(request, options) {
|
function resolve(request, options) {
|
||||||
@ -139,7 +134,6 @@ module.exports = exports = {
|
|||||||
builtinLibs,
|
builtinLibs,
|
||||||
makeRequireFunction,
|
makeRequireFunction,
|
||||||
normalizeReferrerURL,
|
normalizeReferrerURL,
|
||||||
requireDepth: 0,
|
|
||||||
stripBOM,
|
stripBOM,
|
||||||
stripShebang
|
stripShebang
|
||||||
};
|
};
|
||||||
|
@ -37,7 +37,6 @@ const { safeGetenv } = internalBinding('credentials');
|
|||||||
const {
|
const {
|
||||||
makeRequireFunction,
|
makeRequireFunction,
|
||||||
normalizeReferrerURL,
|
normalizeReferrerURL,
|
||||||
requireDepth,
|
|
||||||
stripBOM,
|
stripBOM,
|
||||||
stripShebang
|
stripShebang
|
||||||
} = require('internal/modules/cjs/helpers');
|
} = require('internal/modules/cjs/helpers');
|
||||||
@ -85,18 +84,17 @@ const {
|
|||||||
|
|
||||||
const isWindows = process.platform === 'win32';
|
const isWindows = process.platform === 'win32';
|
||||||
|
|
||||||
|
let requireDepth = 0;
|
||||||
|
let statCache = new Map();
|
||||||
function stat(filename) {
|
function stat(filename) {
|
||||||
filename = path.toNamespacedPath(filename);
|
filename = path.toNamespacedPath(filename);
|
||||||
const cache = stat.cache;
|
if (statCache === null) statCache = new Map();
|
||||||
if (cache !== null) {
|
let result = statCache.get(filename);
|
||||||
const result = cache.get(filename);
|
if (result !== undefined) return result;
|
||||||
if (result !== undefined) return result;
|
result = internalModuleStat(filename);
|
||||||
}
|
statCache.set(filename, result);
|
||||||
const result = internalModuleStat(filename);
|
|
||||||
if (cache !== null) cache.set(filename, result);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
stat.cache = null;
|
|
||||||
|
|
||||||
function updateChildren(parent, child, scan) {
|
function updateChildren(parent, child, scan) {
|
||||||
var children = parent && parent.children;
|
var children = parent && parent.children;
|
||||||
@ -710,7 +708,12 @@ Module.prototype.require = function(id) {
|
|||||||
throw new ERR_INVALID_ARG_VALUE('id', id,
|
throw new ERR_INVALID_ARG_VALUE('id', id,
|
||||||
'must be a non-empty string');
|
'must be a non-empty string');
|
||||||
}
|
}
|
||||||
return Module._load(id, this, /* isMain */ false);
|
requireDepth++;
|
||||||
|
try {
|
||||||
|
return Module._load(id, this, /* isMain */ false);
|
||||||
|
} finally {
|
||||||
|
requireDepth--;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -793,8 +796,6 @@ Module.prototype._compile = function(content, filename) {
|
|||||||
}
|
}
|
||||||
var dirname = path.dirname(filename);
|
var dirname = path.dirname(filename);
|
||||||
var require = makeRequireFunction(this);
|
var require = makeRequireFunction(this);
|
||||||
var depth = requireDepth;
|
|
||||||
if (depth === 0) stat.cache = new Map();
|
|
||||||
var result;
|
var result;
|
||||||
var exports = this.exports;
|
var exports = this.exports;
|
||||||
var thisValue = exports;
|
var thisValue = exports;
|
||||||
@ -806,7 +807,7 @@ Module.prototype._compile = function(content, filename) {
|
|||||||
result = compiledWrapper.call(thisValue, exports, require, module,
|
result = compiledWrapper.call(thisValue, exports, require, module,
|
||||||
filename, dirname);
|
filename, dirname);
|
||||||
}
|
}
|
||||||
if (depth === 0) stat.cache = null;
|
if (requireDepth === 0) statCache = null;
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
11
test/fixtures/module-require-depth/one.js
vendored
11
test/fixtures/module-require-depth/one.js
vendored
@ -1,11 +0,0 @@
|
|||||||
// Flags: --expose_internals
|
|
||||||
'use strict';
|
|
||||||
const assert = require('assert');
|
|
||||||
const {
|
|
||||||
requireDepth
|
|
||||||
} = require('internal/modules/cjs/helpers');
|
|
||||||
|
|
||||||
exports.requireDepth = requireDepth;
|
|
||||||
assert.strictEqual(requireDepth, 1);
|
|
||||||
assert.deepStrictEqual(require('./two'), { requireDepth: 2 });
|
|
||||||
assert.strictEqual(requireDepth, 1);
|
|
11
test/fixtures/module-require-depth/two.js
vendored
11
test/fixtures/module-require-depth/two.js
vendored
@ -1,11 +0,0 @@
|
|||||||
// Flags: --expose_internals
|
|
||||||
'use strict';
|
|
||||||
const assert = require('assert');
|
|
||||||
const {
|
|
||||||
requireDepth
|
|
||||||
} = require('internal/modules/cjs/helpers');
|
|
||||||
|
|
||||||
exports.requireDepth = requireDepth;
|
|
||||||
assert.strictEqual(requireDepth, 2);
|
|
||||||
assert.deepStrictEqual(require('./one'), { requireDepth: 1 });
|
|
||||||
assert.strictEqual(requireDepth, 2);
|
|
@ -1,16 +0,0 @@
|
|||||||
// Flags: --expose_internals
|
|
||||||
'use strict';
|
|
||||||
require('../common');
|
|
||||||
const fixtures = require('../common/fixtures');
|
|
||||||
const assert = require('assert');
|
|
||||||
const {
|
|
||||||
requireDepth
|
|
||||||
} = require('internal/modules/cjs/helpers');
|
|
||||||
|
|
||||||
// Module one loads two too so the expected depth for two is, well, two.
|
|
||||||
assert.strictEqual(requireDepth, 0);
|
|
||||||
const one = require(fixtures.path('module-require-depth', 'one'));
|
|
||||||
const two = require(fixtures.path('module-require-depth', 'two'));
|
|
||||||
assert.deepStrictEqual(one, { requireDepth: 1 });
|
|
||||||
assert.deepStrictEqual(two, { requireDepth: 2 });
|
|
||||||
assert.strictEqual(requireDepth, 0);
|
|
Loading…
x
Reference in New Issue
Block a user