@jsenv/core 27.3.2 → 27.4.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/README.md +16 -4
- package/dist/controllable_child_process.mjs +1 -0
- package/dist/controllable_worker_thread.mjs +1 -0
- package/dist/js/event_source_client.js +45 -24
- package/dist/js/execute_using_dynamic_import.js +5 -3
- package/dist/js/html_supervisor_installer.js +368 -139
- package/dist/main.js +668 -471
- package/package.json +5 -6
- package/src/build/build.js +6 -4
- package/src/build/graph_utils.js +14 -11
- package/src/execute/run.js +29 -28
- package/src/execute/runtimes/browsers/from_playwright.js +90 -92
- package/src/execute/runtimes/node/execute_using_dynamic_import.js +8 -2
- package/src/execute/runtimes/node/node_child_process.js +2 -0
- package/src/execute/runtimes/node/node_worker_thread.js +11 -6
- package/src/helpers/event_source/event_source.js +38 -17
- package/src/omega/errors.js +41 -9
- package/src/omega/kitchen.js +35 -19
- package/src/omega/omega_server.js +54 -1
- package/src/omega/server/file_service.js +30 -3
- package/src/omega/url_graph/url_graph_report.js +2 -4
- package/src/omega/url_graph.js +29 -16
- package/src/plugins/autoreload/dev_sse/client/event_source_client.js +8 -8
- package/src/plugins/autoreload/dev_sse/jsenv_plugin_dev_sse_server.js +160 -172
- package/src/plugins/autoreload/jsenv_plugin_autoreload.js +0 -4
- package/src/plugins/bundling/js_module/bundle_js_module.js +0 -1
- package/src/plugins/html_supervisor/client/error_in_document.js +268 -121
- package/src/plugins/html_supervisor/client/html_supervisor_installer.js +47 -5
- package/src/plugins/html_supervisor/jsenv_plugin_html_supervisor.js +37 -12
- package/src/plugins/node_esm_resolution/jsenv_plugin_node_esm_resolution.js +1 -2
- package/src/plugins/plugins.js +0 -2
- package/src/plugins/url_analysis/js/js_urls.js +0 -9
- package/src/plugins/url_analysis/jsenv_plugin_url_analysis.js +3 -1
- package/src/test/coverage/report_to_coverage.js +16 -11
- package/src/test/execute_plan.js +3 -2
- package/src/test/execute_test_plan.js +3 -1
- package/src/test/logs_file_execution.js +60 -27
- package/src/test/logs_file_execution.test.mjs +41 -0
package/dist/main.js
CHANGED
|
@@ -5928,19 +5928,6 @@ const generateInlineContentUrl = ({
|
|
|
5928
5928
|
return inlineContentUrl;
|
|
5929
5929
|
};
|
|
5930
5930
|
|
|
5931
|
-
const urlToFileSystemPath = url => {
|
|
5932
|
-
let urlString = String(url);
|
|
5933
|
-
|
|
5934
|
-
if (urlString[urlString.length - 1] === "/") {
|
|
5935
|
-
// remove trailing / so that nodejs path becomes predictable otherwise it logs
|
|
5936
|
-
// the trailing slash on linux but does not on windows
|
|
5937
|
-
urlString = urlString.slice(0, -1);
|
|
5938
|
-
}
|
|
5939
|
-
|
|
5940
|
-
const fileSystemPath = fileURLToPath(urlString);
|
|
5941
|
-
return fileSystemPath;
|
|
5942
|
-
};
|
|
5943
|
-
|
|
5944
5931
|
// consider switching to https://babeljs.io/docs/en/babel-code-frame
|
|
5945
5932
|
const stringifyUrlSite = ({
|
|
5946
5933
|
url,
|
|
@@ -5953,7 +5940,7 @@ const stringifyUrlSite = ({
|
|
|
5953
5940
|
lineMaxLength,
|
|
5954
5941
|
color
|
|
5955
5942
|
} = {}) => {
|
|
5956
|
-
let string =
|
|
5943
|
+
let string = url;
|
|
5957
5944
|
|
|
5958
5945
|
if (typeof line === "number") {
|
|
5959
5946
|
string += `:${line}`;
|
|
@@ -5978,15 +5965,6 @@ const stringifyUrlSite = ({
|
|
|
5978
5965
|
return `${string}
|
|
5979
5966
|
${sourceLoc}`;
|
|
5980
5967
|
};
|
|
5981
|
-
const humanizeUrl = url => {
|
|
5982
|
-
if (url.startsWith("file://")) {
|
|
5983
|
-
// we prefer file system path because vscode reliably make them clickable
|
|
5984
|
-
// and sometimes it won't for file:// urls
|
|
5985
|
-
return urlToFileSystemPath(url);
|
|
5986
|
-
}
|
|
5987
|
-
|
|
5988
|
-
return url;
|
|
5989
|
-
};
|
|
5990
5968
|
const showSourceLocation = ({
|
|
5991
5969
|
content,
|
|
5992
5970
|
line,
|
|
@@ -6489,6 +6467,19 @@ const urlToBasename = url => {
|
|
|
6489
6467
|
return basename;
|
|
6490
6468
|
};
|
|
6491
6469
|
|
|
6470
|
+
const urlToFileSystemPath = url => {
|
|
6471
|
+
let urlString = String(url);
|
|
6472
|
+
|
|
6473
|
+
if (urlString[urlString.length - 1] === "/") {
|
|
6474
|
+
// remove trailing / so that nodejs path becomes predictable otherwise it logs
|
|
6475
|
+
// the trailing slash on linux but does not on windows
|
|
6476
|
+
urlString = urlString.slice(0, -1);
|
|
6477
|
+
}
|
|
6478
|
+
|
|
6479
|
+
const fileSystemPath = fileURLToPath(urlString);
|
|
6480
|
+
return fileSystemPath;
|
|
6481
|
+
};
|
|
6482
|
+
|
|
6492
6483
|
const assertAndNormalizeDirectoryUrl = value => {
|
|
6493
6484
|
let urlString;
|
|
6494
6485
|
|
|
@@ -8470,22 +8461,11 @@ const parseAndTransformJsUrls = async (urlInfo, context) => {
|
|
|
8470
8461
|
} = context;
|
|
8471
8462
|
const actions = [];
|
|
8472
8463
|
const magicSource = createMagicSource(urlInfo.content);
|
|
8473
|
-
urlInfo.data.usesImport = false;
|
|
8474
|
-
urlInfo.data.usesExport = false;
|
|
8475
|
-
urlInfo.data.usesImportAssertion = false;
|
|
8476
8464
|
jsMentions.forEach(jsMention => {
|
|
8477
|
-
if (jsMention.assert) {
|
|
8478
|
-
urlInfo.data.usesImportAssertion = true;
|
|
8479
|
-
}
|
|
8480
|
-
|
|
8481
8465
|
if (jsMention.subtype === "import_static" || jsMention.subtype === "import_dynamic") {
|
|
8482
8466
|
urlInfo.data.usesImport = true;
|
|
8483
8467
|
}
|
|
8484
8468
|
|
|
8485
|
-
if (jsMention.subtype === "export") {
|
|
8486
|
-
urlInfo.data.usesExport = true;
|
|
8487
|
-
}
|
|
8488
|
-
|
|
8489
8469
|
const [reference] = referenceUtils.found({
|
|
8490
8470
|
type: jsMention.type,
|
|
8491
8471
|
subtype: jsMention.subtype,
|
|
@@ -8633,7 +8613,9 @@ const jsenvPluginUrlAnalysis = ({
|
|
|
8633
8613
|
type: "filesystem",
|
|
8634
8614
|
subtype: "directory_entry",
|
|
8635
8615
|
specifier: directoryEntryName,
|
|
8636
|
-
trace:
|
|
8616
|
+
trace: {
|
|
8617
|
+
message: `"${directoryRelativeUrl}${directoryEntryName}" entry in directory referenced by ${originalDirectoryReference.trace.message}`
|
|
8618
|
+
}
|
|
8637
8619
|
});
|
|
8638
8620
|
});
|
|
8639
8621
|
}
|
|
@@ -10927,9 +10909,7 @@ const jsenvPluginNodeEsmResolution = ({
|
|
|
10927
10909
|
const onFileChange = () => {
|
|
10928
10910
|
packageScopesCache.clear();
|
|
10929
10911
|
packageJsonsCache.clear();
|
|
10930
|
-
|
|
10931
|
-
const urlInfo = urlGraph.getUrlInfo(url);
|
|
10932
|
-
|
|
10912
|
+
urlGraph.urlInfoMap.forEach(urlInfo => {
|
|
10933
10913
|
if (urlInfo.dependsOnPackageJson) {
|
|
10934
10914
|
urlGraph.considerModified(urlInfo);
|
|
10935
10915
|
}
|
|
@@ -12050,6 +12030,8 @@ const jsenvPluginInlineUrls = () => {
|
|
|
12050
12030
|
};
|
|
12051
12031
|
};
|
|
12052
12032
|
|
|
12033
|
+
const requireFromJsenv = createRequire(import.meta.url);
|
|
12034
|
+
|
|
12053
12035
|
/*
|
|
12054
12036
|
* Things happening here
|
|
12055
12037
|
* - html supervisor module injection
|
|
@@ -12067,13 +12049,32 @@ const jsenvPluginHtmlSupervisor = ({
|
|
|
12067
12049
|
dev: true,
|
|
12068
12050
|
test: true
|
|
12069
12051
|
},
|
|
12052
|
+
serve: request => {
|
|
12053
|
+
if (!request.ressource.startsWith("/__open_in_editor__/")) {
|
|
12054
|
+
return null;
|
|
12055
|
+
}
|
|
12056
|
+
|
|
12057
|
+
const file = request.ressource.slice("/__open_in_editor__/".length);
|
|
12058
|
+
|
|
12059
|
+
if (!file) {
|
|
12060
|
+
return {
|
|
12061
|
+
status: 400,
|
|
12062
|
+
body: 'Missing "file" in url search params'
|
|
12063
|
+
};
|
|
12064
|
+
}
|
|
12065
|
+
|
|
12066
|
+
const launch = requireFromJsenv("launch-editor");
|
|
12067
|
+
launch(fileURLToPath(file), () => {// ignore error for now
|
|
12068
|
+
});
|
|
12069
|
+
return {
|
|
12070
|
+
status: 200
|
|
12071
|
+
};
|
|
12072
|
+
},
|
|
12070
12073
|
transformUrlContent: {
|
|
12071
12074
|
html: ({
|
|
12072
12075
|
url,
|
|
12073
12076
|
content
|
|
12074
|
-
}, {
|
|
12075
|
-
referenceUtils
|
|
12076
|
-
}) => {
|
|
12077
|
+
}, context) => {
|
|
12077
12078
|
const htmlAst = parseHtmlString(content);
|
|
12078
12079
|
const scriptsToSupervise = [];
|
|
12079
12080
|
|
|
@@ -12096,7 +12097,7 @@ const jsenvPluginHtmlSupervisor = ({
|
|
|
12096
12097
|
lineEnd,
|
|
12097
12098
|
columnEnd
|
|
12098
12099
|
});
|
|
12099
|
-
const [inlineScriptReference] = referenceUtils.foundInline({
|
|
12100
|
+
const [inlineScriptReference] = context.referenceUtils.foundInline({
|
|
12100
12101
|
type: "script_src",
|
|
12101
12102
|
expectedType: {
|
|
12102
12103
|
classic: "js_classic",
|
|
@@ -12173,7 +12174,7 @@ const jsenvPluginHtmlSupervisor = ({
|
|
|
12173
12174
|
}
|
|
12174
12175
|
}
|
|
12175
12176
|
});
|
|
12176
|
-
const [htmlSupervisorInstallerFileReference] = referenceUtils.inject({
|
|
12177
|
+
const [htmlSupervisorInstallerFileReference] = context.referenceUtils.inject({
|
|
12177
12178
|
type: "js_import_export",
|
|
12178
12179
|
expectedType: "js_module",
|
|
12179
12180
|
specifier: htmlSupervisorInstallerFileUrl
|
|
@@ -12185,11 +12186,12 @@ const jsenvPluginHtmlSupervisor = ({
|
|
|
12185
12186
|
import { installHtmlSupervisor } from ${htmlSupervisorInstallerFileReference.generatedSpecifier}
|
|
12186
12187
|
installHtmlSupervisor(${JSON.stringify({
|
|
12187
12188
|
logs,
|
|
12188
|
-
measurePerf
|
|
12189
|
+
measurePerf,
|
|
12190
|
+
rootDirectoryUrl: context.rootDirectoryUrl
|
|
12189
12191
|
}, null, " ")})`,
|
|
12190
12192
|
"injected-by": "jsenv:html_supervisor"
|
|
12191
12193
|
}));
|
|
12192
|
-
const [htmlSupervisorSetupFileReference] = referenceUtils.inject({
|
|
12194
|
+
const [htmlSupervisorSetupFileReference] = context.referenceUtils.inject({
|
|
12193
12195
|
type: "script_src",
|
|
12194
12196
|
expectedType: "js_classic",
|
|
12195
12197
|
specifier: htmlSupervisorSetupFileUrl
|
|
@@ -12776,8 +12778,6 @@ export default inlineContent.text`,
|
|
|
12776
12778
|
return [asJsonModule, asCssModule, asTextModule];
|
|
12777
12779
|
};
|
|
12778
12780
|
|
|
12779
|
-
const requireFromJsenv = createRequire(import.meta.url);
|
|
12780
|
-
|
|
12781
12781
|
const babelPluginPackagePath = requireFromJsenv.resolve("@jsenv/babel-plugins");
|
|
12782
12782
|
const babelPluginPackageUrl = pathToFileURL(babelPluginPackagePath);
|
|
12783
12783
|
const requireBabelPlugin = createRequire(babelPluginPackageUrl);
|
|
@@ -19338,8 +19338,7 @@ const rollupPluginJsenv = ({
|
|
|
19338
19338
|
data: {
|
|
19339
19339
|
generatedBy: "rollup",
|
|
19340
19340
|
bundleRelativeUrl: rollupFileInfo.fileName,
|
|
19341
|
-
usesImport: rollupFileInfo.imports.length > 0 || rollupFileInfo.dynamicImports.length > 0
|
|
19342
|
-
usesExport: rollupFileInfo.exports.length > 0
|
|
19341
|
+
usesImport: rollupFileInfo.imports.length > 0 || rollupFileInfo.dynamicImports.length > 0
|
|
19343
19342
|
},
|
|
19344
19343
|
contentType: "text/javascript",
|
|
19345
19344
|
content: rollupFileInfo.code,
|
|
@@ -20240,269 +20239,216 @@ const jsenvPluginDevSSEClient = () => {
|
|
|
20240
20239
|
};
|
|
20241
20240
|
};
|
|
20242
20241
|
|
|
20243
|
-
const createSSEService = ({
|
|
20244
|
-
serverEventCallbackList
|
|
20245
|
-
}) => {
|
|
20246
|
-
const destroyCallbackList = createCallbackListNotifiedOnce();
|
|
20247
|
-
const cache = [];
|
|
20248
|
-
const sseRoomLimit = 100;
|
|
20249
|
-
|
|
20250
|
-
const getOrCreateSSERoom = request => {
|
|
20251
|
-
const htmlFileRelativeUrl = request.ressource.slice(1);
|
|
20252
|
-
const cacheEntry = cache.find(cacheEntryCandidate => cacheEntryCandidate.htmlFileRelativeUrl === htmlFileRelativeUrl);
|
|
20253
|
-
|
|
20254
|
-
if (cacheEntry) {
|
|
20255
|
-
return cacheEntry.sseRoom;
|
|
20256
|
-
}
|
|
20257
|
-
|
|
20258
|
-
const sseRoom = createSSERoom({
|
|
20259
|
-
retryDuration: 2000,
|
|
20260
|
-
historyLength: 100,
|
|
20261
|
-
welcomeEventEnabled: true,
|
|
20262
|
-
effect: () => {
|
|
20263
|
-
return serverEventCallbackList.add(event => {
|
|
20264
|
-
sseRoom.sendEvent(event);
|
|
20265
|
-
});
|
|
20266
|
-
}
|
|
20267
|
-
});
|
|
20268
|
-
const removeSSECleanupCallback = destroyCallbackList.add(() => {
|
|
20269
|
-
removeSSECleanupCallback();
|
|
20270
|
-
sseRoom.close();
|
|
20271
|
-
});
|
|
20272
|
-
cache.push({
|
|
20273
|
-
htmlFileRelativeUrl,
|
|
20274
|
-
sseRoom,
|
|
20275
|
-
cleanup: () => {
|
|
20276
|
-
removeSSECleanupCallback();
|
|
20277
|
-
sseRoom.close();
|
|
20278
|
-
}
|
|
20279
|
-
});
|
|
20280
|
-
|
|
20281
|
-
if (cache.length >= sseRoomLimit) {
|
|
20282
|
-
const firstCacheEntry = cache.shift();
|
|
20283
|
-
firstCacheEntry.cleanup();
|
|
20284
|
-
}
|
|
20285
|
-
|
|
20286
|
-
return sseRoom;
|
|
20287
|
-
};
|
|
20288
|
-
|
|
20289
|
-
return {
|
|
20290
|
-
getOrCreateSSERoom,
|
|
20291
|
-
destroy: () => {
|
|
20292
|
-
destroyCallbackList.notify();
|
|
20293
|
-
}
|
|
20294
|
-
};
|
|
20295
|
-
};
|
|
20296
|
-
|
|
20297
20242
|
const jsenvPluginDevSSEServer = ({
|
|
20298
|
-
rootDirectoryUrl,
|
|
20299
|
-
urlGraph,
|
|
20300
20243
|
clientFileChangeCallbackList,
|
|
20301
20244
|
clientFilesPruneCallbackList
|
|
20302
20245
|
}) => {
|
|
20303
|
-
|
|
20304
|
-
|
|
20305
|
-
|
|
20306
|
-
|
|
20307
|
-
|
|
20308
|
-
|
|
20309
|
-
|
|
20310
|
-
|
|
20311
|
-
|
|
20312
|
-
|
|
20313
|
-
|
|
20314
|
-
|
|
20315
|
-
data: JSON.stringify({
|
|
20246
|
+
return {
|
|
20247
|
+
name: "jsenv:sse_server",
|
|
20248
|
+
appliesDuring: {
|
|
20249
|
+
dev: true
|
|
20250
|
+
},
|
|
20251
|
+
registerServerEvents: ({
|
|
20252
|
+
sendServerEvent
|
|
20253
|
+
}, {
|
|
20254
|
+
rootDirectoryUrl,
|
|
20255
|
+
urlGraph
|
|
20256
|
+
}) => {
|
|
20257
|
+
const notifyDeclined = ({
|
|
20316
20258
|
cause,
|
|
20317
|
-
|
|
20318
|
-
typeReason: reason,
|
|
20259
|
+
reason,
|
|
20319
20260
|
declinedBy
|
|
20320
|
-
})
|
|
20321
|
-
|
|
20322
|
-
|
|
20261
|
+
}) => {
|
|
20262
|
+
sendServerEvent({
|
|
20263
|
+
type: "reload",
|
|
20264
|
+
data: {
|
|
20265
|
+
cause,
|
|
20266
|
+
type: "full",
|
|
20267
|
+
typeReason: reason,
|
|
20268
|
+
declinedBy
|
|
20269
|
+
}
|
|
20270
|
+
});
|
|
20271
|
+
};
|
|
20323
20272
|
|
|
20324
|
-
|
|
20325
|
-
cause,
|
|
20326
|
-
reason,
|
|
20327
|
-
instructions
|
|
20328
|
-
}) => {
|
|
20329
|
-
serverEventCallbackList.notify({
|
|
20330
|
-
type: "reload",
|
|
20331
|
-
data: JSON.stringify({
|
|
20273
|
+
const notifyAccepted = ({
|
|
20332
20274
|
cause,
|
|
20333
|
-
|
|
20334
|
-
|
|
20335
|
-
|
|
20336
|
-
|
|
20337
|
-
|
|
20338
|
-
|
|
20339
|
-
|
|
20340
|
-
|
|
20341
|
-
|
|
20275
|
+
reason,
|
|
20276
|
+
instructions
|
|
20277
|
+
}) => {
|
|
20278
|
+
sendServerEvent({
|
|
20279
|
+
type: "reload",
|
|
20280
|
+
data: {
|
|
20281
|
+
cause,
|
|
20282
|
+
type: "hot",
|
|
20283
|
+
typeReason: reason,
|
|
20284
|
+
hotInstructions: instructions
|
|
20285
|
+
}
|
|
20286
|
+
});
|
|
20287
|
+
};
|
|
20342
20288
|
|
|
20343
|
-
|
|
20344
|
-
|
|
20345
|
-
|
|
20346
|
-
|
|
20347
|
-
|
|
20348
|
-
|
|
20349
|
-
|
|
20350
|
-
|
|
20351
|
-
|
|
20352
|
-
|
|
20353
|
-
|
|
20354
|
-
|
|
20289
|
+
const propagateUpdate = firstUrlInfo => {
|
|
20290
|
+
const iterate = (urlInfo, seen) => {
|
|
20291
|
+
if (urlInfo.data.hotAcceptSelf) {
|
|
20292
|
+
return {
|
|
20293
|
+
accepted: true,
|
|
20294
|
+
reason: urlInfo === firstUrlInfo ? `file accepts hot reload` : `a dependent file accepts hot reload`,
|
|
20295
|
+
instructions: [{
|
|
20296
|
+
type: urlInfo.type,
|
|
20297
|
+
boundary: urlToRelativeUrl(urlInfo.url, rootDirectoryUrl),
|
|
20298
|
+
acceptedBy: urlToRelativeUrl(urlInfo.url, rootDirectoryUrl)
|
|
20299
|
+
}]
|
|
20300
|
+
};
|
|
20301
|
+
}
|
|
20355
20302
|
|
|
20356
|
-
|
|
20357
|
-
|
|
20358
|
-
|
|
20359
|
-
|
|
20303
|
+
const {
|
|
20304
|
+
dependents
|
|
20305
|
+
} = urlInfo;
|
|
20306
|
+
const instructions = [];
|
|
20360
20307
|
|
|
20361
|
-
|
|
20362
|
-
|
|
20308
|
+
for (const dependentUrl of dependents) {
|
|
20309
|
+
const dependentUrlInfo = urlGraph.getUrlInfo(dependentUrl);
|
|
20363
20310
|
|
|
20364
|
-
|
|
20365
|
-
|
|
20366
|
-
|
|
20367
|
-
|
|
20368
|
-
|
|
20369
|
-
|
|
20370
|
-
|
|
20311
|
+
if (dependentUrlInfo.data.hotDecline) {
|
|
20312
|
+
return {
|
|
20313
|
+
declined: true,
|
|
20314
|
+
reason: `a dependent file declines hot reload`,
|
|
20315
|
+
declinedBy: dependentUrl
|
|
20316
|
+
};
|
|
20317
|
+
}
|
|
20371
20318
|
|
|
20372
|
-
|
|
20373
|
-
|
|
20374
|
-
|
|
20319
|
+
const {
|
|
20320
|
+
hotAcceptDependencies = []
|
|
20321
|
+
} = dependentUrlInfo.data;
|
|
20322
|
+
|
|
20323
|
+
if (hotAcceptDependencies.includes(urlInfo.url)) {
|
|
20324
|
+
instructions.push({
|
|
20325
|
+
type: dependentUrlInfo.type,
|
|
20326
|
+
boundary: urlToRelativeUrl(dependentUrl, rootDirectoryUrl),
|
|
20327
|
+
acceptedBy: urlToRelativeUrl(urlInfo.url, rootDirectoryUrl)
|
|
20328
|
+
});
|
|
20329
|
+
continue;
|
|
20330
|
+
}
|
|
20375
20331
|
|
|
20376
|
-
|
|
20377
|
-
|
|
20378
|
-
|
|
20379
|
-
|
|
20380
|
-
|
|
20381
|
-
|
|
20382
|
-
|
|
20383
|
-
}
|
|
20332
|
+
if (seen.includes(dependentUrl)) {
|
|
20333
|
+
return {
|
|
20334
|
+
declined: true,
|
|
20335
|
+
reason: "circular dependency",
|
|
20336
|
+
declinedBy: urlToRelativeUrl(dependentUrl, rootDirectoryUrl)
|
|
20337
|
+
};
|
|
20338
|
+
}
|
|
20384
20339
|
|
|
20385
|
-
|
|
20386
|
-
return {
|
|
20387
|
-
declined: true,
|
|
20388
|
-
reason: "circular dependency",
|
|
20389
|
-
declinedBy: urlToRelativeUrl(dependentUrl, rootDirectoryUrl)
|
|
20390
|
-
};
|
|
20391
|
-
}
|
|
20340
|
+
const dependentPropagationResult = iterate(dependentUrlInfo, [...seen, dependentUrl]);
|
|
20392
20341
|
|
|
20393
|
-
|
|
20342
|
+
if (dependentPropagationResult.accepted) {
|
|
20343
|
+
instructions.push(...dependentPropagationResult.instructions);
|
|
20344
|
+
continue;
|
|
20345
|
+
}
|
|
20394
20346
|
|
|
20395
|
-
|
|
20396
|
-
|
|
20397
|
-
|
|
20398
|
-
|
|
20347
|
+
if ( // declined explicitely by an other file, it must decline the whole update
|
|
20348
|
+
dependentPropagationResult.declinedBy) {
|
|
20349
|
+
return dependentPropagationResult;
|
|
20350
|
+
} // declined by absence of boundary, we can keep searching
|
|
20399
20351
|
|
|
20400
|
-
if ( // declined explicitely by an other file, it must decline the whole update
|
|
20401
|
-
dependentPropagationResult.declinedBy) {
|
|
20402
|
-
return dependentPropagationResult;
|
|
20403
|
-
} // declined by absence of boundary, we can keep searching
|
|
20404
20352
|
|
|
20353
|
+
continue;
|
|
20354
|
+
}
|
|
20405
20355
|
|
|
20406
|
-
|
|
20407
|
-
|
|
20356
|
+
if (instructions.length === 0) {
|
|
20357
|
+
return {
|
|
20358
|
+
declined: true,
|
|
20359
|
+
reason: `there is no file accepting hot reload while propagating update`
|
|
20360
|
+
};
|
|
20361
|
+
}
|
|
20408
20362
|
|
|
20409
|
-
|
|
20410
|
-
|
|
20411
|
-
|
|
20412
|
-
|
|
20363
|
+
return {
|
|
20364
|
+
accepted: true,
|
|
20365
|
+
reason: `${instructions.length} dependent file(s) accepts hot reload`,
|
|
20366
|
+
instructions
|
|
20367
|
+
};
|
|
20413
20368
|
};
|
|
20414
|
-
}
|
|
20415
20369
|
|
|
20416
|
-
|
|
20417
|
-
|
|
20418
|
-
reason: `${instructions.length} dependent file(s) accepts hot reload`,
|
|
20419
|
-
instructions
|
|
20370
|
+
const seen = [];
|
|
20371
|
+
return iterate(firstUrlInfo, seen);
|
|
20420
20372
|
};
|
|
20421
|
-
};
|
|
20422
20373
|
|
|
20423
|
-
|
|
20424
|
-
|
|
20425
|
-
|
|
20426
|
-
|
|
20427
|
-
|
|
20428
|
-
url,
|
|
20429
|
-
event
|
|
20430
|
-
}) => {
|
|
20431
|
-
const urlInfo = urlGraph.getUrlInfo(url); // file not part of dependency graph
|
|
20374
|
+
clientFileChangeCallbackList.push(({
|
|
20375
|
+
url,
|
|
20376
|
+
event
|
|
20377
|
+
}) => {
|
|
20378
|
+
const urlInfo = urlGraph.getUrlInfo(url); // file not part of dependency graph
|
|
20432
20379
|
|
|
20433
|
-
|
|
20434
|
-
|
|
20435
|
-
|
|
20380
|
+
if (!urlInfo) {
|
|
20381
|
+
return;
|
|
20382
|
+
}
|
|
20436
20383
|
|
|
20437
|
-
|
|
20438
|
-
|
|
20384
|
+
const relativeUrl = urlToRelativeUrl(url, rootDirectoryUrl);
|
|
20385
|
+
const hotUpdate = propagateUpdate(urlInfo);
|
|
20439
20386
|
|
|
20440
|
-
|
|
20441
|
-
|
|
20442
|
-
|
|
20443
|
-
|
|
20444
|
-
|
|
20445
|
-
|
|
20446
|
-
|
|
20447
|
-
|
|
20448
|
-
|
|
20449
|
-
|
|
20450
|
-
|
|
20387
|
+
if (hotUpdate.declined) {
|
|
20388
|
+
notifyDeclined({
|
|
20389
|
+
cause: `${relativeUrl} ${event}`,
|
|
20390
|
+
reason: hotUpdate.reason,
|
|
20391
|
+
declinedBy: hotUpdate.declinedBy
|
|
20392
|
+
});
|
|
20393
|
+
} else {
|
|
20394
|
+
notifyAccepted({
|
|
20395
|
+
cause: `${relativeUrl} ${event}`,
|
|
20396
|
+
reason: hotUpdate.reason,
|
|
20397
|
+
instructions: hotUpdate.instructions
|
|
20398
|
+
});
|
|
20399
|
+
}
|
|
20451
20400
|
});
|
|
20452
|
-
|
|
20453
|
-
|
|
20454
|
-
|
|
20455
|
-
|
|
20456
|
-
|
|
20457
|
-
|
|
20458
|
-
|
|
20459
|
-
|
|
20460
|
-
|
|
20401
|
+
clientFilesPruneCallbackList.push(({
|
|
20402
|
+
prunedUrlInfos,
|
|
20403
|
+
firstUrlInfo
|
|
20404
|
+
}) => {
|
|
20405
|
+
const mainHotUpdate = propagateUpdate(firstUrlInfo);
|
|
20406
|
+
const cause = `following files are no longer referenced: ${prunedUrlInfos.map(prunedUrlInfo => urlToRelativeUrl(prunedUrlInfo.url, rootDirectoryUrl))}`; // now check if we can hot update the main ressource
|
|
20407
|
+
// then if we can hot update all dependencies
|
|
20408
|
+
|
|
20409
|
+
if (mainHotUpdate.declined) {
|
|
20410
|
+
notifyDeclined({
|
|
20411
|
+
cause,
|
|
20412
|
+
reason: mainHotUpdate.reason,
|
|
20413
|
+
declinedBy: mainHotUpdate.declinedBy
|
|
20414
|
+
});
|
|
20415
|
+
return;
|
|
20416
|
+
} // main can hot update
|
|
20461
20417
|
|
|
20462
|
-
if (mainHotUpdate.declined) {
|
|
20463
|
-
notifyDeclined({
|
|
20464
|
-
cause,
|
|
20465
|
-
reason: mainHotUpdate.reason,
|
|
20466
|
-
declinedBy: mainHotUpdate.declinedBy
|
|
20467
|
-
});
|
|
20468
|
-
return;
|
|
20469
|
-
} // main can hot update
|
|
20470
20418
|
|
|
20419
|
+
let i = 0;
|
|
20420
|
+
const instructions = [];
|
|
20471
20421
|
|
|
20472
|
-
|
|
20473
|
-
|
|
20422
|
+
while (i < prunedUrlInfos.length) {
|
|
20423
|
+
const prunedUrlInfo = prunedUrlInfos[i++];
|
|
20424
|
+
|
|
20425
|
+
if (prunedUrlInfo.data.hotDecline) {
|
|
20426
|
+
notifyDeclined({
|
|
20427
|
+
cause,
|
|
20428
|
+
reason: `a pruned file declines hot reload`,
|
|
20429
|
+
declinedBy: urlToRelativeUrl(prunedUrlInfo.url, rootDirectoryUrl)
|
|
20430
|
+
});
|
|
20431
|
+
return;
|
|
20432
|
+
}
|
|
20474
20433
|
|
|
20475
|
-
|
|
20476
|
-
|
|
20434
|
+
instructions.push({
|
|
20435
|
+
type: "prune",
|
|
20436
|
+
boundary: urlToRelativeUrl(prunedUrlInfo.url, rootDirectoryUrl),
|
|
20437
|
+
acceptedBy: urlToRelativeUrl(firstUrlInfo.url, rootDirectoryUrl)
|
|
20438
|
+
});
|
|
20439
|
+
}
|
|
20477
20440
|
|
|
20478
|
-
|
|
20479
|
-
notifyDeclined({
|
|
20441
|
+
notifyAccepted({
|
|
20480
20442
|
cause,
|
|
20481
|
-
reason:
|
|
20482
|
-
|
|
20443
|
+
reason: mainHotUpdate.reason,
|
|
20444
|
+
instructions
|
|
20483
20445
|
});
|
|
20484
|
-
return;
|
|
20485
|
-
}
|
|
20486
|
-
|
|
20487
|
-
instructions.push({
|
|
20488
|
-
type: "prune",
|
|
20489
|
-
boundary: urlToRelativeUrl(prunedUrlInfo.url, rootDirectoryUrl),
|
|
20490
|
-
acceptedBy: urlToRelativeUrl(firstUrlInfo.url, rootDirectoryUrl)
|
|
20491
20446
|
});
|
|
20492
|
-
}
|
|
20493
|
-
|
|
20494
|
-
notifyAccepted({
|
|
20495
|
-
cause,
|
|
20496
|
-
reason: mainHotUpdate.reason,
|
|
20497
|
-
instructions
|
|
20498
|
-
});
|
|
20499
|
-
});
|
|
20500
|
-
return {
|
|
20501
|
-
name: "jsenv:sse_server",
|
|
20502
|
-
appliesDuring: {
|
|
20503
|
-
dev: true
|
|
20504
20447
|
},
|
|
20505
|
-
serve: request
|
|
20448
|
+
serve: (request, {
|
|
20449
|
+
rootDirectoryUrl,
|
|
20450
|
+
urlGraph
|
|
20451
|
+
}) => {
|
|
20506
20452
|
if (request.ressource === "/__graph__") {
|
|
20507
20453
|
const graphJson = JSON.stringify(urlGraph.toJSON(rootDirectoryUrl));
|
|
20508
20454
|
return {
|
|
@@ -20515,26 +20461,12 @@ const jsenvPluginDevSSEServer = ({
|
|
|
20515
20461
|
};
|
|
20516
20462
|
}
|
|
20517
20463
|
|
|
20518
|
-
|
|
20519
|
-
|
|
20520
|
-
|
|
20521
|
-
|
|
20522
|
-
if (accept && accept.includes("text/event-stream")) {
|
|
20523
|
-
const room = sseService.getOrCreateSSERoom(request);
|
|
20524
|
-
return room.join(request);
|
|
20525
|
-
}
|
|
20526
|
-
|
|
20527
|
-
return null;
|
|
20528
|
-
},
|
|
20529
|
-
destroy: () => {
|
|
20530
|
-
sseService.destroy();
|
|
20531
|
-
}
|
|
20532
|
-
};
|
|
20533
|
-
};
|
|
20464
|
+
return null;
|
|
20465
|
+
}
|
|
20466
|
+
};
|
|
20467
|
+
};
|
|
20534
20468
|
|
|
20535
20469
|
const jsenvPluginAutoreload = ({
|
|
20536
|
-
rootDirectoryUrl,
|
|
20537
|
-
urlGraph,
|
|
20538
20470
|
scenario,
|
|
20539
20471
|
clientFileChangeCallbackList,
|
|
20540
20472
|
clientFilesPruneCallbackList
|
|
@@ -20544,8 +20476,6 @@ const jsenvPluginAutoreload = ({
|
|
|
20544
20476
|
}
|
|
20545
20477
|
|
|
20546
20478
|
return [jsenvPluginHmr(), jsenvPluginDevSSEClient(), jsenvPluginDevSSEServer({
|
|
20547
|
-
rootDirectoryUrl,
|
|
20548
|
-
urlGraph,
|
|
20549
20479
|
clientFileChangeCallbackList,
|
|
20550
20480
|
clientFilesPruneCallbackList
|
|
20551
20481
|
})];
|
|
@@ -20634,8 +20564,6 @@ const getCorePlugins = ({
|
|
|
20634
20564
|
}), jsenvPluginUrlResolution(), jsenvPluginUrlVersion(), jsenvPluginCommonJsGlobals(), jsenvPluginImportMetaScenarios(), jsenvPluginNodeRuntime({
|
|
20635
20565
|
runtimeCompat
|
|
20636
20566
|
}), jsenvPluginBundling(bundling), jsenvPluginMinification(minification), jsenvPluginImportMetaHot(), ...(clientAutoreload ? [jsenvPluginAutoreload({ ...clientAutoreload,
|
|
20637
|
-
rootDirectoryUrl,
|
|
20638
|
-
urlGraph,
|
|
20639
20567
|
scenario,
|
|
20640
20568
|
clientFileChangeCallbackList,
|
|
20641
20569
|
clientFilesPruneCallbackList
|
|
@@ -20722,15 +20650,15 @@ const createUrlGraph = ({
|
|
|
20722
20650
|
clientFileChangeCallbackList,
|
|
20723
20651
|
clientFilesPruneCallbackList
|
|
20724
20652
|
} = {}) => {
|
|
20725
|
-
const
|
|
20653
|
+
const urlInfoMap = new Map();
|
|
20726
20654
|
|
|
20727
|
-
const getUrlInfo = url =>
|
|
20655
|
+
const getUrlInfo = url => urlInfoMap.get(url);
|
|
20728
20656
|
|
|
20729
20657
|
const deleteUrlInfo = url => {
|
|
20730
|
-
const urlInfo =
|
|
20658
|
+
const urlInfo = urlInfoMap.get(url);
|
|
20731
20659
|
|
|
20732
20660
|
if (urlInfo) {
|
|
20733
|
-
delete
|
|
20661
|
+
urlInfoMap.delete(url);
|
|
20734
20662
|
|
|
20735
20663
|
if (urlInfo.sourcemapReference) {
|
|
20736
20664
|
deleteUrlInfo(urlInfo.sourcemapReference.url);
|
|
@@ -20739,15 +20667,15 @@ const createUrlGraph = ({
|
|
|
20739
20667
|
};
|
|
20740
20668
|
|
|
20741
20669
|
const reuseOrCreateUrlInfo = url => {
|
|
20742
|
-
const existingUrlInfo =
|
|
20670
|
+
const existingUrlInfo = getUrlInfo(url);
|
|
20743
20671
|
if (existingUrlInfo) return existingUrlInfo;
|
|
20744
20672
|
const urlInfo = createUrlInfo(url);
|
|
20745
|
-
|
|
20673
|
+
urlInfoMap.set(url, urlInfo);
|
|
20746
20674
|
return urlInfo;
|
|
20747
20675
|
};
|
|
20748
20676
|
|
|
20749
20677
|
const inferReference = (specifier, parentUrl) => {
|
|
20750
|
-
const parentUrlInfo =
|
|
20678
|
+
const parentUrlInfo = getUrlInfo(parentUrl);
|
|
20751
20679
|
|
|
20752
20680
|
if (!parentUrlInfo) {
|
|
20753
20681
|
return null;
|
|
@@ -20760,7 +20688,7 @@ const createUrlGraph = ({
|
|
|
20760
20688
|
};
|
|
20761
20689
|
|
|
20762
20690
|
const findDependent = (url, predicate) => {
|
|
20763
|
-
const urlInfo =
|
|
20691
|
+
const urlInfo = getUrlInfo(url);
|
|
20764
20692
|
|
|
20765
20693
|
if (!urlInfo) {
|
|
20766
20694
|
return null;
|
|
@@ -20768,7 +20696,7 @@ const createUrlGraph = ({
|
|
|
20768
20696
|
|
|
20769
20697
|
const visitDependents = urlInfo => {
|
|
20770
20698
|
for (const dependentUrl of urlInfo.dependents) {
|
|
20771
|
-
const dependent =
|
|
20699
|
+
const dependent = getUrlInfo(dependentUrl);
|
|
20772
20700
|
|
|
20773
20701
|
if (predicate(dependent)) {
|
|
20774
20702
|
return dependent;
|
|
@@ -20818,7 +20746,7 @@ const createUrlGraph = ({
|
|
|
20818
20746
|
const removeDependencies = (urlInfo, urlsToPrune) => {
|
|
20819
20747
|
urlsToPrune.forEach(urlToPrune => {
|
|
20820
20748
|
urlInfo.dependencies.delete(urlToPrune);
|
|
20821
|
-
const dependency =
|
|
20749
|
+
const dependency = getUrlInfo(urlToPrune);
|
|
20822
20750
|
|
|
20823
20751
|
if (!dependency) {
|
|
20824
20752
|
return;
|
|
@@ -20858,7 +20786,7 @@ const createUrlGraph = ({
|
|
|
20858
20786
|
clientFileChangeCallbackList.push(({
|
|
20859
20787
|
url
|
|
20860
20788
|
}) => {
|
|
20861
|
-
const urlInfo =
|
|
20789
|
+
const urlInfo = getUrlInfo(url);
|
|
20862
20790
|
|
|
20863
20791
|
if (urlInfo) {
|
|
20864
20792
|
considerModified(urlInfo, Date.now());
|
|
@@ -20878,7 +20806,7 @@ const createUrlGraph = ({
|
|
|
20878
20806
|
urlInfo.modifiedTimestamp = modifiedTimestamp;
|
|
20879
20807
|
urlInfo.contentEtag = undefined;
|
|
20880
20808
|
urlInfo.dependents.forEach(dependentUrl => {
|
|
20881
|
-
const dependentUrlInfo =
|
|
20809
|
+
const dependentUrlInfo = getUrlInfo(dependentUrl);
|
|
20882
20810
|
const {
|
|
20883
20811
|
hotAcceptDependencies = []
|
|
20884
20812
|
} = dependentUrlInfo.data;
|
|
@@ -20887,6 +20815,13 @@ const createUrlGraph = ({
|
|
|
20887
20815
|
iterate(dependentUrlInfo);
|
|
20888
20816
|
}
|
|
20889
20817
|
});
|
|
20818
|
+
urlInfo.dependencies.forEach(dependencyUrl => {
|
|
20819
|
+
const dependencyUrlInfo = getUrlInfo(dependencyUrl);
|
|
20820
|
+
|
|
20821
|
+
if (dependencyUrlInfo.isInline) {
|
|
20822
|
+
iterate(dependencyUrlInfo);
|
|
20823
|
+
}
|
|
20824
|
+
});
|
|
20890
20825
|
};
|
|
20891
20826
|
|
|
20892
20827
|
iterate(urlInfo);
|
|
@@ -20908,7 +20843,7 @@ const createUrlGraph = ({
|
|
|
20908
20843
|
};
|
|
20909
20844
|
|
|
20910
20845
|
return {
|
|
20911
|
-
|
|
20846
|
+
urlInfoMap,
|
|
20912
20847
|
reuseOrCreateUrlInfo,
|
|
20913
20848
|
getUrlInfo,
|
|
20914
20849
|
deleteUrlInfo,
|
|
@@ -20917,13 +20852,20 @@ const createUrlGraph = ({
|
|
|
20917
20852
|
updateReferences,
|
|
20918
20853
|
considerModified,
|
|
20919
20854
|
getRelatedUrlInfos,
|
|
20855
|
+
toObject: () => {
|
|
20856
|
+
const data = {};
|
|
20857
|
+
urlInfoMap.forEach(urlInfo => {
|
|
20858
|
+
data[urlInfo.url] = urlInfo;
|
|
20859
|
+
});
|
|
20860
|
+
return data;
|
|
20861
|
+
},
|
|
20920
20862
|
toJSON: rootDirectoryUrl => {
|
|
20921
20863
|
const data = {};
|
|
20922
|
-
|
|
20923
|
-
const dependencyUrls = Array.from(
|
|
20864
|
+
urlInfoMap.forEach(urlInfo => {
|
|
20865
|
+
const dependencyUrls = Array.from(urlInfo.dependencies);
|
|
20924
20866
|
|
|
20925
20867
|
if (dependencyUrls.length) {
|
|
20926
|
-
const relativeUrl = urlToRelativeUrl(url, rootDirectoryUrl);
|
|
20868
|
+
const relativeUrl = urlToRelativeUrl(urlInfo.url, rootDirectoryUrl);
|
|
20927
20869
|
data[relativeUrl] = dependencyUrls.map(dependencyUrl => urlToRelativeUrl(dependencyUrl, rootDirectoryUrl));
|
|
20928
20870
|
}
|
|
20929
20871
|
});
|
|
@@ -21508,7 +21450,7 @@ const createResolveUrlError = ({
|
|
|
21508
21450
|
reason,
|
|
21509
21451
|
...details,
|
|
21510
21452
|
"specifier": `"${reference.specifier}"`,
|
|
21511
|
-
"specifier trace": reference.trace,
|
|
21453
|
+
"specifier trace": reference.trace.message,
|
|
21512
21454
|
...detailsFromPluginController(pluginController)
|
|
21513
21455
|
}));
|
|
21514
21456
|
resolveError.name = "RESOLVE_URL_ERROR";
|
|
@@ -21539,17 +21481,21 @@ const createFetchUrlContentError = ({
|
|
|
21539
21481
|
reason,
|
|
21540
21482
|
...details
|
|
21541
21483
|
}) => {
|
|
21542
|
-
const
|
|
21484
|
+
const fetchError = new Error(createDetailedMessage$1(`Failed to fetch url content`, {
|
|
21543
21485
|
reason,
|
|
21544
21486
|
...details,
|
|
21545
21487
|
"url": urlInfo.url,
|
|
21546
|
-
"url reference trace": reference.trace,
|
|
21488
|
+
"url reference trace": reference.trace.message,
|
|
21547
21489
|
...detailsFromPluginController(pluginController)
|
|
21548
21490
|
}));
|
|
21549
|
-
|
|
21550
|
-
|
|
21551
|
-
|
|
21552
|
-
|
|
21491
|
+
fetchError.name = "FETCH_URL_CONTENT_ERROR";
|
|
21492
|
+
fetchError.code = code;
|
|
21493
|
+
fetchError.reason = reason;
|
|
21494
|
+
fetchError.url = reference.trace.url;
|
|
21495
|
+
fetchError.line = reference.trace.line;
|
|
21496
|
+
fetchError.column = reference.trace.column;
|
|
21497
|
+
fetchError.contentFrame = reference.trace.message;
|
|
21498
|
+
return fetchError;
|
|
21553
21499
|
};
|
|
21554
21500
|
|
|
21555
21501
|
if (error.code === "EPERM") {
|
|
@@ -21593,12 +21539,42 @@ const createTransformUrlContentError = ({
|
|
|
21593
21539
|
reason,
|
|
21594
21540
|
...details,
|
|
21595
21541
|
"url": urlInfo.url,
|
|
21596
|
-
"url reference trace": reference.trace,
|
|
21542
|
+
"url reference trace": reference.trace.message,
|
|
21597
21543
|
...detailsFromPluginController(pluginController)
|
|
21598
21544
|
}));
|
|
21599
21545
|
transformError.name = "TRANSFORM_URL_CONTENT_ERROR";
|
|
21600
21546
|
transformError.code = code;
|
|
21601
21547
|
transformError.reason = reason;
|
|
21548
|
+
transformError.url = reference.trace.url;
|
|
21549
|
+
transformError.line = reference.trace.line;
|
|
21550
|
+
transformError.column = reference.trace.column;
|
|
21551
|
+
transformError.stack = error.stack;
|
|
21552
|
+
transformError.contentFrame = reference.trace.message;
|
|
21553
|
+
|
|
21554
|
+
if (code === "PARSE_ERROR") {
|
|
21555
|
+
transformError.reason = error.message;
|
|
21556
|
+
|
|
21557
|
+
if (urlInfo.isInline) {
|
|
21558
|
+
transformError.line = reference.trace.line + error.line - 1;
|
|
21559
|
+
transformError.column = reference.trace.column + error.column;
|
|
21560
|
+
transformError.contentFrame = stringifyUrlSite({
|
|
21561
|
+
url: urlInfo.inlineUrlSite.url,
|
|
21562
|
+
line: transformError.line,
|
|
21563
|
+
column: transformError.column,
|
|
21564
|
+
content: urlInfo.inlineUrlSite.content
|
|
21565
|
+
});
|
|
21566
|
+
} else {
|
|
21567
|
+
transformError.line = error.line;
|
|
21568
|
+
transformError.column = error.column;
|
|
21569
|
+
transformError.contentFrame = stringifyUrlSite({
|
|
21570
|
+
url: urlInfo.url,
|
|
21571
|
+
line: transformError.line,
|
|
21572
|
+
column: transformError.column,
|
|
21573
|
+
content: urlInfo.content
|
|
21574
|
+
});
|
|
21575
|
+
}
|
|
21576
|
+
}
|
|
21577
|
+
|
|
21602
21578
|
return transformError;
|
|
21603
21579
|
};
|
|
21604
21580
|
|
|
@@ -21617,7 +21593,7 @@ const createFinalizeUrlContentError = ({
|
|
|
21617
21593
|
"reason": `An error occured during "finalizeUrlContent"`,
|
|
21618
21594
|
...detailsFromValueThrown(error),
|
|
21619
21595
|
"url": urlInfo.url,
|
|
21620
|
-
"url reference trace": reference.trace,
|
|
21596
|
+
"url reference trace": reference.trace.message,
|
|
21621
21597
|
...detailsFromPluginController(pluginController)
|
|
21622
21598
|
}));
|
|
21623
21599
|
finalizeError.name = "FINALIZE_URL_CONTENT_ERROR";
|
|
@@ -22012,7 +21988,10 @@ const createKitchen = ({
|
|
|
22012
21988
|
specifier
|
|
22013
21989
|
}) => {
|
|
22014
21990
|
const sourcemapReference = createReference({
|
|
22015
|
-
trace:
|
|
21991
|
+
trace: {
|
|
21992
|
+
message: `sourcemap comment placeholder`,
|
|
21993
|
+
url: urlInfo.url
|
|
21994
|
+
},
|
|
22016
21995
|
type: "sourcemap_comment",
|
|
22017
21996
|
subtype: urlInfo.contentType === "text/javascript" ? "js" : "css",
|
|
22018
21997
|
parentUrl: urlInfo.url,
|
|
@@ -22029,13 +22008,14 @@ const createKitchen = ({
|
|
|
22029
22008
|
specifierLine,
|
|
22030
22009
|
specifierColumn
|
|
22031
22010
|
}) => {
|
|
22011
|
+
const sourcemapUrlSite = adjustUrlSite(urlInfo, {
|
|
22012
|
+
urlGraph,
|
|
22013
|
+
url: urlInfo.url,
|
|
22014
|
+
line: specifierLine,
|
|
22015
|
+
column: specifierColumn
|
|
22016
|
+
});
|
|
22032
22017
|
const sourcemapReference = createReference({
|
|
22033
|
-
trace:
|
|
22034
|
-
urlGraph,
|
|
22035
|
-
url: urlInfo.url,
|
|
22036
|
-
line: specifierLine,
|
|
22037
|
-
column: specifierColumn
|
|
22038
|
-
})),
|
|
22018
|
+
trace: traceFromUrlSite(sourcemapUrlSite),
|
|
22039
22019
|
type,
|
|
22040
22020
|
parentUrl: urlInfo.url,
|
|
22041
22021
|
specifier,
|
|
@@ -22058,7 +22038,7 @@ const createKitchen = ({
|
|
|
22058
22038
|
if (!fetchUrlContentReturnValue) {
|
|
22059
22039
|
logger.warn(createDetailedMessage$1(`no plugin has handled url during "fetchUrlContent" hook -> url will be ignored`, {
|
|
22060
22040
|
"url": urlInfo.url,
|
|
22061
|
-
"url reference trace": reference.trace
|
|
22041
|
+
"url reference trace": reference.trace.message
|
|
22062
22042
|
}));
|
|
22063
22043
|
return;
|
|
22064
22044
|
}
|
|
@@ -22215,7 +22195,7 @@ const createKitchen = ({
|
|
|
22215
22195
|
...rest
|
|
22216
22196
|
}) => {
|
|
22217
22197
|
if (trace === undefined) {
|
|
22218
|
-
trace =
|
|
22198
|
+
trace = traceFromUrlSite(adjustUrlSite(urlInfo, {
|
|
22219
22199
|
urlGraph,
|
|
22220
22200
|
url: urlInfo.url,
|
|
22221
22201
|
line: rest.specifierLine,
|
|
@@ -22231,22 +22211,22 @@ const createKitchen = ({
|
|
|
22231
22211
|
},
|
|
22232
22212
|
foundInline: ({
|
|
22233
22213
|
isOriginalPosition,
|
|
22234
|
-
|
|
22235
|
-
|
|
22214
|
+
specifierLine,
|
|
22215
|
+
specifierColumn,
|
|
22236
22216
|
...rest
|
|
22237
22217
|
}) => {
|
|
22238
22218
|
const parentUrl = isOriginalPosition ? urlInfo.url : urlInfo.generatedUrl;
|
|
22239
22219
|
const parentContent = isOriginalPosition ? urlInfo.originalContent : urlInfo.content;
|
|
22240
22220
|
return addReference({
|
|
22241
|
-
trace:
|
|
22221
|
+
trace: traceFromUrlSite({
|
|
22242
22222
|
url: parentUrl,
|
|
22243
22223
|
content: parentContent,
|
|
22244
|
-
line,
|
|
22245
|
-
column
|
|
22224
|
+
line: specifierLine,
|
|
22225
|
+
column: specifierColumn
|
|
22246
22226
|
}),
|
|
22247
22227
|
isOriginalPosition,
|
|
22248
|
-
|
|
22249
|
-
|
|
22228
|
+
specifierLine,
|
|
22229
|
+
specifierColumn,
|
|
22250
22230
|
isInline: true,
|
|
22251
22231
|
...rest
|
|
22252
22232
|
});
|
|
@@ -22284,7 +22264,7 @@ const createKitchen = ({
|
|
|
22284
22264
|
const parentUrl = isOriginalPosition ? urlInfo.url : urlInfo.generatedUrl;
|
|
22285
22265
|
const parentContent = isOriginalPosition ? urlInfo.originalContent : urlInfo.content;
|
|
22286
22266
|
return referenceUtils.update(reference, {
|
|
22287
|
-
trace:
|
|
22267
|
+
trace: traceFromUrlSite({
|
|
22288
22268
|
url: parentUrl,
|
|
22289
22269
|
content: parentContent,
|
|
22290
22270
|
line: specifierLine,
|
|
@@ -22309,7 +22289,7 @@ const createKitchen = ({
|
|
|
22309
22289
|
line,
|
|
22310
22290
|
column
|
|
22311
22291
|
} = getCallerPosition();
|
|
22312
|
-
trace =
|
|
22292
|
+
trace = traceFromUrlSite({
|
|
22313
22293
|
url,
|
|
22314
22294
|
line,
|
|
22315
22295
|
column
|
|
@@ -22518,6 +22498,15 @@ const memoizeCook = cook => {
|
|
|
22518
22498
|
};
|
|
22519
22499
|
};
|
|
22520
22500
|
|
|
22501
|
+
const traceFromUrlSite = urlSite => {
|
|
22502
|
+
return {
|
|
22503
|
+
message: stringifyUrlSite(urlSite),
|
|
22504
|
+
url: urlSite.url,
|
|
22505
|
+
line: urlSite.line,
|
|
22506
|
+
column: urlSite.column
|
|
22507
|
+
};
|
|
22508
|
+
};
|
|
22509
|
+
|
|
22521
22510
|
const applyReferenceEffectsOnUrlInfo = (reference, urlInfo, context) => {
|
|
22522
22511
|
if (reference.shouldHandle) {
|
|
22523
22512
|
urlInfo.shouldHandle = true;
|
|
@@ -22746,6 +22735,60 @@ const determineFileUrlForOutDirectory = ({
|
|
|
22746
22735
|
// }
|
|
22747
22736
|
// }
|
|
22748
22737
|
|
|
22738
|
+
const createSSEService = ({
|
|
22739
|
+
serverEventCallbackList
|
|
22740
|
+
}) => {
|
|
22741
|
+
const destroyCallbackList = createCallbackListNotifiedOnce();
|
|
22742
|
+
const cache = [];
|
|
22743
|
+
const sseRoomLimit = 100;
|
|
22744
|
+
|
|
22745
|
+
const getOrCreateSSERoom = request => {
|
|
22746
|
+
const htmlFileRelativeUrl = request.ressource.slice(1);
|
|
22747
|
+
const cacheEntry = cache.find(cacheEntryCandidate => cacheEntryCandidate.htmlFileRelativeUrl === htmlFileRelativeUrl);
|
|
22748
|
+
|
|
22749
|
+
if (cacheEntry) {
|
|
22750
|
+
return cacheEntry.sseRoom;
|
|
22751
|
+
}
|
|
22752
|
+
|
|
22753
|
+
const sseRoom = createSSERoom({
|
|
22754
|
+
retryDuration: 2000,
|
|
22755
|
+
historyLength: 100,
|
|
22756
|
+
welcomeEventEnabled: true,
|
|
22757
|
+
effect: () => {
|
|
22758
|
+
return serverEventCallbackList.add(event => {
|
|
22759
|
+
sseRoom.sendEvent(event);
|
|
22760
|
+
});
|
|
22761
|
+
}
|
|
22762
|
+
});
|
|
22763
|
+
const removeSSECleanupCallback = destroyCallbackList.add(() => {
|
|
22764
|
+
removeSSECleanupCallback();
|
|
22765
|
+
sseRoom.close();
|
|
22766
|
+
});
|
|
22767
|
+
cache.push({
|
|
22768
|
+
htmlFileRelativeUrl,
|
|
22769
|
+
sseRoom,
|
|
22770
|
+
cleanup: () => {
|
|
22771
|
+
removeSSECleanupCallback();
|
|
22772
|
+
sseRoom.close();
|
|
22773
|
+
}
|
|
22774
|
+
});
|
|
22775
|
+
|
|
22776
|
+
if (cache.length >= sseRoomLimit) {
|
|
22777
|
+
const firstCacheEntry = cache.shift();
|
|
22778
|
+
firstCacheEntry.cleanup();
|
|
22779
|
+
}
|
|
22780
|
+
|
|
22781
|
+
return sseRoom;
|
|
22782
|
+
};
|
|
22783
|
+
|
|
22784
|
+
return {
|
|
22785
|
+
getOrCreateSSERoom,
|
|
22786
|
+
destroy: () => {
|
|
22787
|
+
destroyCallbackList.notify();
|
|
22788
|
+
}
|
|
22789
|
+
};
|
|
22790
|
+
};
|
|
22791
|
+
|
|
22749
22792
|
const memoizeByFirstArgument = compute => {
|
|
22750
22793
|
const urlCache = new Map();
|
|
22751
22794
|
|
|
@@ -22798,7 +22841,10 @@ const createFileService = ({
|
|
|
22798
22841
|
rootDirectoryUrl,
|
|
22799
22842
|
urlGraph,
|
|
22800
22843
|
kitchen,
|
|
22801
|
-
scenario
|
|
22844
|
+
scenario,
|
|
22845
|
+
onParseError,
|
|
22846
|
+
onFileNotFound,
|
|
22847
|
+
onUnexpectedError
|
|
22802
22848
|
}) => {
|
|
22803
22849
|
kitchen.pluginController.addHook("serve");
|
|
22804
22850
|
kitchen.pluginController.addHook("augmentResponse");
|
|
@@ -22838,7 +22884,9 @@ const createFileService = ({
|
|
|
22838
22884
|
|
|
22839
22885
|
if (!reference) {
|
|
22840
22886
|
const entryPoint = kitchen.injectReference({
|
|
22841
|
-
trace:
|
|
22887
|
+
trace: {
|
|
22888
|
+
message: parentUrl || rootDirectoryUrl
|
|
22889
|
+
},
|
|
22842
22890
|
parentUrl: parentUrl || rootDirectoryUrl,
|
|
22843
22891
|
type: "http_request",
|
|
22844
22892
|
specifier: request.ressource
|
|
@@ -22918,10 +22966,18 @@ const createFileService = ({
|
|
|
22918
22966
|
const code = e.code;
|
|
22919
22967
|
|
|
22920
22968
|
if (code === "PARSE_ERROR") {
|
|
22921
|
-
|
|
22969
|
+
onParseError({
|
|
22970
|
+
reason: e.reason,
|
|
22971
|
+
message: e.message,
|
|
22972
|
+
url: e.url,
|
|
22973
|
+
line: e.line,
|
|
22974
|
+
column: e.column,
|
|
22975
|
+
contentFrame: e.contentFrame
|
|
22976
|
+
});
|
|
22922
22977
|
return {
|
|
22923
22978
|
url: reference.url,
|
|
22924
22979
|
status: 200,
|
|
22980
|
+
// let the browser re-throw the syntax error
|
|
22925
22981
|
statusText: e.reason,
|
|
22926
22982
|
statusMessage: e.message,
|
|
22927
22983
|
headers: {
|
|
@@ -22952,6 +23008,14 @@ const createFileService = ({
|
|
|
22952
23008
|
}
|
|
22953
23009
|
|
|
22954
23010
|
if (code === "NOT_FOUND") {
|
|
23011
|
+
onFileNotFound({
|
|
23012
|
+
reason: e.reason,
|
|
23013
|
+
message: e.message,
|
|
23014
|
+
url: e.url,
|
|
23015
|
+
line: e.line,
|
|
23016
|
+
column: e.column,
|
|
23017
|
+
contentFrame: e.contentFrame
|
|
23018
|
+
});
|
|
22955
23019
|
return {
|
|
22956
23020
|
url: reference.url,
|
|
22957
23021
|
status: 404,
|
|
@@ -22960,6 +23024,15 @@ const createFileService = ({
|
|
|
22960
23024
|
};
|
|
22961
23025
|
}
|
|
22962
23026
|
|
|
23027
|
+
onUnexpectedError({
|
|
23028
|
+
reason: e.reason,
|
|
23029
|
+
message: e.message,
|
|
23030
|
+
stack: e.stack,
|
|
23031
|
+
url: e.url,
|
|
23032
|
+
line: e.line,
|
|
23033
|
+
column: e.column,
|
|
23034
|
+
contentFrame: e.contentFrame
|
|
23035
|
+
});
|
|
22963
23036
|
return {
|
|
22964
23037
|
url: reference.url,
|
|
22965
23038
|
status: 500,
|
|
@@ -23026,12 +23099,75 @@ const startOmegaServer = async ({
|
|
|
23026
23099
|
kitchen
|
|
23027
23100
|
}) => {
|
|
23028
23101
|
const serverStopCallbackList = createCallbackListNotifiedOnce();
|
|
23102
|
+
const serverEventCallbackList = createCallbackList();
|
|
23103
|
+
const sseService = createSSEService({
|
|
23104
|
+
serverEventCallbackList
|
|
23105
|
+
});
|
|
23106
|
+
|
|
23107
|
+
const sendServerEvent = ({
|
|
23108
|
+
type,
|
|
23109
|
+
data
|
|
23110
|
+
}) => {
|
|
23111
|
+
serverEventCallbackList.notify({
|
|
23112
|
+
type,
|
|
23113
|
+
data: JSON.stringify(data)
|
|
23114
|
+
});
|
|
23115
|
+
};
|
|
23116
|
+
|
|
23117
|
+
kitchen.pluginController.addHook("registerServerEvents");
|
|
23118
|
+
kitchen.pluginController.callHooks("registerServerEvents", {
|
|
23119
|
+
sendServerEvent
|
|
23120
|
+
}, {
|
|
23121
|
+
rootDirectoryUrl,
|
|
23122
|
+
urlGraph,
|
|
23123
|
+
scenario
|
|
23124
|
+
}, () => {});
|
|
23125
|
+
|
|
23126
|
+
const sendServerErrorEvent = event => {
|
|
23127
|
+
// setTimeout display first the error
|
|
23128
|
+
// dispatched on window by browser
|
|
23129
|
+
// then display the jsenv error
|
|
23130
|
+
setTimeout(() => {
|
|
23131
|
+
sendServerEvent(event);
|
|
23132
|
+
}, 10);
|
|
23133
|
+
};
|
|
23134
|
+
|
|
23029
23135
|
const coreServices = {
|
|
23136
|
+
"service:server_events": request => {
|
|
23137
|
+
const {
|
|
23138
|
+
accept
|
|
23139
|
+
} = request.headers;
|
|
23140
|
+
|
|
23141
|
+
if (accept && accept.includes("text/event-stream")) {
|
|
23142
|
+
const room = sseService.getOrCreateSSERoom(request);
|
|
23143
|
+
return room.join(request);
|
|
23144
|
+
}
|
|
23145
|
+
|
|
23146
|
+
return null;
|
|
23147
|
+
},
|
|
23030
23148
|
"service:file": createFileService({
|
|
23031
23149
|
rootDirectoryUrl,
|
|
23032
23150
|
urlGraph,
|
|
23033
23151
|
kitchen,
|
|
23034
|
-
scenario
|
|
23152
|
+
scenario,
|
|
23153
|
+
onFileNotFound: data => {
|
|
23154
|
+
sendServerErrorEvent({
|
|
23155
|
+
type: "file_not_found",
|
|
23156
|
+
data
|
|
23157
|
+
});
|
|
23158
|
+
},
|
|
23159
|
+
onParseError: data => {
|
|
23160
|
+
sendServerErrorEvent({
|
|
23161
|
+
type: "parse_error",
|
|
23162
|
+
data
|
|
23163
|
+
});
|
|
23164
|
+
},
|
|
23165
|
+
onUnexpectedError: data => {
|
|
23166
|
+
sendServerErrorEvent({
|
|
23167
|
+
type: "unexpected_error",
|
|
23168
|
+
data
|
|
23169
|
+
});
|
|
23170
|
+
}
|
|
23035
23171
|
})
|
|
23036
23172
|
};
|
|
23037
23173
|
const server = await startServer({
|
|
@@ -23112,6 +23248,7 @@ const startOmegaServer = async ({
|
|
|
23112
23248
|
}),
|
|
23113
23249
|
onStop: reason => {
|
|
23114
23250
|
onStop();
|
|
23251
|
+
sseService.destroy();
|
|
23115
23252
|
serverStopCallbackList.notify(reason);
|
|
23116
23253
|
}
|
|
23117
23254
|
});
|
|
@@ -24003,7 +24140,7 @@ const reportToCoverage = async (report, {
|
|
|
24003
24140
|
// coverDescription will generate empty coverage for files
|
|
24004
24141
|
// that were suppose to be coverage but were not.
|
|
24005
24142
|
if (executionResult.status === "completed" && executionResult.type === "node" && coverageMethodForNodeJs !== "NODE_V8_COVERAGE") {
|
|
24006
|
-
logger.warn(`
|
|
24143
|
+
logger.warn(`"${executionName}" execution of ${file} did not properly write coverage into ${executionResult.coverageFileUrl}`);
|
|
24007
24144
|
}
|
|
24008
24145
|
}
|
|
24009
24146
|
});
|
|
@@ -24084,17 +24221,22 @@ const getCoverageFromReport = async ({
|
|
|
24084
24221
|
const {
|
|
24085
24222
|
coverageFileUrl
|
|
24086
24223
|
} = executionResultForFileOnRuntime;
|
|
24224
|
+
let executionCoverage;
|
|
24087
24225
|
|
|
24088
|
-
|
|
24089
|
-
|
|
24090
|
-
|
|
24091
|
-
|
|
24092
|
-
|
|
24093
|
-
|
|
24094
|
-
|
|
24095
|
-
|
|
24226
|
+
try {
|
|
24227
|
+
executionCoverage = JSON.parse(String(readFileSync$1(new URL(coverageFileUrl))));
|
|
24228
|
+
} catch (e) {
|
|
24229
|
+
if (e.code === "ENOENT" || e.name === "SyntaxError") {
|
|
24230
|
+
onMissing({
|
|
24231
|
+
executionName,
|
|
24232
|
+
file,
|
|
24233
|
+
executionResult: executionResultForFileOnRuntime
|
|
24234
|
+
});
|
|
24235
|
+
return;
|
|
24236
|
+
}
|
|
24096
24237
|
|
|
24097
|
-
|
|
24238
|
+
throw e;
|
|
24239
|
+
}
|
|
24098
24240
|
|
|
24099
24241
|
if (isV8Coverage(executionCoverage)) {
|
|
24100
24242
|
v8Coverage = v8Coverage ? composeTwoV8Coverages(v8Coverage, executionCoverage) : executionCoverage;
|
|
@@ -24127,7 +24269,7 @@ const run = async ({
|
|
|
24127
24269
|
runtime,
|
|
24128
24270
|
runtimeParams
|
|
24129
24271
|
}) => {
|
|
24130
|
-
|
|
24272
|
+
const result = {};
|
|
24131
24273
|
const callbacks = [];
|
|
24132
24274
|
const onConsoleRef = {
|
|
24133
24275
|
current: () => {}
|
|
@@ -24145,18 +24287,16 @@ const run = async ({
|
|
|
24145
24287
|
const timeoutAbortSource = runOperation.timeout(allocatedMs);
|
|
24146
24288
|
callbacks.push(() => {
|
|
24147
24289
|
if (result.status === "errored" && Abort.isAbortError(result.error) && timeoutAbortSource.signal.aborted) {
|
|
24148
|
-
result =
|
|
24149
|
-
|
|
24150
|
-
};
|
|
24290
|
+
result.status = "timedout";
|
|
24291
|
+
delete result.error;
|
|
24151
24292
|
}
|
|
24152
24293
|
});
|
|
24153
24294
|
}
|
|
24154
24295
|
|
|
24155
24296
|
callbacks.push(() => {
|
|
24156
24297
|
if (result.status === "errored" && Abort.isAbortError(result.error)) {
|
|
24157
|
-
result =
|
|
24158
|
-
|
|
24159
|
-
};
|
|
24298
|
+
result.status = "aborted";
|
|
24299
|
+
delete result.error;
|
|
24160
24300
|
}
|
|
24161
24301
|
});
|
|
24162
24302
|
const consoleCalls = [];
|
|
@@ -24185,6 +24325,22 @@ const run = async ({
|
|
|
24185
24325
|
callbacks.push(() => {
|
|
24186
24326
|
result.consoleCalls = consoleCalls;
|
|
24187
24327
|
});
|
|
24328
|
+
} // we do not keep coverage in memory, it can grow very big
|
|
24329
|
+
// instead we store it on the filesystem
|
|
24330
|
+
// and they can be read later at "coverageFileUrl"
|
|
24331
|
+
|
|
24332
|
+
|
|
24333
|
+
let coverageFileUrl;
|
|
24334
|
+
|
|
24335
|
+
if (coverageEnabled) {
|
|
24336
|
+
coverageFileUrl = new URL(`./${runtime.name}/${cuid()}.json`, coverageTempDirectoryUrl).href;
|
|
24337
|
+
await ensureParentDirectories(coverageFileUrl);
|
|
24338
|
+
|
|
24339
|
+
if (coverageEnabled) {
|
|
24340
|
+
result.coverageFileUrl = coverageFileUrl; // written within the child_process/worker_thread or during runtime.run()
|
|
24341
|
+
// for browsers
|
|
24342
|
+
// (because it takes time to serialize and transfer the coverage object)
|
|
24343
|
+
}
|
|
24188
24344
|
}
|
|
24189
24345
|
|
|
24190
24346
|
const startMs = Date.now();
|
|
@@ -24209,7 +24365,9 @@ const run = async ({
|
|
|
24209
24365
|
signal: runOperation.signal,
|
|
24210
24366
|
logger,
|
|
24211
24367
|
...runtimeParams,
|
|
24368
|
+
collectConsole,
|
|
24212
24369
|
collectPerformance,
|
|
24370
|
+
coverageFileUrl,
|
|
24213
24371
|
keepRunning,
|
|
24214
24372
|
stopSignal,
|
|
24215
24373
|
onConsole: log => onConsoleRef.current(log)
|
|
@@ -24234,8 +24392,7 @@ const run = async ({
|
|
|
24234
24392
|
status,
|
|
24235
24393
|
namespace,
|
|
24236
24394
|
error,
|
|
24237
|
-
performance
|
|
24238
|
-
coverage
|
|
24395
|
+
performance
|
|
24239
24396
|
} = winner.data;
|
|
24240
24397
|
result.status = status;
|
|
24241
24398
|
|
|
@@ -24249,27 +24406,13 @@ const run = async ({
|
|
|
24249
24406
|
result.performance = performance;
|
|
24250
24407
|
}
|
|
24251
24408
|
|
|
24252
|
-
if (coverageEnabled) {
|
|
24253
|
-
if (coverage) {
|
|
24254
|
-
// we do not keep coverage in memory, it can grow very big
|
|
24255
|
-
// instead we store it on the filesystem
|
|
24256
|
-
// and they can be read later at "coverageFileUrl"
|
|
24257
|
-
const coverageFileUrl = new URL(`./${runtime.name}/${cuid()}.json`, coverageTempDirectoryUrl);
|
|
24258
|
-
writeFileSync(coverageFileUrl, JSON.stringify(coverage, null, " "));
|
|
24259
|
-
result.coverageFileUrl = coverageFileUrl.href;
|
|
24260
|
-
} else {// will eventually log a warning in report_to_coverage.js
|
|
24261
|
-
}
|
|
24262
|
-
}
|
|
24263
|
-
|
|
24264
24409
|
callbacks.forEach(callback => {
|
|
24265
24410
|
callback();
|
|
24266
24411
|
});
|
|
24267
24412
|
return result;
|
|
24268
24413
|
} catch (e) {
|
|
24269
|
-
result =
|
|
24270
|
-
|
|
24271
|
-
error: e
|
|
24272
|
-
};
|
|
24414
|
+
result.status = "errored";
|
|
24415
|
+
result.error = e;
|
|
24273
24416
|
callbacks.forEach(callback => {
|
|
24274
24417
|
callback();
|
|
24275
24418
|
});
|
|
@@ -24567,20 +24710,78 @@ const formatConsoleCalls = consoleCalls => {
|
|
|
24567
24710
|
error: 0,
|
|
24568
24711
|
log: 0
|
|
24569
24712
|
};
|
|
24570
|
-
let consoleOutput = ``;
|
|
24571
24713
|
consoleCalls.forEach(consoleCall => {
|
|
24572
24714
|
repartition[consoleCall.type]++;
|
|
24573
|
-
|
|
24715
|
+
});
|
|
24716
|
+
const consoleOutput = formatConsoleOutput(consoleCalls);
|
|
24717
|
+
return `${ANSI.color(`-------- ${formatConsoleSummary(repartition)} --------`, ANSI.GREY)}
|
|
24718
|
+
${consoleOutput}
|
|
24719
|
+
${ANSI.color(`-------------------------`, ANSI.GREY)}`;
|
|
24720
|
+
};
|
|
24721
|
+
|
|
24722
|
+
const formatConsoleOutput = consoleCalls => {
|
|
24723
|
+
// inside Node.js you can do process.stdout.write()
|
|
24724
|
+
// and in that case the consoleCall is not suffixed with "\n"
|
|
24725
|
+
// we want to keep these calls together in the output
|
|
24726
|
+
const regroupedCalls = [];
|
|
24727
|
+
consoleCalls.forEach((consoleCall, index) => {
|
|
24728
|
+
if (index === 0) {
|
|
24729
|
+
regroupedCalls.push(consoleCall);
|
|
24730
|
+
return;
|
|
24731
|
+
}
|
|
24732
|
+
|
|
24733
|
+
const previousCall = consoleCalls[index - 1];
|
|
24734
|
+
|
|
24735
|
+
if (previousCall.type !== consoleCall.type) {
|
|
24736
|
+
regroupedCalls.push(consoleCall);
|
|
24737
|
+
return;
|
|
24738
|
+
}
|
|
24739
|
+
|
|
24740
|
+
if (previousCall.text.endsWith("\n")) {
|
|
24741
|
+
regroupedCalls.push(consoleCall);
|
|
24742
|
+
return;
|
|
24743
|
+
}
|
|
24744
|
+
|
|
24745
|
+
if (previousCall.text.endsWith("\r")) {
|
|
24746
|
+
regroupedCalls.push(consoleCall);
|
|
24747
|
+
return;
|
|
24748
|
+
}
|
|
24749
|
+
|
|
24750
|
+
const previousRegroupedCallIndex = regroupedCalls.length - 1;
|
|
24751
|
+
const previousRegroupedCall = regroupedCalls[previousRegroupedCallIndex];
|
|
24752
|
+
previousRegroupedCall.text = `${previousRegroupedCall.text}${consoleCall.text}`;
|
|
24753
|
+
});
|
|
24754
|
+
let consoleOutput = ``;
|
|
24755
|
+
regroupedCalls.forEach((regroupedCall, index) => {
|
|
24756
|
+
const text = regroupedCall.text;
|
|
24574
24757
|
const textFormatted = prefixFirstAndIndentRemainingLines({
|
|
24575
|
-
prefix: CONSOLE_ICONS[
|
|
24758
|
+
prefix: CONSOLE_ICONS[regroupedCall.type],
|
|
24576
24759
|
text,
|
|
24577
|
-
trimLastLine:
|
|
24760
|
+
trimLastLine: index === regroupedCalls.length - 1
|
|
24578
24761
|
});
|
|
24579
24762
|
consoleOutput += textFormatted;
|
|
24580
24763
|
});
|
|
24581
|
-
return
|
|
24582
|
-
|
|
24583
|
-
|
|
24764
|
+
return consoleOutput;
|
|
24765
|
+
};
|
|
24766
|
+
|
|
24767
|
+
const prefixFirstAndIndentRemainingLines = ({
|
|
24768
|
+
prefix,
|
|
24769
|
+
text,
|
|
24770
|
+
trimLastLine
|
|
24771
|
+
}) => {
|
|
24772
|
+
const lines = text.split(/\r?\n/);
|
|
24773
|
+
const firstLine = lines.shift();
|
|
24774
|
+
let result = `${prefix} ${firstLine}`;
|
|
24775
|
+
let i = 0;
|
|
24776
|
+
const indentation = ` `;
|
|
24777
|
+
|
|
24778
|
+
while (i < lines.length) {
|
|
24779
|
+
const line = lines[i].trim();
|
|
24780
|
+
i++;
|
|
24781
|
+
result += line.length ? `\n${indentation}${line}` : trimLastLine && i === lines.length ? "" : `\n`;
|
|
24782
|
+
}
|
|
24783
|
+
|
|
24784
|
+
return result;
|
|
24584
24785
|
};
|
|
24585
24786
|
|
|
24586
24787
|
const CONSOLE_ICONS = {
|
|
@@ -24623,26 +24824,6 @@ const formatConsoleSummary = repartition => {
|
|
|
24623
24824
|
return `console (${parts.join(" ")})`;
|
|
24624
24825
|
};
|
|
24625
24826
|
|
|
24626
|
-
const prefixFirstAndIndentRemainingLines = ({
|
|
24627
|
-
prefix,
|
|
24628
|
-
text,
|
|
24629
|
-
trimLastLine
|
|
24630
|
-
}) => {
|
|
24631
|
-
const lines = text.split(/\r?\n/);
|
|
24632
|
-
const firstLine = lines.shift();
|
|
24633
|
-
let result = `${prefix} ${firstLine}`;
|
|
24634
|
-
let i = 0;
|
|
24635
|
-
const indentation = ` `;
|
|
24636
|
-
|
|
24637
|
-
while (i < lines.length) {
|
|
24638
|
-
const line = lines[i].trim();
|
|
24639
|
-
i++;
|
|
24640
|
-
result += line.length ? `\n${indentation}${line}` : trimLastLine && i === lines.length ? "" : `\n`;
|
|
24641
|
-
}
|
|
24642
|
-
|
|
24643
|
-
return result;
|
|
24644
|
-
};
|
|
24645
|
-
|
|
24646
24827
|
const formatExecution = ({
|
|
24647
24828
|
label,
|
|
24648
24829
|
details = {},
|
|
@@ -24767,7 +24948,7 @@ const executePlan = async (plan, {
|
|
|
24767
24948
|
} else {
|
|
24768
24949
|
coverageMethodForNodeJs = "Profiler";
|
|
24769
24950
|
logger.warn(createDetailedMessage$1(`process.env.NODE_V8_COVERAGE is required to generate coverage for Node.js subprocesses`, {
|
|
24770
|
-
"suggestion": `
|
|
24951
|
+
"suggestion": `set process.env.NODE_V8_COVERAGE`,
|
|
24771
24952
|
"suggestion 2": `use coverageMethodForNodeJs: "Profiler". But it means coverage for child_process and worker_thread cannot be collected`
|
|
24772
24953
|
}));
|
|
24773
24954
|
}
|
|
@@ -24845,7 +25026,7 @@ const executePlan = async (plan, {
|
|
|
24845
25026
|
getCustomBabelPlugins: ({
|
|
24846
25027
|
clientRuntimeCompat
|
|
24847
25028
|
}) => {
|
|
24848
|
-
if (coverageEnabled && Object.keys(clientRuntimeCompat)[0] !== "chrome") {
|
|
25029
|
+
if (coverageEnabled && (coverageMethodForBrowsers !== "playwright_api" || Object.keys(clientRuntimeCompat)[0] !== "chrome")) {
|
|
24849
25030
|
return {
|
|
24850
25031
|
"transform-instrument": [babelPluginInstrument, {
|
|
24851
25032
|
rootDirectoryUrl,
|
|
@@ -25269,8 +25450,7 @@ const executeTestPlan = async ({
|
|
|
25269
25450
|
},
|
|
25270
25451
|
coverageIncludeMissing = true,
|
|
25271
25452
|
coverageAndExecutionAllowed = false,
|
|
25272
|
-
coverageMethodForNodeJs = "NODE_V8_COVERAGE",
|
|
25273
|
-
// "Profiler" also accepted
|
|
25453
|
+
coverageMethodForNodeJs = process.env.NODE_V8_COVERAGE ? "NODE_V8_COVERAGE" : "Profiler",
|
|
25274
25454
|
coverageMethodForBrowsers = "playwright_api",
|
|
25275
25455
|
// "istanbul" also accepted
|
|
25276
25456
|
coverageV8ConflictWarning = true,
|
|
@@ -25508,6 +25688,7 @@ const createRuntimeFromPlaywright = ({
|
|
|
25508
25688
|
coverageEnabled = false,
|
|
25509
25689
|
coverageConfig,
|
|
25510
25690
|
coverageMethodForBrowsers,
|
|
25691
|
+
coverageFileUrl,
|
|
25511
25692
|
stopAfterAllSignal,
|
|
25512
25693
|
stopSignal,
|
|
25513
25694
|
keepRunning,
|
|
@@ -25590,13 +25771,14 @@ const createRuntimeFromPlaywright = ({
|
|
|
25590
25771
|
}
|
|
25591
25772
|
};
|
|
25592
25773
|
|
|
25593
|
-
|
|
25774
|
+
const result = {};
|
|
25775
|
+
const callbacks = [];
|
|
25594
25776
|
|
|
25595
25777
|
if (coverageEnabled) {
|
|
25596
25778
|
if (coveragePlaywrightAPIAvailable && coverageMethodForBrowsers === "playwright_api") {
|
|
25597
25779
|
await page.coverage.startJSCoverage({// reportAnonymousScripts: true,
|
|
25598
25780
|
});
|
|
25599
|
-
|
|
25781
|
+
callbacks.push(async () => {
|
|
25600
25782
|
const v8CoveragesWithWebUrls = await page.coverage.stopJSCoverage(); // we convert urls starting with http:// to file:// because we later
|
|
25601
25783
|
// convert the url to filesystem path in istanbulCoverageFromV8Coverage function
|
|
25602
25784
|
|
|
@@ -25617,23 +25799,20 @@ const createRuntimeFromPlaywright = ({
|
|
|
25617
25799
|
rootDirectoryUrl,
|
|
25618
25800
|
coverageConfig
|
|
25619
25801
|
});
|
|
25620
|
-
|
|
25621
|
-
coverage
|
|
25622
|
-
};
|
|
25802
|
+
writeFileSync$1(new URL(coverageFileUrl), JSON.stringify(coverage, null, " "));
|
|
25623
25803
|
});
|
|
25624
25804
|
} else {
|
|
25625
|
-
|
|
25805
|
+
callbacks.push(() => {
|
|
25626
25806
|
const scriptExecutionResults = result.namespace;
|
|
25627
25807
|
|
|
25628
25808
|
if (scriptExecutionResults) {
|
|
25629
|
-
|
|
25809
|
+
const coverage = generateCoverageForPage(scriptExecutionResults) || {};
|
|
25810
|
+
writeFileSync$1(new URL(coverageFileUrl), JSON.stringify(coverage, null, " "));
|
|
25630
25811
|
}
|
|
25631
|
-
|
|
25632
|
-
return result;
|
|
25633
25812
|
});
|
|
25634
25813
|
}
|
|
25635
25814
|
} else {
|
|
25636
|
-
|
|
25815
|
+
callbacks.push(() => {
|
|
25637
25816
|
const scriptExecutionResults = result.namespace;
|
|
25638
25817
|
|
|
25639
25818
|
if (scriptExecutionResults) {
|
|
@@ -25641,13 +25820,11 @@ const createRuntimeFromPlaywright = ({
|
|
|
25641
25820
|
delete scriptExecutionResults[fileRelativeUrl].coverage;
|
|
25642
25821
|
});
|
|
25643
25822
|
}
|
|
25644
|
-
|
|
25645
|
-
return result;
|
|
25646
25823
|
});
|
|
25647
25824
|
}
|
|
25648
25825
|
|
|
25649
25826
|
if (collectPerformance) {
|
|
25650
|
-
|
|
25827
|
+
callbacks.push(async () => {
|
|
25651
25828
|
const performance = await page.evaluate(
|
|
25652
25829
|
/* eslint-disable no-undef */
|
|
25653
25830
|
|
|
@@ -25676,7 +25853,6 @@ const createRuntimeFromPlaywright = ({
|
|
|
25676
25853
|
/* eslint-enable no-undef */
|
|
25677
25854
|
);
|
|
25678
25855
|
result.performance = performance;
|
|
25679
|
-
return result;
|
|
25680
25856
|
});
|
|
25681
25857
|
}
|
|
25682
25858
|
|
|
@@ -25770,7 +25946,7 @@ const createRuntimeFromPlaywright = ({
|
|
|
25770
25946
|
await page.goto(fileClientUrl, {
|
|
25771
25947
|
timeout: 0
|
|
25772
25948
|
});
|
|
25773
|
-
const
|
|
25949
|
+
const returnValue = await page.evaluate(
|
|
25774
25950
|
/* eslint-disable no-undef */
|
|
25775
25951
|
|
|
25776
25952
|
/* istanbul ignore next */
|
|
@@ -25786,12 +25962,12 @@ const createRuntimeFromPlaywright = ({
|
|
|
25786
25962
|
const {
|
|
25787
25963
|
status,
|
|
25788
25964
|
scriptExecutionResults
|
|
25789
|
-
} =
|
|
25965
|
+
} = returnValue;
|
|
25790
25966
|
|
|
25791
25967
|
if (status === "errored") {
|
|
25792
25968
|
const {
|
|
25793
25969
|
exceptionSource
|
|
25794
|
-
} =
|
|
25970
|
+
} = returnValue;
|
|
25795
25971
|
const error = evalException(exceptionSource, {
|
|
25796
25972
|
rootDirectoryUrl,
|
|
25797
25973
|
server,
|
|
@@ -25842,16 +26018,32 @@ const createRuntimeFromPlaywright = ({
|
|
|
25842
26018
|
return winner.data;
|
|
25843
26019
|
};
|
|
25844
26020
|
|
|
25845
|
-
let result;
|
|
25846
|
-
|
|
25847
26021
|
try {
|
|
25848
|
-
|
|
25849
|
-
|
|
26022
|
+
const {
|
|
26023
|
+
status,
|
|
26024
|
+
error,
|
|
26025
|
+
namespace,
|
|
26026
|
+
performance
|
|
26027
|
+
} = await getResult();
|
|
26028
|
+
result.status = status;
|
|
26029
|
+
|
|
26030
|
+
if (status === "errored") {
|
|
26031
|
+
result.error = error;
|
|
26032
|
+
} else {
|
|
26033
|
+
result.namespace = namespace;
|
|
26034
|
+
}
|
|
26035
|
+
|
|
26036
|
+
if (collectPerformance) {
|
|
26037
|
+
result.performance = performance;
|
|
26038
|
+
}
|
|
26039
|
+
|
|
26040
|
+
await callbacks.reduce(async (previous, callback) => {
|
|
26041
|
+
await previous;
|
|
26042
|
+
await callback();
|
|
26043
|
+
}, Promise.resolve());
|
|
25850
26044
|
} catch (e) {
|
|
25851
|
-
result =
|
|
25852
|
-
|
|
25853
|
-
error: e
|
|
25854
|
-
};
|
|
26045
|
+
result.status = "errored";
|
|
26046
|
+
result.error = e;
|
|
25855
26047
|
}
|
|
25856
26048
|
|
|
25857
26049
|
if (keepRunning) {
|
|
@@ -25969,13 +26161,6 @@ const isTargetClosedError = error => {
|
|
|
25969
26161
|
return false;
|
|
25970
26162
|
};
|
|
25971
26163
|
|
|
25972
|
-
const composeTransformer = (previousTransformer, transformer) => {
|
|
25973
|
-
return async value => {
|
|
25974
|
-
const transformedValue = await previousTransformer(value);
|
|
25975
|
-
return transformer(transformedValue);
|
|
25976
|
-
};
|
|
25977
|
-
};
|
|
25978
|
-
|
|
25979
26164
|
const extractTextFromConsoleMessage = consoleMessage => {
|
|
25980
26165
|
return consoleMessage.text(); // ensure we use a string so that istanbul won't try
|
|
25981
26166
|
// to put any coverage statement inside it
|
|
@@ -26385,6 +26570,7 @@ nodeChildProcess.run = async ({
|
|
|
26385
26570
|
coverageEnabled = false,
|
|
26386
26571
|
coverageConfig,
|
|
26387
26572
|
coverageMethodForNodeJs,
|
|
26573
|
+
coverageFileUrl,
|
|
26388
26574
|
collectPerformance,
|
|
26389
26575
|
env,
|
|
26390
26576
|
debugPort,
|
|
@@ -26548,6 +26734,7 @@ nodeChildProcess.run = async ({
|
|
|
26548
26734
|
coverageEnabled,
|
|
26549
26735
|
coverageConfig,
|
|
26550
26736
|
coverageMethodForNodeJs,
|
|
26737
|
+
coverageFileUrl,
|
|
26551
26738
|
exitAfterAction: true
|
|
26552
26739
|
}
|
|
26553
26740
|
}
|
|
@@ -26728,10 +26915,12 @@ nodeWorkerThread.run = async ({
|
|
|
26728
26915
|
keepRunning,
|
|
26729
26916
|
stopSignal,
|
|
26730
26917
|
onConsole,
|
|
26918
|
+
collectConsole = false,
|
|
26919
|
+
collectPerformance,
|
|
26920
|
+
coverageEnabled = false,
|
|
26731
26921
|
coverageConfig,
|
|
26732
26922
|
coverageMethodForNodeJs,
|
|
26733
|
-
|
|
26734
|
-
collectPerformance,
|
|
26923
|
+
coverageFileUrl,
|
|
26735
26924
|
env,
|
|
26736
26925
|
debugPort,
|
|
26737
26926
|
debugMode,
|
|
@@ -26797,11 +26986,14 @@ nodeWorkerThread.run = async ({
|
|
|
26797
26986
|
const stop = memoize(async () => {
|
|
26798
26987
|
// read all stdout before terminating
|
|
26799
26988
|
// (no need for stderr because it's sync)
|
|
26800
|
-
|
|
26989
|
+
if (collectConsole) {
|
|
26990
|
+
while (workerThread.stdout.read() !== null) {}
|
|
26991
|
+
|
|
26992
|
+
await new Promise(resolve => {
|
|
26993
|
+
setTimeout(resolve, 50);
|
|
26994
|
+
});
|
|
26995
|
+
}
|
|
26801
26996
|
|
|
26802
|
-
await new Promise(resolve => {
|
|
26803
|
-
setTimeout(resolve);
|
|
26804
|
-
});
|
|
26805
26997
|
await workerThread.terminate();
|
|
26806
26998
|
});
|
|
26807
26999
|
const winnerPromise = new Promise(resolve => {
|
|
@@ -26841,6 +27033,7 @@ nodeWorkerThread.run = async ({
|
|
|
26841
27033
|
coverageEnabled,
|
|
26842
27034
|
coverageConfig,
|
|
26843
27035
|
coverageMethodForNodeJs,
|
|
27036
|
+
coverageFileUrl,
|
|
26844
27037
|
exitAfterAction: true
|
|
26845
27038
|
}
|
|
26846
27039
|
}
|
|
@@ -27098,9 +27291,6 @@ ${createRepartitionMessage(graphReport)}
|
|
|
27098
27291
|
};
|
|
27099
27292
|
|
|
27100
27293
|
const createUrlGraphReport = urlGraph => {
|
|
27101
|
-
const {
|
|
27102
|
-
urlInfos
|
|
27103
|
-
} = urlGraph;
|
|
27104
27294
|
const countGroups = {
|
|
27105
27295
|
sourcemaps: 0,
|
|
27106
27296
|
html: 0,
|
|
@@ -27119,15 +27309,14 @@ const createUrlGraphReport = urlGraph => {
|
|
|
27119
27309
|
other: 0,
|
|
27120
27310
|
total: 0
|
|
27121
27311
|
};
|
|
27122
|
-
|
|
27123
|
-
if (url.startsWith("data:")) {
|
|
27312
|
+
urlGraph.urlInfoMap.forEach(urlInfo => {
|
|
27313
|
+
if (urlInfo.url.startsWith("data:")) {
|
|
27124
27314
|
return;
|
|
27125
|
-
}
|
|
27126
|
-
|
|
27127
|
-
const urlInfo = urlInfos[url]; // ignore:
|
|
27315
|
+
} // ignore:
|
|
27128
27316
|
// - inline files: they are already taken into account in the file where they appear
|
|
27129
27317
|
// - ignored files: we don't know their content
|
|
27130
27318
|
|
|
27319
|
+
|
|
27131
27320
|
if (urlInfo.isInline || !urlInfo.shouldHandle) {
|
|
27132
27321
|
return;
|
|
27133
27322
|
} // file loaded via import assertion are already inside the graph
|
|
@@ -27305,20 +27494,18 @@ const createRepartitionMessage = ({
|
|
|
27305
27494
|
|
|
27306
27495
|
const GRAPH = {
|
|
27307
27496
|
map: (graph, callback) => {
|
|
27308
|
-
|
|
27309
|
-
|
|
27497
|
+
const array = [];
|
|
27498
|
+
graph.urlInfoMap.forEach(urlInfo => {
|
|
27499
|
+
array.push(callback(urlInfo));
|
|
27310
27500
|
});
|
|
27501
|
+
return array;
|
|
27311
27502
|
},
|
|
27312
27503
|
forEach: (graph, callback) => {
|
|
27313
|
-
|
|
27314
|
-
callback(graph.urlInfos[url], url);
|
|
27315
|
-
});
|
|
27504
|
+
graph.urlInfoMap.forEach(callback);
|
|
27316
27505
|
},
|
|
27317
27506
|
filter: (graph, callback) => {
|
|
27318
27507
|
const urlInfos = [];
|
|
27319
|
-
|
|
27320
|
-
const urlInfo = graph.urlInfos[url];
|
|
27321
|
-
|
|
27508
|
+
graph.urlInfoMap.forEach(urlInfo => {
|
|
27322
27509
|
if (callback(urlInfo)) {
|
|
27323
27510
|
urlInfos.push(urlInfo);
|
|
27324
27511
|
}
|
|
@@ -27326,10 +27513,16 @@ const GRAPH = {
|
|
|
27326
27513
|
return urlInfos;
|
|
27327
27514
|
},
|
|
27328
27515
|
find: (graph, callback) => {
|
|
27329
|
-
|
|
27330
|
-
|
|
27331
|
-
|
|
27332
|
-
|
|
27516
|
+
let found = null;
|
|
27517
|
+
|
|
27518
|
+
for (const urlInfo of graph.urlInfoMap.values()) {
|
|
27519
|
+
if (callback(urlInfo)) {
|
|
27520
|
+
found = urlInfo;
|
|
27521
|
+
break;
|
|
27522
|
+
}
|
|
27523
|
+
}
|
|
27524
|
+
|
|
27525
|
+
return found;
|
|
27333
27526
|
}
|
|
27334
27527
|
};
|
|
27335
27528
|
|
|
@@ -27964,7 +28157,9 @@ build ${entryPointKeys.length} entry points`);
|
|
|
27964
28157
|
startLoading: cookEntryFile => {
|
|
27965
28158
|
Object.keys(entryPoints).forEach(key => {
|
|
27966
28159
|
const [, entryUrlInfo] = cookEntryFile({
|
|
27967
|
-
trace:
|
|
28160
|
+
trace: {
|
|
28161
|
+
message: `"${key}" in entryPoints parameter`
|
|
28162
|
+
},
|
|
27968
28163
|
type: "entry_point",
|
|
27969
28164
|
specifier: key
|
|
27970
28165
|
});
|
|
@@ -28460,7 +28655,9 @@ build ${entryPointKeys.length} entry points`);
|
|
|
28460
28655
|
startLoading: cookEntryFile => {
|
|
28461
28656
|
entryUrls.forEach(entryUrl => {
|
|
28462
28657
|
const [, postBuildEntryUrlInfo] = cookEntryFile({
|
|
28463
|
-
trace:
|
|
28658
|
+
trace: {
|
|
28659
|
+
message: `entryPoint`
|
|
28660
|
+
},
|
|
28464
28661
|
type: "entry_point",
|
|
28465
28662
|
specifier: entryUrl
|
|
28466
28663
|
});
|
|
@@ -28475,7 +28672,7 @@ build ${entryPointKeys.length} entry points`);
|
|
|
28475
28672
|
|
|
28476
28673
|
buildTask.done();
|
|
28477
28674
|
logger.debug(`graph urls pre-versioning:
|
|
28478
|
-
${
|
|
28675
|
+
${Array.from(finalGraph.urlInfoMap.keys()).join("\n")}`);
|
|
28479
28676
|
|
|
28480
28677
|
if (versioning) {
|
|
28481
28678
|
await applyUrlVersioning({
|
|
@@ -28731,7 +28928,7 @@ const applyUrlVersioning = async ({
|
|
|
28731
28928
|
});
|
|
28732
28929
|
|
|
28733
28930
|
try {
|
|
28734
|
-
const urlsSorted = sortByDependencies(finalGraph.
|
|
28931
|
+
const urlsSorted = sortByDependencies(finalGraph.toObject());
|
|
28735
28932
|
urlsSorted.forEach(url => {
|
|
28736
28933
|
if (url.startsWith("data:")) {
|
|
28737
28934
|
return;
|