Skip to content

Commit 8acb238

Browse files
committed
Cache requested source maps
This fixes #1245 [1]. [1] #1245
1 parent 1e11dca commit 8acb238

File tree

4 files changed

+58
-1
lines changed

4 files changed

+58
-1
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
## Unreleased
6+
7+
- Cache requested source maps, fixes [#1245](https://github.com/badeball/cypress-cucumber-preprocessor/discussions/1245).
8+
59
## v21.0.1
610

711
- Support config file locations other than project root, fixes [#1243](https://github.com/badeball/cypress-cucumber-preprocessor/discussions/1243).

features/issues/1245.feature

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
Feature: cached source maps
2+
3+
Ideally, I would have liked to test this in a more behavior driven way, like counting the number
4+
of times that the bundler, whichever was configured, was invoked. However, it turns out that
5+
Cypress does in fact cache [1]. Unfortunately, this cache is dead slow and requires higher-order
6+
caching. The only way to verify that Cypress' cache isn't invoked, is by interpreting stderr.
7+
8+
[1] https://github.com/cypress-io/cypress/blob/v13.15.0/packages/server/lib/plugins/preprocessor.js#L94-L98
9+
10+
Scenario:
11+
Given a file named "cypress/e2e/a.feature" with:
12+
"""
13+
Feature: a feature name
14+
Scenario: a scenario name
15+
Given a step
16+
"""
17+
And a file named "cypress/support/step_definitions/steps.ts" with:
18+
"""
19+
import { Given } from "@badeball/cypress-cucumber-preprocessor";
20+
Given("a step", function(this: Mocha.Context) {});
21+
for (let i = 0; i < 10; i++) {
22+
Given(`an unused step (${i + 1})`, function(this: Mocha.Context) {});
23+
};
24+
"""
25+
When I run cypress with environment variables
26+
| name | value |
27+
| DEBUG | cypress:server:preprocessor |
28+
Then it passes
29+
# Why two? Who knows. Cypress requests this file twice and the library once.
30+
And I should see exactly 2 instances of "headless and already processed" in stderr

features/step_definitions/cli_steps.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,3 +249,14 @@ Then(
249249
assert.match(expectLastRun(this).stdout, pendingScenarioExpr(scenarioName));
250250
},
251251
);
252+
253+
Then(
254+
"I should see exactly {int} instance(s) of {string} in stderr",
255+
function (this: ICustomWorld, expectedOccurences: number, output: string) {
256+
const actualyOccurences =
257+
expectLastRun(this).stderr.match(new RegExp(rescape(output), "g"))
258+
?.length ?? 0;
259+
260+
assert.equal(actualyOccurences, expectedOccurences);
261+
},
262+
);

lib/helpers/source-map.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ function sourceMapWarn(message: string) {
2121
isSourceMapWarned = true;
2222
}
2323

24+
const cache = new Map<string, string | undefined>();
25+
2426
/**
2527
* Taken from https://github.com/evanw/node-source-map-support/blob/v0.5.21/source-map-support.js#L148-L177.
2628
*/
@@ -61,14 +63,24 @@ export function retrieveSourceMapURL(source: string) {
6163
return lastMatch[1];
6264
}
6365

66+
export function cachedRetrieveSourceMapURL(source: string): string | undefined {
67+
if (cache.has(source)) {
68+
return cache.get(source);
69+
} else {
70+
const result = retrieveSourceMapURL(source);
71+
cache.set(source, result);
72+
return result;
73+
}
74+
}
75+
6476
export function maybeRetrievePositionFromSourceMap(): Position | undefined {
6577
const stack = ErrorStackParser.parse(new Error());
6678

6779
if (stack[0].fileName == null) {
6880
return;
6981
}
7082

71-
const sourceMappingURL = retrieveSourceMapURL(stack[0].fileName);
83+
const sourceMappingURL = cachedRetrieveSourceMapURL(stack[0].fileName);
7284

7385
if (!sourceMappingURL) {
7486
return;

0 commit comments

Comments
 (0)