-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
99 lines (93 loc) · 2.64 KB
/
index.js
File metadata and controls
99 lines (93 loc) · 2.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
const StackTrace = require("stacktrace-js");
const crypto = require("crypto");
const globalExecutionContext = {};
const KEY_PREFIX = "$$exec_context$$";
/**
* Destroy the execution context
*
* @param {string} executionId
*/
function destroyExecutionContext(executionId) {
delete globalExecutionContext[executionId];
}
/**
* Get the execution UUID from the function name
*
* @param {string} functionName
* @returns {string} execution UUID
* */
function getExecutionUUID(functionName = "") {
return functionName
.replace("Object.", "")
.replace(KEY_PREFIX, "")
.replace("async ", "");
}
/**
* Find the context frame from the callstack
**/
const findContextFrame = () => {
const stack = StackTrace.getSync();
if (!stack || !stack.length) {
return null;
}
return stack.find(function findFrame(frame) {
if (frame && frame.functionName) {
return frame.functionName.includes(KEY_PREFIX);
}
});
};
/**
* Get the execution context from callstack
*
* @returns {any} execution context
*/
exports.getExecutionContext = function getExecutionContext() {
const stackFrame = findContextFrame();
if (!stackFrame) {
return null;
}
const uuid = getExecutionUUID(stackFrame.functionName);
return globalExecutionContext[uuid];
};
/**
* Set execution context
*
* @param {any} contextValue - context value
*/
exports.setExecutionContext = function setExecutionContext(contextValue) {
const stackFrame = findContextFrame();
if (!stackFrame) {
return;
}
const uuid = getExecutionUUID(stackFrame.functionName);
globalExecutionContext[uuid] = contextValue;
};
/**
* Initialize execution context
*
* @param {Function} handler - actual handler function
*/
exports.provideExecutionContext = function provideExecutionContext(
handler,
contextValue
) {
const uniqueId = "f-" + crypto.randomBytes(16).toString("hex") + "-" + Date.now();
const that = this;
const functionName = `Object.${KEY_PREFIX}${uniqueId}`;
const contextProvider = {
[functionName]: async function () {
try {
const returnValue = await handler.apply(that, arguments);
// destroy the execution context after the execution is completed
destroyExecutionContext(uniqueId);
return returnValue;
} catch (err) {
destroyExecutionContext(uniqueId);
throw err;
}
},
};
globalExecutionContext[uniqueId] = contextValue;
contextProvider[functionName].name = functionName;
return contextProvider[functionName];
};