From aba15f2e533462a7903a8bc7ed4205f4d28fb0b9 Mon Sep 17 00:00:00 2001 From: Jonas Amundsen Date: Thu, 14 Nov 2024 11:43:56 +0100 Subject: [PATCH] Cache instances of SourceMapConsumer Creating these was apparently a little expensive. This fixes #1256 [1]. [1] https://github.com/badeball/cypress-cucumber-preprocessor/issues/1256 --- CHANGELOG.md | 2 ++ lib/helpers/source-map.ts | 48 ++++++++++++++++++++++++--------------- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index afd299a7..ac2064ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ All notable changes to this project will be documented in this file. - Correctly represent consecutive BeforeAll & AfterAll hooks in the command log, relates to [#1250](https://github.com/badeball/cypress-cucumber-preprocessor/issues/1250). +- Cache instances of SourceMapConsumer, fixes [#1256](https://github.com/badeball/cypress-cucumber-preprocessor/issues/1256). + ## v21.0.2 - Cache requested source maps, fixes [#1245](https://github.com/badeball/cypress-cucumber-preprocessor/discussions/1245). diff --git a/lib/helpers/source-map.ts b/lib/helpers/source-map.ts index b5f8853e..2e06b29b 100644 --- a/lib/helpers/source-map.ts +++ b/lib/helpers/source-map.ts @@ -21,7 +21,7 @@ function sourceMapWarn(message: string) { isSourceMapWarned = true; } -const cache = new Map(); +const cache = new Map(); /** * Taken from https://github.com/evanw/node-source-map-support/blob/v0.5.21/source-map-support.js#L148-L177. @@ -63,11 +63,36 @@ export function retrieveSourceMapURL(source: string) { return lastMatch[1]; } -export function cachedRetrieveSourceMapURL(source: string): string | undefined { +export function createSourceMapConsumer( + source: string, +): SourceMapConsumer | undefined { + const sourceMappingURL = retrieveSourceMapURL(source); + + if (!sourceMappingURL) { + return; + } + + const rawSourceMap = JSON.parse( + new TextDecoder().decode( + toByteArray(sourceMappingURL.slice(sourceMappingURL.indexOf(",") + 1)), + ), + ); + + // Why? Because of Vite. Vite fails building the source-map module properly and this errors with "x is not a constructor". + if (typeof SourceMapConsumer !== "function") { + return; + } + + return new SourceMapConsumer(rawSourceMap); +} + +export function cachedCreateSourceMapConsumer( + source: string, +): SourceMapConsumer | undefined { if (cache.has(source)) { return cache.get(source); } else { - const result = retrieveSourceMapURL(source); + const result = createSourceMapConsumer(source); cache.set(source, result); return result; } @@ -80,25 +105,12 @@ export function maybeRetrievePositionFromSourceMap(): Position | undefined { return; } - const sourceMappingURL = cachedRetrieveSourceMapURL(stack[0].fileName); + const sourceMap = cachedCreateSourceMapConsumer(stack[0].fileName); - if (!sourceMappingURL) { + if (!sourceMap) { return; } - const rawSourceMap = JSON.parse( - new TextDecoder().decode( - toByteArray(sourceMappingURL.slice(sourceMappingURL.indexOf(",") + 1)), - ), - ); - - // Why? Because of Vite. Vite fails building the source-map module properly and this errors with "x is not a constructor". - if (typeof SourceMapConsumer !== "function") { - return; - } - - const sourceMap = new SourceMapConsumer(rawSourceMap); - const relevantFrame = stack[3]; const position = sourceMap.originalPositionFor({