@jsenv/core 36.0.2 → 36.1.0
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/dist/jsenv_core.js +142 -876
- package/package.json +4 -4
- package/src/build/build.js +29 -40
- package/src/dev/file_service.js +2 -0
- package/src/dev/start_dev_server.js +2 -0
- package/src/kitchen/kitchen.js +65 -12
- package/src/kitchen/url_graph/url_graph_report.js +9 -5
- package/src/kitchen/url_graph.js +0 -1
- package/src/plugins/plugin_controller.js +15 -7
- package/src/plugins/plugins.js +2 -1
- package/src/plugins/protocol_file/jsenv_plugin_protocol_file.js +44 -39
- package/src/plugins/protocol_http/jsenv_plugin_protocol_http.js +4 -3
- package/src/plugins/reference_analysis/jsenv_plugin_reference_analysis.js +0 -88
- package/dist/js/supervisor.js +0 -1175
- package/src/helpers/basic_fetch.js +0 -53
- package/src/helpers/ping_server.js +0 -30
- package/src/plugins/supervisor/client/supervisor.js +0 -1153
- package/src/plugins/supervisor/html_supervisor_injection.js +0 -281
- package/src/plugins/supervisor/js_supervisor_injection.js +0 -283
- package/src/plugins/supervisor/jsenv_plugin_supervisor.js +0 -218
|
@@ -1,281 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Jsenv needs to track js execution in order to:
|
|
3
|
-
* 1. report errors
|
|
4
|
-
* 2. wait for all js execution inside an HTML page before killing the browser
|
|
5
|
-
*
|
|
6
|
-
* A naive approach would rely on "load" events on window but:
|
|
7
|
-
* scenario | covered by window "load"
|
|
8
|
-
* ------------------------------------------- | -------------------------
|
|
9
|
-
* js referenced by <script src> | yes
|
|
10
|
-
* js inlined into <script> | yes
|
|
11
|
-
* js referenced by <script type="module" src> | partially (not for import and top level await)
|
|
12
|
-
* js inlined into <script type="module"> | not at all
|
|
13
|
-
* Same for "error" event on window who is not enough
|
|
14
|
-
*
|
|
15
|
-
* <script src="file.js">
|
|
16
|
-
* becomes
|
|
17
|
-
* <script>
|
|
18
|
-
* window.__supervisor__.superviseScript('file.js')
|
|
19
|
-
* </script>
|
|
20
|
-
*
|
|
21
|
-
* <script>
|
|
22
|
-
* console.log(42)
|
|
23
|
-
* </script>
|
|
24
|
-
* becomes
|
|
25
|
-
* <script inlined-from-src="main.html@L10-C5.js">
|
|
26
|
-
* window.__supervisor.__superviseScript("main.html@L10-C5.js")
|
|
27
|
-
* </script>
|
|
28
|
-
*
|
|
29
|
-
* <script type="module" src="module.js"></script>
|
|
30
|
-
* becomes
|
|
31
|
-
* <script type="module">
|
|
32
|
-
* window.__supervisor__.superviseScriptTypeModule('module.js')
|
|
33
|
-
* </script>
|
|
34
|
-
*
|
|
35
|
-
* <script type="module">
|
|
36
|
-
* console.log(42)
|
|
37
|
-
* </script>
|
|
38
|
-
* becomes
|
|
39
|
-
* <script type="module" inlined-from-src="main.html@L10-C5.js">
|
|
40
|
-
* window.__supervisor__.superviseScriptTypeModule('main.html@L10-C5.js')
|
|
41
|
-
* </script>
|
|
42
|
-
*
|
|
43
|
-
* Why Inline scripts are converted to files dynamically?
|
|
44
|
-
* -> No changes required on js source code, it's only the HTML that is modified
|
|
45
|
-
* - Also allow to catch syntax errors and export missing
|
|
46
|
-
*/
|
|
47
|
-
|
|
48
|
-
import {
|
|
49
|
-
parseHtmlString,
|
|
50
|
-
stringifyHtmlAst,
|
|
51
|
-
visitHtmlNodes,
|
|
52
|
-
getHtmlNodeAttribute,
|
|
53
|
-
setHtmlNodeAttributes,
|
|
54
|
-
analyzeScriptNode,
|
|
55
|
-
injectHtmlNodeAsEarlyAsPossible,
|
|
56
|
-
createHtmlNode,
|
|
57
|
-
getHtmlNodePosition,
|
|
58
|
-
getHtmlNodeText,
|
|
59
|
-
setHtmlNodeText,
|
|
60
|
-
} from "@jsenv/ast";
|
|
61
|
-
import { generateInlineContentUrl, urlToRelativeUrl } from "@jsenv/urls";
|
|
62
|
-
|
|
63
|
-
import { injectSupervisorIntoJs } from "./js_supervisor_injection.js";
|
|
64
|
-
|
|
65
|
-
export const supervisorFileUrl = new URL(
|
|
66
|
-
"./client/supervisor.js",
|
|
67
|
-
import.meta.url,
|
|
68
|
-
).href;
|
|
69
|
-
|
|
70
|
-
export const injectSupervisorIntoHTML = async (
|
|
71
|
-
{ content, url },
|
|
72
|
-
{
|
|
73
|
-
supervisorScriptSrc = supervisorFileUrl,
|
|
74
|
-
supervisorOptions,
|
|
75
|
-
webServer,
|
|
76
|
-
onInlineScript = () => {},
|
|
77
|
-
generateInlineScriptSrc = ({ inlineScriptUrl }) =>
|
|
78
|
-
urlToRelativeUrl(inlineScriptUrl, webServer.rootDirectoryUrl),
|
|
79
|
-
inlineAsRemote,
|
|
80
|
-
},
|
|
81
|
-
) => {
|
|
82
|
-
const htmlAst = parseHtmlString(content);
|
|
83
|
-
const mutations = [];
|
|
84
|
-
const actions = [];
|
|
85
|
-
|
|
86
|
-
const scriptInfos = [];
|
|
87
|
-
// 1. Find inline and remote scripts
|
|
88
|
-
{
|
|
89
|
-
const handleInlineScript = (
|
|
90
|
-
scriptNode,
|
|
91
|
-
{ type, extension, textContent },
|
|
92
|
-
) => {
|
|
93
|
-
const { line, column, lineEnd, columnEnd, isOriginal } =
|
|
94
|
-
getHtmlNodePosition(scriptNode, { preferOriginal: true });
|
|
95
|
-
const inlineScriptUrl = generateInlineContentUrl({
|
|
96
|
-
url,
|
|
97
|
-
extension: extension || ".js",
|
|
98
|
-
line,
|
|
99
|
-
column,
|
|
100
|
-
lineEnd,
|
|
101
|
-
columnEnd,
|
|
102
|
-
});
|
|
103
|
-
const inlineScriptSrc = generateInlineScriptSrc({
|
|
104
|
-
type,
|
|
105
|
-
textContent,
|
|
106
|
-
inlineScriptUrl,
|
|
107
|
-
isOriginal,
|
|
108
|
-
line,
|
|
109
|
-
column,
|
|
110
|
-
});
|
|
111
|
-
onInlineScript({
|
|
112
|
-
type,
|
|
113
|
-
textContent,
|
|
114
|
-
url: inlineScriptUrl,
|
|
115
|
-
isOriginal,
|
|
116
|
-
line,
|
|
117
|
-
column,
|
|
118
|
-
src: inlineScriptSrc,
|
|
119
|
-
});
|
|
120
|
-
if (inlineAsRemote) {
|
|
121
|
-
// prefere la version src
|
|
122
|
-
scriptInfos.push({ type, src: inlineScriptSrc });
|
|
123
|
-
const remoteJsSupervised = generateCodeToSuperviseScriptWithSrc({
|
|
124
|
-
type,
|
|
125
|
-
src: inlineScriptSrc,
|
|
126
|
-
});
|
|
127
|
-
mutations.push(() => {
|
|
128
|
-
setHtmlNodeText(scriptNode, remoteJsSupervised, {
|
|
129
|
-
indentation: "auto",
|
|
130
|
-
});
|
|
131
|
-
setHtmlNodeAttributes(scriptNode, {
|
|
132
|
-
"jsenv-cooked-by": "jsenv:supervisor",
|
|
133
|
-
"src": undefined,
|
|
134
|
-
"inlined-from-src": inlineScriptSrc,
|
|
135
|
-
});
|
|
136
|
-
});
|
|
137
|
-
} else {
|
|
138
|
-
scriptInfos.push({ type, src: inlineScriptSrc, isInline: true });
|
|
139
|
-
actions.push(async () => {
|
|
140
|
-
try {
|
|
141
|
-
const inlineJsSupervised = await injectSupervisorIntoJs({
|
|
142
|
-
webServer,
|
|
143
|
-
content: textContent,
|
|
144
|
-
url: inlineScriptUrl,
|
|
145
|
-
type,
|
|
146
|
-
inlineSrc: inlineScriptSrc,
|
|
147
|
-
});
|
|
148
|
-
mutations.push(() => {
|
|
149
|
-
setHtmlNodeText(scriptNode, inlineJsSupervised, {
|
|
150
|
-
indentation: "auto",
|
|
151
|
-
});
|
|
152
|
-
setHtmlNodeAttributes(scriptNode, {
|
|
153
|
-
"jsenv-cooked-by": "jsenv:supervisor",
|
|
154
|
-
});
|
|
155
|
-
});
|
|
156
|
-
} catch (e) {
|
|
157
|
-
if (e.code === "PARSE_ERROR") {
|
|
158
|
-
// mutations.push(() => {
|
|
159
|
-
// setHtmlNodeAttributes(scriptNode, {
|
|
160
|
-
// "jsenv-cooked-by": "jsenv:supervisor",
|
|
161
|
-
// })
|
|
162
|
-
// })
|
|
163
|
-
// on touche a rien
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
throw e;
|
|
167
|
-
}
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
};
|
|
171
|
-
const handleScriptWithSrc = (scriptNode, { type, src }) => {
|
|
172
|
-
scriptInfos.push({ type, src });
|
|
173
|
-
const remoteJsSupervised = generateCodeToSuperviseScriptWithSrc({
|
|
174
|
-
type,
|
|
175
|
-
src,
|
|
176
|
-
});
|
|
177
|
-
mutations.push(() => {
|
|
178
|
-
setHtmlNodeText(scriptNode, remoteJsSupervised, {
|
|
179
|
-
indentation: "auto",
|
|
180
|
-
});
|
|
181
|
-
setHtmlNodeAttributes(scriptNode, {
|
|
182
|
-
"jsenv-cooked-by": "jsenv:supervisor",
|
|
183
|
-
"src": undefined,
|
|
184
|
-
"inlined-from-src": src,
|
|
185
|
-
});
|
|
186
|
-
});
|
|
187
|
-
};
|
|
188
|
-
visitHtmlNodes(htmlAst, {
|
|
189
|
-
script: (scriptNode) => {
|
|
190
|
-
const { type, extension } = analyzeScriptNode(scriptNode);
|
|
191
|
-
if (type !== "js_classic" && type !== "js_module") {
|
|
192
|
-
return;
|
|
193
|
-
}
|
|
194
|
-
if (getHtmlNodeAttribute(scriptNode, "jsenv-injected-by")) {
|
|
195
|
-
return;
|
|
196
|
-
}
|
|
197
|
-
const noSupervisor = getHtmlNodeAttribute(scriptNode, "no-supervisor");
|
|
198
|
-
if (noSupervisor !== undefined) {
|
|
199
|
-
return;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
const scriptNodeText = getHtmlNodeText(scriptNode);
|
|
203
|
-
if (scriptNodeText) {
|
|
204
|
-
handleInlineScript(scriptNode, {
|
|
205
|
-
type,
|
|
206
|
-
extension,
|
|
207
|
-
textContent: scriptNodeText,
|
|
208
|
-
});
|
|
209
|
-
return;
|
|
210
|
-
}
|
|
211
|
-
const src = getHtmlNodeAttribute(scriptNode, "src");
|
|
212
|
-
if (src) {
|
|
213
|
-
const urlObject = new URL(src, "http://example.com");
|
|
214
|
-
if (urlObject.searchParams.has("inline")) {
|
|
215
|
-
return;
|
|
216
|
-
}
|
|
217
|
-
handleScriptWithSrc(scriptNode, { type, src });
|
|
218
|
-
return;
|
|
219
|
-
}
|
|
220
|
-
},
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
// 2. Inject supervisor js file + setup call
|
|
224
|
-
{
|
|
225
|
-
const setupParamsSource = stringifyParams(
|
|
226
|
-
{
|
|
227
|
-
...supervisorOptions,
|
|
228
|
-
serverIsJsenvDevServer: webServer.isJsenvDevServer,
|
|
229
|
-
rootDirectoryUrl: webServer.rootDirectoryUrl,
|
|
230
|
-
scriptInfos,
|
|
231
|
-
},
|
|
232
|
-
" ",
|
|
233
|
-
);
|
|
234
|
-
injectHtmlNodeAsEarlyAsPossible(
|
|
235
|
-
htmlAst,
|
|
236
|
-
createHtmlNode({
|
|
237
|
-
tagName: "script",
|
|
238
|
-
textContent: `window.__supervisor__.setup({${setupParamsSource}})`,
|
|
239
|
-
}),
|
|
240
|
-
"jsenv:supervisor",
|
|
241
|
-
);
|
|
242
|
-
injectHtmlNodeAsEarlyAsPossible(
|
|
243
|
-
htmlAst,
|
|
244
|
-
createHtmlNode({
|
|
245
|
-
tagName: "script",
|
|
246
|
-
src: supervisorScriptSrc,
|
|
247
|
-
}),
|
|
248
|
-
"jsenv:supervisor",
|
|
249
|
-
);
|
|
250
|
-
}
|
|
251
|
-
// 3. Perform actions (transforming inline script content) and html mutations
|
|
252
|
-
if (actions.length > 0) {
|
|
253
|
-
await Promise.all(actions.map((action) => action()));
|
|
254
|
-
}
|
|
255
|
-
mutations.forEach((mutation) => mutation());
|
|
256
|
-
const htmlModified = stringifyHtmlAst(htmlAst);
|
|
257
|
-
return {
|
|
258
|
-
content: htmlModified,
|
|
259
|
-
};
|
|
260
|
-
};
|
|
261
|
-
|
|
262
|
-
const stringifyParams = (params, prefix = "") => {
|
|
263
|
-
const source = JSON.stringify(params, null, prefix);
|
|
264
|
-
if (prefix.length) {
|
|
265
|
-
// remove leading "{\n"
|
|
266
|
-
// remove leading prefix
|
|
267
|
-
// remove trailing "\n}"
|
|
268
|
-
return source.slice(2 + prefix.length, -2);
|
|
269
|
-
}
|
|
270
|
-
// remove leading "{"
|
|
271
|
-
// remove trailing "}"
|
|
272
|
-
return source.slice(1, -1);
|
|
273
|
-
};
|
|
274
|
-
|
|
275
|
-
const generateCodeToSuperviseScriptWithSrc = ({ type, src }) => {
|
|
276
|
-
const srcEncoded = JSON.stringify(src);
|
|
277
|
-
if (type === "js_module") {
|
|
278
|
-
return `window.__supervisor__.superviseScriptTypeModule(${srcEncoded}, (url) => import(url));`;
|
|
279
|
-
}
|
|
280
|
-
return `window.__supervisor__.superviseScript(${srcEncoded});`;
|
|
281
|
-
};
|
|
@@ -1,283 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* ```js
|
|
3
|
-
* console.log(42)
|
|
4
|
-
* ```
|
|
5
|
-
* becomes
|
|
6
|
-
* ```js
|
|
7
|
-
* window.__supervisor__.jsClassicStart('main.html@L10-L13.js')
|
|
8
|
-
* try {
|
|
9
|
-
* console.log(42)
|
|
10
|
-
* window.__supervisor__.jsClassicEnd('main.html@L10-L13.js')
|
|
11
|
-
* } catch(e) {
|
|
12
|
-
* window.__supervisor__.jsClassicError('main.html@L10-L13.js', e)
|
|
13
|
-
* }
|
|
14
|
-
* ```
|
|
15
|
-
*
|
|
16
|
-
* ```js
|
|
17
|
-
* import value from "./file.js"
|
|
18
|
-
* console.log(value)
|
|
19
|
-
* ```
|
|
20
|
-
* becomes
|
|
21
|
-
* ```js
|
|
22
|
-
* window.__supervisor__.jsModuleStart('main.html@L10-L13.js')
|
|
23
|
-
* try {
|
|
24
|
-
* const value = await import("./file.js")
|
|
25
|
-
* console.log(value)
|
|
26
|
-
* window.__supervisor__.jsModuleEnd('main.html@L10-L13.js')
|
|
27
|
-
* } catch(e) {
|
|
28
|
-
* window.__supervisor__.jsModuleError('main.html@L10-L13.js', e)
|
|
29
|
-
* }
|
|
30
|
-
* ```
|
|
31
|
-
*
|
|
32
|
-
* -> TO KEEP IN MIND:
|
|
33
|
-
* Static import can throw errors like
|
|
34
|
-
* The requested module '/js_module_export_not_found/foo.js' does not provide an export named 'answerr'
|
|
35
|
-
* While dynamic import will work just fine
|
|
36
|
-
* and create a variable named "undefined"
|
|
37
|
-
*/
|
|
38
|
-
|
|
39
|
-
import { urlToRelativeUrl } from "@jsenv/urls";
|
|
40
|
-
import { applyBabelPlugins } from "@jsenv/ast";
|
|
41
|
-
import { SOURCEMAP, generateSourcemapDataUrl } from "@jsenv/sourcemap";
|
|
42
|
-
|
|
43
|
-
export const injectSupervisorIntoJs = async ({
|
|
44
|
-
webServer,
|
|
45
|
-
content,
|
|
46
|
-
url,
|
|
47
|
-
type,
|
|
48
|
-
inlineSrc,
|
|
49
|
-
}) => {
|
|
50
|
-
const babelPluginJsSupervisor =
|
|
51
|
-
type === "js_module"
|
|
52
|
-
? babelPluginJsModuleSupervisor
|
|
53
|
-
: babelPluginJsClassicSupervisor;
|
|
54
|
-
const result = await applyBabelPlugins({
|
|
55
|
-
urlInfo: {
|
|
56
|
-
content,
|
|
57
|
-
originalUrl: url,
|
|
58
|
-
type,
|
|
59
|
-
},
|
|
60
|
-
babelPlugins: [[babelPluginJsSupervisor, { inlineSrc }]],
|
|
61
|
-
});
|
|
62
|
-
let code = result.code;
|
|
63
|
-
let map = result.map;
|
|
64
|
-
const sourcemapDataUrl = generateSourcemapDataUrl(map);
|
|
65
|
-
code = SOURCEMAP.writeComment({
|
|
66
|
-
contentType: "text/javascript",
|
|
67
|
-
content: code,
|
|
68
|
-
specifier: sourcemapDataUrl,
|
|
69
|
-
});
|
|
70
|
-
code = `${code}
|
|
71
|
-
//# sourceURL=${urlToRelativeUrl(url, webServer.rootDirectoryUrl)}`;
|
|
72
|
-
return code;
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
const babelPluginJsModuleSupervisor = (babel) => {
|
|
76
|
-
const t = babel.types;
|
|
77
|
-
|
|
78
|
-
return {
|
|
79
|
-
name: "js-module-supervisor",
|
|
80
|
-
visitor: {
|
|
81
|
-
Program: (programPath, state) => {
|
|
82
|
-
const { inlineSrc } = state.opts;
|
|
83
|
-
if (state.file.metadata.jsExecutionInstrumented) return;
|
|
84
|
-
state.file.metadata.jsExecutionInstrumented = true;
|
|
85
|
-
|
|
86
|
-
const urlNode = t.stringLiteral(inlineSrc);
|
|
87
|
-
const startCallNode = createSupervisionCall({
|
|
88
|
-
t,
|
|
89
|
-
urlNode,
|
|
90
|
-
methodName: "jsModuleStart",
|
|
91
|
-
});
|
|
92
|
-
const endCallNode = createSupervisionCall({
|
|
93
|
-
t,
|
|
94
|
-
urlNode,
|
|
95
|
-
methodName: "jsModuleEnd",
|
|
96
|
-
});
|
|
97
|
-
const errorCallNode = createSupervisionCall({
|
|
98
|
-
t,
|
|
99
|
-
urlNode,
|
|
100
|
-
methodName: "jsModuleError",
|
|
101
|
-
args: [t.identifier("e")],
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
const bodyPath = programPath.get("body");
|
|
105
|
-
const importNodes = [];
|
|
106
|
-
const topLevelNodes = [];
|
|
107
|
-
for (const topLevelNodePath of bodyPath) {
|
|
108
|
-
const topLevelNode = topLevelNodePath.node;
|
|
109
|
-
if (t.isImportDeclaration(topLevelNode)) {
|
|
110
|
-
importNodes.push(topLevelNode);
|
|
111
|
-
} else {
|
|
112
|
-
topLevelNodes.push(topLevelNode);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// replace all import nodes with dynamic imports
|
|
117
|
-
const dynamicImports = [];
|
|
118
|
-
importNodes.forEach((importNode) => {
|
|
119
|
-
const dynamicImportConversion = convertStaticImportIntoDynamicImport(
|
|
120
|
-
importNode,
|
|
121
|
-
t,
|
|
122
|
-
);
|
|
123
|
-
if (Array.isArray(dynamicImportConversion)) {
|
|
124
|
-
dynamicImports.push(...dynamicImportConversion);
|
|
125
|
-
} else {
|
|
126
|
-
dynamicImports.push(dynamicImportConversion);
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
const tryCatchNode = t.tryStatement(
|
|
131
|
-
t.blockStatement([...dynamicImports, ...topLevelNodes, endCallNode]),
|
|
132
|
-
t.catchClause(t.identifier("e"), t.blockStatement([errorCallNode])),
|
|
133
|
-
);
|
|
134
|
-
programPath.replaceWith(t.program([startCallNode, tryCatchNode]));
|
|
135
|
-
},
|
|
136
|
-
},
|
|
137
|
-
};
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
const convertStaticImportIntoDynamicImport = (staticImportNode, t) => {
|
|
141
|
-
const awaitExpression = t.awaitExpression(
|
|
142
|
-
t.callExpression(t.import(), [
|
|
143
|
-
t.stringLiteral(staticImportNode.source.value),
|
|
144
|
-
]),
|
|
145
|
-
);
|
|
146
|
-
|
|
147
|
-
// import "./file.js" -> await import("./file.js")
|
|
148
|
-
if (staticImportNode.specifiers.length === 0) {
|
|
149
|
-
return t.expressionStatement(awaitExpression);
|
|
150
|
-
}
|
|
151
|
-
if (staticImportNode.specifiers.length === 1) {
|
|
152
|
-
const [firstSpecifier] = staticImportNode.specifiers;
|
|
153
|
-
if (firstSpecifier.type === "ImportNamespaceSpecifier") {
|
|
154
|
-
return t.variableDeclaration("const", [
|
|
155
|
-
t.variableDeclarator(
|
|
156
|
-
t.identifier(firstSpecifier.local.name),
|
|
157
|
-
awaitExpression,
|
|
158
|
-
),
|
|
159
|
-
]);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
if (staticImportNode.specifiers.length === 2) {
|
|
163
|
-
const [first, second] = staticImportNode.specifiers;
|
|
164
|
-
if (
|
|
165
|
-
first.type === "ImportDefaultSpecifier" &&
|
|
166
|
-
second.type === "ImportNamespaceSpecifier"
|
|
167
|
-
) {
|
|
168
|
-
const namespaceDeclaration = t.variableDeclaration("const", [
|
|
169
|
-
t.variableDeclarator(t.identifier(second.local.name), awaitExpression),
|
|
170
|
-
]);
|
|
171
|
-
const defaultDeclaration = t.variableDeclaration("const", [
|
|
172
|
-
t.variableDeclarator(
|
|
173
|
-
t.identifier(first.local.name),
|
|
174
|
-
t.memberExpression(
|
|
175
|
-
t.identifier(second.local.name),
|
|
176
|
-
t.identifier("default"),
|
|
177
|
-
),
|
|
178
|
-
),
|
|
179
|
-
]);
|
|
180
|
-
return [namespaceDeclaration, defaultDeclaration];
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// import { name } from "./file.js" -> const { name } = await import("./file.js")
|
|
185
|
-
// import toto, { name } from "./file.js" -> const { name, default as toto } = await import("./file.js")
|
|
186
|
-
const objectPattern = t.objectPattern(
|
|
187
|
-
staticImportNode.specifiers.map((specifier) => {
|
|
188
|
-
if (specifier.type === "ImportDefaultSpecifier") {
|
|
189
|
-
return t.objectProperty(
|
|
190
|
-
t.identifier("default"),
|
|
191
|
-
t.identifier(specifier.local.name),
|
|
192
|
-
false, // computed
|
|
193
|
-
false, // shorthand
|
|
194
|
-
);
|
|
195
|
-
}
|
|
196
|
-
// if (specifier.type === "ImportNamespaceSpecifier") {
|
|
197
|
-
// return t.restElement(t.identifier(specifier.local.name))
|
|
198
|
-
// }
|
|
199
|
-
const isRenamed = specifier.imported.name !== specifier.local.name;
|
|
200
|
-
if (isRenamed) {
|
|
201
|
-
return t.objectProperty(
|
|
202
|
-
t.identifier(specifier.imported.name),
|
|
203
|
-
t.identifier(specifier.local.name),
|
|
204
|
-
false, // computed
|
|
205
|
-
false, // shorthand
|
|
206
|
-
);
|
|
207
|
-
}
|
|
208
|
-
// shorthand must be true
|
|
209
|
-
return t.objectProperty(
|
|
210
|
-
t.identifier(specifier.local.name),
|
|
211
|
-
t.identifier(specifier.local.name),
|
|
212
|
-
false, // computed
|
|
213
|
-
true, // shorthand
|
|
214
|
-
);
|
|
215
|
-
}),
|
|
216
|
-
);
|
|
217
|
-
const variableDeclarator = t.variableDeclarator(
|
|
218
|
-
objectPattern,
|
|
219
|
-
awaitExpression,
|
|
220
|
-
);
|
|
221
|
-
const variableDeclaration = t.variableDeclaration("const", [
|
|
222
|
-
variableDeclarator,
|
|
223
|
-
]);
|
|
224
|
-
return variableDeclaration;
|
|
225
|
-
};
|
|
226
|
-
|
|
227
|
-
const babelPluginJsClassicSupervisor = (babel) => {
|
|
228
|
-
const t = babel.types;
|
|
229
|
-
|
|
230
|
-
return {
|
|
231
|
-
name: "js-classic-supervisor",
|
|
232
|
-
visitor: {
|
|
233
|
-
Program: (programPath, state) => {
|
|
234
|
-
const { inlineSrc } = state.opts;
|
|
235
|
-
if (state.file.metadata.jsExecutionInstrumented) return;
|
|
236
|
-
state.file.metadata.jsExecutionInstrumented = true;
|
|
237
|
-
|
|
238
|
-
const urlNode = t.stringLiteral(inlineSrc);
|
|
239
|
-
const startCallNode = createSupervisionCall({
|
|
240
|
-
t,
|
|
241
|
-
urlNode,
|
|
242
|
-
methodName: "jsClassicStart",
|
|
243
|
-
});
|
|
244
|
-
const endCallNode = createSupervisionCall({
|
|
245
|
-
t,
|
|
246
|
-
urlNode,
|
|
247
|
-
methodName: "jsClassicEnd",
|
|
248
|
-
});
|
|
249
|
-
const errorCallNode = createSupervisionCall({
|
|
250
|
-
t,
|
|
251
|
-
urlNode,
|
|
252
|
-
methodName: "jsClassicError",
|
|
253
|
-
args: [t.identifier("e")],
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
const topLevelNodes = programPath.node.body;
|
|
257
|
-
const tryCatchNode = t.tryStatement(
|
|
258
|
-
t.blockStatement([...topLevelNodes, endCallNode]),
|
|
259
|
-
t.catchClause(t.identifier("e"), t.blockStatement([errorCallNode])),
|
|
260
|
-
);
|
|
261
|
-
|
|
262
|
-
programPath.replaceWith(t.program([startCallNode, tryCatchNode]));
|
|
263
|
-
},
|
|
264
|
-
},
|
|
265
|
-
};
|
|
266
|
-
};
|
|
267
|
-
|
|
268
|
-
const createSupervisionCall = ({ t, methodName, urlNode, args = [] }) => {
|
|
269
|
-
return t.expressionStatement(
|
|
270
|
-
t.callExpression(
|
|
271
|
-
t.memberExpression(
|
|
272
|
-
t.memberExpression(
|
|
273
|
-
t.identifier("window"),
|
|
274
|
-
t.identifier("__supervisor__"),
|
|
275
|
-
),
|
|
276
|
-
t.identifier(methodName),
|
|
277
|
-
),
|
|
278
|
-
[urlNode, ...args],
|
|
279
|
-
),
|
|
280
|
-
[],
|
|
281
|
-
null,
|
|
282
|
-
);
|
|
283
|
-
};
|