From 207021e6411a81e8a25d3f9409fcbf7bd45a5585 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nenad=20Vi=C4=87enti=C4=87?= Date: Wed, 6 Aug 2025 20:08:13 +0200 Subject: [PATCH 1/2] fix: `bundled-source.js` - transformed source map is saved to cache. --- lib/build/amodro-trace/read/es.js | 2 +- lib/build/bundled-source.js | 11 +++- spec/lib/build/bundled-source.spec.js | 95 +++++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 4 deletions(-) diff --git a/lib/build/amodro-trace/read/es.js b/lib/build/amodro-trace/read/es.js index f13e49a59..b59d8f5ed 100644 --- a/lib/build/amodro-trace/read/es.js +++ b/lib/build/amodro-trace/read/es.js @@ -5,7 +5,7 @@ const transformSync = require('@babel/core').transformSync; * @param {string} fileName * @param {string} fileContents * @param {{} | boolean} inputSourceMap - * @returns {{ code: string, map: string, ast: any }} + * @returns {babel.BabelFileResult} */ module.exports = function es(fileName, fileContents, inputSourceMap) { return transformSync(fileContents, { diff --git a/lib/build/bundled-source.js b/lib/build/bundled-source.js index 32cbdaafe..b463eb7f2 100644 --- a/lib/build/bundled-source.js +++ b/lib/build/bundled-source.js @@ -14,11 +14,14 @@ exports.BundledSource = class { this.includedIn = null; this.includedBy = null; this._contents = null; + this._transformedSourceMap = null; this.requiresTransform = true; } get sourceMap() { - return this.file.sourceMap; + return this._transformedSourceMap === null + ? this.file.sourceMap + : this._transformedSourceMap; } get path() { @@ -215,6 +218,7 @@ exports.BundledSource = class { if (cache) { this.contents = cache.contents; + this._transformedSourceMap = cache.transformedSourceMap || null; deps = cache.deps; } else { let contents; @@ -239,7 +243,7 @@ exports.BundledSource = class { contents = result.code; if (result.map) { - this.file.sourceMap = result.map; // save updated source map + this._transformedSourceMap = result.map; } } catch (e) { logger.error('Could not convert to AMD module, skipping ' + modulePath); @@ -279,7 +283,8 @@ exports.BundledSource = class { if (useCache && hash) { Utils.setCache(hash, { deps: deps, - contents: this.contents + contents: this.contents, + transformedSourceMap: this._transformedSourceMap }); } } diff --git a/spec/lib/build/bundled-source.spec.js b/spec/lib/build/bundled-source.spec.js index efc98835b..ca8be7204 100644 --- a/spec/lib/build/bundled-source.spec.js +++ b/spec/lib/build/bundled-source.spec.js @@ -881,5 +881,100 @@ module.exports = require('./bar.js'); expect(Utils.getCache).toHaveBeenCalled(); expect(Utils.setCache).not.toHaveBeenCalled(); }); + + it('transform saves transformed source map to cache', () => { + let file = { + path: path.resolve(cwd, 'node_modules/foo/bar/lo.js'), + contents: "export {default as t} from './t.js';", + sourceMap: {"version":3,"file":"lo.js","sourceRoot":"","sources":["lo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,IAAI,CAAC,EAAC,MAAM,QAAQ,CAAA"} + }; + + Utils.getCache = jasmine.createSpy('getCache').and.returnValue(undefined); + Utils.setCache = jasmine.createSpy('setCache'); + + let bs = new BundledSource(bundler, file); + bs._getProjectRoot = () => 'src'; + bs.includedBy = { + includedBy: { + description: { + name: 'foo', + mainId: 'foo/index', + loaderConfig: { + name: 'foo', + path: '../node_modules/foo', + main: 'index' + }, + browserReplacement: () => undefined + } + } + }; + bs._getLoaderPlugins = () => []; + bs._getLoaderConfig = () => ({paths: {}}); + bs._getUseCache = () => true; + + let deps = bs.transform(); + let contents = "define('foo/bar/lo',[\"exports\", './t'], function (_exports, _t) { \"use strict\"; _exports.__esModule = true; _exports.t = void 0; _t = _interopRequireDefault(_t); _exports.t = _t.default; function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }});"; + let transformedSourceMap = {version:3,file:undefined,names:['_t', '_interopRequireDefault', '_exports', 't', 'default', 'e', '__esModule'],sourceRoot:undefined,sources:['lo.ts'],sourcesContent:[undefined],mappings:";;;;;EAAAA,EAAA,GAAAC,sBAAA,CAAAD,EAAA;EAA2BE,QAAA,CAAAC,CAAA,GAAAH,EAAA,CAAAI,OAAA;EAAA,SAAAH,uBAAAI,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAD,OAAA,EAAAC,CAAA;AAAA",ignoreList:[]}; + + expect(deps).toEqual(['foo/bar/t']); + expect(bs.requiresTransform).toBe(false); + expect(bs.contents.replace(/\r|\n/g, '')) + .toBe(contents); + expect(bs.sourceMap).toEqual(transformedSourceMap) + + expect(Utils.getCache).toHaveBeenCalled(); + expect(Utils.setCache).toHaveBeenCalled(); + expect(Utils.setCache.calls.argsFor(0)[1].deps).toEqual(['./t']); + expect(Utils.setCache.calls.argsFor(0)[1].contents.replace(/\r|\n/g, '')).toBe(contents); + expect(Utils.setCache.calls.argsFor(0)[1].transformedSourceMap).toEqual(transformedSourceMap); + }); + + it('transform uses cache for transformed source map', () => { + let file = { + path: path.resolve(cwd, 'node_modules/foo/bar/lo.js'), + contents: "export {default as t} from './t.js';", + sourceMap: {"version":3,"file":"lo.js","sourceRoot":"","sources":["lo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,IAAI,CAAC,EAAC,MAAM,QAAQ,CAAA"} + }; + + let contents = "define('foo/bar/lo',[\"exports\", './t'], function (_exports, _t) { \"use strict\"; _exports.__esModule = true; _exports.t = void 0; _t = _interopRequireDefault(_t); _exports.t = _t.default; function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }});"; + let transformedSourceMap = {version:3,file:undefined,names:['_t', '_interopRequireDefault', '_exports', 't', 'default', 'e', '__esModule'],sourceRoot:undefined,sources:['lo.ts'],sourcesContent:[undefined],mappings:";;;;;EAAAA,EAAA,GAAAC,sBAAA,CAAAD,EAAA;EAA2BE,QAAA,CAAAC,CAAA,GAAAH,EAAA,CAAAI,OAAA;EAAA,SAAAH,uBAAAI,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAD,OAAA,EAAAC,CAAA;AAAA",ignoreList:[]}; + + Utils.getCache = jasmine.createSpy('getCache').and.returnValue({ + deps: ['./t'], + contents, + transformedSourceMap + }); + Utils.setCache = jasmine.createSpy('setCache'); + + let bs = new BundledSource(bundler, file); + bs._getProjectRoot = () => 'src'; + bs.includedBy = { + includedBy: { + description: { + name: 'foo', + mainId: 'foo/index', + loaderConfig: { + name: 'foo', + path: '../node_modules/foo', + main: 'index' + }, + browserReplacement: () => undefined + } + } + }; + bs._getLoaderPlugins = () => []; + bs._getLoaderConfig = () => ({paths: {}}); + bs._getUseCache = () => true; + + let deps = bs.transform(); + expect(deps).toEqual(['foo/bar/t']); + expect(bs.requiresTransform).toBe(false); + expect(bs.contents.replace(/\r|\n/g, '')) + .toBe(contents); + expect(bs.sourceMap).toEqual(transformedSourceMap); + + expect(Utils.getCache).toHaveBeenCalled(); + expect(Utils.setCache).not.toHaveBeenCalled(); + }); }); }); From b0ace4803d0a28d2435ecf273881d4b43928689f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nenad=20Vi=C4=87enti=C4=87?= Date: Thu, 7 Aug 2025 09:48:04 +0200 Subject: [PATCH 2/2] Adopt suggested change - simplify getter + guard from serializing/caching `null`. --- lib/build/bundled-source.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/lib/build/bundled-source.js b/lib/build/bundled-source.js index b463eb7f2..16da4baf4 100644 --- a/lib/build/bundled-source.js +++ b/lib/build/bundled-source.js @@ -14,14 +14,12 @@ exports.BundledSource = class { this.includedIn = null; this.includedBy = null; this._contents = null; - this._transformedSourceMap = null; + this._transformedSourceMap = undefined; this.requiresTransform = true; } get sourceMap() { - return this._transformedSourceMap === null - ? this.file.sourceMap - : this._transformedSourceMap; + return this._transformedSourceMap || this.file.sourceMap; } get path() { @@ -218,7 +216,7 @@ exports.BundledSource = class { if (cache) { this.contents = cache.contents; - this._transformedSourceMap = cache.transformedSourceMap || null; + this._transformedSourceMap = cache.transformedSourceMap; deps = cache.deps; } else { let contents; @@ -284,7 +282,7 @@ exports.BundledSource = class { Utils.setCache(hash, { deps: deps, contents: this.contents, - transformedSourceMap: this._transformedSourceMap + transformedSourceMap: !this._transformedSourceMap ? undefined : this._transformedSourceMap // avoid serializing `null` }); } }