From 651c09c18cf85e01ecc16d14a96fd498bf6346c7 Mon Sep 17 00:00:00 2001 From: Chengzhong Wu Date: Sun, 22 Jan 2023 19:25:19 +0800 Subject: [PATCH] lib: cache parsed source maps to reduce memory footprint This also improves performance to map the stack trace when the `Error.stack` is accessed. PR-URL: https://github.com/nodejs/node/pull/46225 Reviewed-By: Yagiz Nizipli Reviewed-By: Antoine du Hamel Reviewed-By: James M Snell Reviewed-By: Ben Noordhuis --- lib/internal/source_map/source_map_cache.js | 26 ++++++++++++++------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/lib/internal/source_map/source_map_cache.js b/lib/internal/source_map/source_map_cache.js index f1601a5d4ecdae..ea8834d6a930b8 100644 --- a/lib/internal/source_map/source_map_cache.js +++ b/lib/internal/source_map/source_map_cache.js @@ -14,6 +14,9 @@ const { function ObjectGetValueSafe(obj, key) { const desc = ObjectGetOwnPropertyDescriptor(obj, key); + if (desc === undefined) { + return undefined; + } return ObjectPrototypeHasOwnProperty(desc, 'value') ? desc.value : undefined; } @@ -141,6 +144,7 @@ function maybeCacheSourceMap(filename, content, cjsModuleInstance, isGeneratedSo const url = data ? null : sourceMapURL; if (cjsModuleInstance) { getCjsSourceMapCache().set(cjsModuleInstance, { + __proto__: null, filename, lineLengths: lineLengths(content), data, @@ -149,6 +153,7 @@ function maybeCacheSourceMap(filename, content, cjsModuleInstance, isGeneratedSo }); } else if (isGeneratedSource) { const entry = { + __proto__: null, lineLengths: lineLengths(content), data, url, @@ -162,6 +167,7 @@ function maybeCacheSourceMap(filename, content, cjsModuleInstance, isGeneratedSo // If there is no cjsModuleInstance and is not generated source assume we are in a // "modules/esm" context. const entry = { + __proto__: null, lineLengths: lineLengths(content), data, url, @@ -296,6 +302,7 @@ function sourceMapCacheToObject() { function appendCJSCache(obj) { for (const value of getCjsSourceMapCache()) { obj[ObjectGetValueSafe(value, 'filename')] = { + __proto__: null, lineLengths: ObjectGetValueSafe(value, 'lineLengths'), data: ObjectGetValueSafe(value, 'data'), url: ObjectGetValueSafe(value, 'url') @@ -310,22 +317,25 @@ function findSourceMap(sourceURL) { if (!SourceMap) { SourceMap = require('internal/source_map/source_map').SourceMap; } - let sourceMap = esmSourceMapCache.get(sourceURL) ?? generatedSourceMapCache.get(sourceURL); - if (sourceMap === undefined) { + let entry = esmSourceMapCache.get(sourceURL) ?? generatedSourceMapCache.get(sourceURL); + if (entry === undefined) { for (const value of getCjsSourceMapCache()) { const filename = ObjectGetValueSafe(value, 'filename'); const cachedSourceURL = ObjectGetValueSafe(value, 'sourceURL'); if (sourceURL === filename || sourceURL === cachedSourceURL) { - sourceMap = { - data: ObjectGetValueSafe(value, 'data') - }; + entry = value; } } } - if (sourceMap && sourceMap.data) { - return new SourceMap(sourceMap.data); + if (entry === undefined) { + return undefined; + } + let sourceMap = ObjectGetValueSafe(entry, 'sourceMap'); + if (sourceMap === undefined) { + sourceMap = new SourceMap(ObjectGetValueSafe(entry, 'data')); + entry.sourceMap = sourceMap; } - return undefined; + return sourceMap; } module.exports = {