@jsenv/snapshot 2.2.6 → 2.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/function_snapshot.js +46 -25
package/package.json
CHANGED
package/src/function_snapshot.js
CHANGED
|
@@ -4,22 +4,31 @@ import {
|
|
|
4
4
|
removeFileSync,
|
|
5
5
|
writeFileSync,
|
|
6
6
|
} from "@jsenv/filesystem";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
ensurePathnameTrailingSlash,
|
|
9
|
+
urlToFilename,
|
|
10
|
+
urlToRelativeUrl,
|
|
11
|
+
} from "@jsenv/urls";
|
|
8
12
|
import { takeDirectorySnapshot } from "./filesystem_snapshot.js";
|
|
9
13
|
import { replaceFluctuatingValues } from "./replace_fluctuating_values.js";
|
|
10
14
|
|
|
15
|
+
const consoleSpySymbol = Symbol.for("console_spy_for_jsenv_snapshot");
|
|
16
|
+
|
|
11
17
|
export const snapshotFunctionSideEffects = (
|
|
12
18
|
fn,
|
|
13
19
|
fnFileUrl,
|
|
14
|
-
sideEffectDirectoryRelativeUrl,
|
|
20
|
+
sideEffectDirectoryRelativeUrl = "./",
|
|
15
21
|
{
|
|
16
22
|
rootDirectoryUrl = new URL("./", fnFileUrl),
|
|
17
23
|
captureConsole = true,
|
|
18
24
|
filesystemEffects,
|
|
19
|
-
|
|
25
|
+
filesystemEffectsDirectory,
|
|
20
26
|
restoreFilesystem = true,
|
|
21
27
|
} = {},
|
|
22
28
|
) => {
|
|
29
|
+
if (filesystemEffectsDirectory === true) {
|
|
30
|
+
filesystemEffectsDirectory = "./fs/";
|
|
31
|
+
}
|
|
23
32
|
const sideEffectDirectoryUrl = new URL(
|
|
24
33
|
sideEffectDirectoryRelativeUrl,
|
|
25
34
|
fnFileUrl,
|
|
@@ -31,15 +40,15 @@ export const snapshotFunctionSideEffects = (
|
|
|
31
40
|
const sideEffectFileUrl = new URL(sideEffectFilename, sideEffectDirectoryUrl);
|
|
32
41
|
const sideEffects = [];
|
|
33
42
|
const finallyCallbackSet = new Set();
|
|
34
|
-
const onError = (e) => {
|
|
43
|
+
const onError = (e, isAsync) => {
|
|
35
44
|
sideEffects.push({
|
|
36
|
-
type: "throw",
|
|
45
|
+
type: isAsync ? "reject" : "throw",
|
|
37
46
|
value: e,
|
|
38
47
|
});
|
|
39
48
|
};
|
|
40
|
-
const onResult = (result) => {
|
|
49
|
+
const onResult = (result, isAsync) => {
|
|
41
50
|
sideEffects.push({
|
|
42
|
-
type: "return",
|
|
51
|
+
type: isAsync ? "resolve" : "return",
|
|
43
52
|
value: result,
|
|
44
53
|
});
|
|
45
54
|
};
|
|
@@ -51,7 +60,7 @@ export const snapshotFunctionSideEffects = (
|
|
|
51
60
|
sideEffectFileUrl,
|
|
52
61
|
stringifySideEffects(sideEffects, {
|
|
53
62
|
rootDirectoryUrl,
|
|
54
|
-
|
|
63
|
+
filesystemEffectsDirectory,
|
|
55
64
|
}),
|
|
56
65
|
);
|
|
57
66
|
sideEffectDirectorySnapshot.compare();
|
|
@@ -59,12 +68,17 @@ export const snapshotFunctionSideEffects = (
|
|
|
59
68
|
if (captureConsole) {
|
|
60
69
|
const installConsoleSpy = (methodName) => {
|
|
61
70
|
const methodSpied = console[methodName];
|
|
62
|
-
|
|
71
|
+
if (consoleSpySymbol in methodSpied) {
|
|
72
|
+
throw new Error("snapshotFunctionSideEffects already running");
|
|
73
|
+
}
|
|
74
|
+
const methodSpy = (message) => {
|
|
63
75
|
sideEffects.push({
|
|
64
76
|
type: `console.${methodName}`,
|
|
65
77
|
value: message,
|
|
66
78
|
});
|
|
67
79
|
};
|
|
80
|
+
methodSpy[consoleSpySymbol] = true;
|
|
81
|
+
console[methodName] = methodSpy;
|
|
68
82
|
finallyCallbackSet.add(() => {
|
|
69
83
|
console[methodName] = methodSpied;
|
|
70
84
|
});
|
|
@@ -75,7 +89,13 @@ export const snapshotFunctionSideEffects = (
|
|
|
75
89
|
installConsoleSpy("log");
|
|
76
90
|
}
|
|
77
91
|
if (filesystemEffects) {
|
|
78
|
-
const fsSideEffectDirectoryUrl =
|
|
92
|
+
const fsSideEffectDirectoryUrl = ensurePathnameTrailingSlash(
|
|
93
|
+
new URL(filesystemEffectsDirectory, sideEffectDirectoryUrl),
|
|
94
|
+
);
|
|
95
|
+
const fsSideEffectsDirectoryRelativeUrl = urlToRelativeUrl(
|
|
96
|
+
fsSideEffectDirectoryUrl,
|
|
97
|
+
sideEffectFileUrl,
|
|
98
|
+
);
|
|
79
99
|
for (const filesystemEffect of filesystemEffects) {
|
|
80
100
|
const from = new URL(filesystemEffect, fnFileUrl);
|
|
81
101
|
const relativeUrl = urlToRelativeUrl(from, fnFileUrl);
|
|
@@ -107,15 +127,15 @@ export const snapshotFunctionSideEffects = (
|
|
|
107
127
|
atStartState.content !== nowState.content ||
|
|
108
128
|
atStartState.mtimeMs !== nowState.mtimeMs
|
|
109
129
|
) {
|
|
110
|
-
if (
|
|
130
|
+
if (filesystemEffectsDirectory) {
|
|
131
|
+
writeFileSync(toUrl, nowState.content);
|
|
111
132
|
onFileSystemSideEffect({
|
|
112
|
-
type: `write file "${relativeUrl}"`,
|
|
133
|
+
type: `write file "${relativeUrl}" (see ./${fsSideEffectsDirectoryRelativeUrl}${relativeUrl})`,
|
|
113
134
|
value: nowState.content,
|
|
114
135
|
});
|
|
115
136
|
} else {
|
|
116
|
-
writeFileSync(toUrl, nowState.content);
|
|
117
137
|
onFileSystemSideEffect({
|
|
118
|
-
type: `write file "${relativeUrl}"
|
|
138
|
+
type: `write file "${relativeUrl}"`,
|
|
119
139
|
value: nowState.content,
|
|
120
140
|
});
|
|
121
141
|
}
|
|
@@ -139,25 +159,26 @@ export const snapshotFunctionSideEffects = (
|
|
|
139
159
|
try {
|
|
140
160
|
const returnValue = fn();
|
|
141
161
|
if (returnValue && returnValue.then) {
|
|
142
|
-
returnedPromise =
|
|
143
|
-
returnValue.then(
|
|
162
|
+
returnedPromise = returnValue.then(
|
|
144
163
|
(value) => {
|
|
145
|
-
onResult(value);
|
|
164
|
+
onResult(value, true);
|
|
146
165
|
onFinally();
|
|
147
166
|
},
|
|
148
167
|
(e) => {
|
|
149
|
-
onError(e);
|
|
168
|
+
onError(e, true);
|
|
150
169
|
onFinally();
|
|
151
170
|
},
|
|
152
171
|
);
|
|
153
|
-
|
|
154
|
-
onResult(returnValue);
|
|
172
|
+
return returnedPromise;
|
|
155
173
|
}
|
|
174
|
+
onResult(returnValue);
|
|
175
|
+
return null;
|
|
156
176
|
} catch (e) {
|
|
157
177
|
onError(e);
|
|
178
|
+
return null;
|
|
158
179
|
} finally {
|
|
159
180
|
if (returnedPromise) {
|
|
160
|
-
return;
|
|
181
|
+
return returnedPromise;
|
|
161
182
|
}
|
|
162
183
|
onFinally();
|
|
163
184
|
}
|
|
@@ -165,7 +186,7 @@ export const snapshotFunctionSideEffects = (
|
|
|
165
186
|
|
|
166
187
|
const stringifySideEffects = (
|
|
167
188
|
sideEffects,
|
|
168
|
-
{ rootDirectoryUrl,
|
|
189
|
+
{ rootDirectoryUrl, filesystemEffectsDirectory },
|
|
169
190
|
) => {
|
|
170
191
|
let string = "";
|
|
171
192
|
let index = 0;
|
|
@@ -186,17 +207,17 @@ const stringifySideEffects = (
|
|
|
186
207
|
sideEffect.type.startsWith("remove file") ||
|
|
187
208
|
sideEffect.type.startsWith("write file")
|
|
188
209
|
) {
|
|
189
|
-
if (
|
|
210
|
+
if (!filesystemEffectsDirectory) {
|
|
190
211
|
string += "\n";
|
|
191
212
|
string += value;
|
|
192
213
|
}
|
|
193
|
-
} else if (sideEffect.type === "throw") {
|
|
214
|
+
} else if (sideEffect.type === "throw" || sideEffect.type === "reject") {
|
|
194
215
|
value = replaceFluctuatingValues(value.stack, {
|
|
195
216
|
stringType: "error",
|
|
196
217
|
});
|
|
197
218
|
string += "\n";
|
|
198
219
|
string += value;
|
|
199
|
-
} else if (sideEffect.type === "return") {
|
|
220
|
+
} else if (sideEffect.type === "return" || sideEffect.type === "resolve") {
|
|
200
221
|
value =
|
|
201
222
|
value === undefined
|
|
202
223
|
? undefined
|