@jsenv/core 27.6.0 → 27.6.1
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/js/html_supervisor_installer.js +11 -3
- package/dist/main.js +28 -7
- package/package.json +2 -2
- package/src/plugins/html_supervisor/client/error_formatter.js +12 -5
- package/src/plugins/html_supervisor/jsenv_plugin_html_supervisor.js +24 -6
- package/src/plugins/html_supervisor/client/error_site_remap.js +0 -85
|
@@ -38,6 +38,8 @@ const formatError = (error, {
|
|
|
38
38
|
line,
|
|
39
39
|
column
|
|
40
40
|
}) => {
|
|
41
|
+
if (typeof line === "string") line = parseInt(line);
|
|
42
|
+
if (typeof column === "string") column = parseInt(column);
|
|
41
43
|
const inlineUrlMatch = url.match(/@L([0-9]+)C([0-9]+)\-L([0-9]+)C([0-9]+)(\.[\w]+)$/);
|
|
42
44
|
|
|
43
45
|
if (inlineUrlMatch) {
|
|
@@ -48,7 +50,7 @@ const formatError = (error, {
|
|
|
48
50
|
const tagColumnEnd = parseInt(inlineUrlMatch[4]);
|
|
49
51
|
const extension = inlineUrlMatch[5];
|
|
50
52
|
url = htmlUrl;
|
|
51
|
-
line = tagLineStart + (line ===
|
|
53
|
+
line = tagLineStart + (typeof line === "number" ? line : 0); // stackTrace formatted by V8 (chrome)
|
|
52
54
|
|
|
53
55
|
if (Error.captureStackTrace) {
|
|
54
56
|
line--;
|
|
@@ -64,7 +66,7 @@ const formatError = (error, {
|
|
|
64
66
|
}
|
|
65
67
|
}
|
|
66
68
|
|
|
67
|
-
column = tagColumnStart + (column ===
|
|
69
|
+
column = tagColumnStart + (typeof column === "number" ? column : 0);
|
|
68
70
|
const fileUrl = resolveFileUrl(url);
|
|
69
71
|
return {
|
|
70
72
|
isInline: true,
|
|
@@ -188,7 +190,13 @@ const formatError = (error, {
|
|
|
188
190
|
}
|
|
189
191
|
|
|
190
192
|
if (urlSite.line !== undefined) {
|
|
191
|
-
|
|
193
|
+
let ressourceToFetch = `/__get_code_frame__/${formatUrlWithLineAndColumn(urlSite)}`;
|
|
194
|
+
|
|
195
|
+
if (!Error.captureStackTrace) {
|
|
196
|
+
ressourceToFetch += `?remap`;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const response = await window.fetch(ressourceToFetch);
|
|
192
200
|
const codeFrame = await response.text();
|
|
193
201
|
return {
|
|
194
202
|
codeFrame: formatErrorText({
|
package/dist/main.js
CHANGED
|
@@ -16,7 +16,7 @@ import { Readable, Stream, Writable } from "node:stream";
|
|
|
16
16
|
import { Http2ServerResponse } from "node:http2";
|
|
17
17
|
import { lookup } from "node:dns";
|
|
18
18
|
import { parseHtmlString, stringifyHtmlAst, visitHtmlNodes, getHtmlNodeAttribute, analyzeScriptNode, setHtmlNodeAttributes, parseSrcSet, getHtmlNodePosition, getHtmlNodeAttributePosition, applyPostCss, postCssPluginUrlVisitor, parseJsUrls, findHtmlNode, getHtmlNodeText, removeHtmlNode, setHtmlNodeText, applyBabelPlugins, injectScriptNodeAsEarlyAsPossible, createHtmlNode, removeHtmlNodeText, transpileWithParcel, injectJsImport, minifyWithParcel, analyzeLinkNode } from "@jsenv/ast";
|
|
19
|
-
import { createMagicSource, composeTwoSourcemaps, sourcemapConverter, SOURCEMAP, generateSourcemapFileUrl, generateSourcemapDataUrl } from "@jsenv/sourcemap";
|
|
19
|
+
import { createMagicSource, getOriginalPosition, composeTwoSourcemaps, sourcemapConverter, SOURCEMAP, generateSourcemapFileUrl, generateSourcemapDataUrl } from "@jsenv/sourcemap";
|
|
20
20
|
import { createRequire } from "node:module";
|
|
21
21
|
import babelParser from "@babel/parser";
|
|
22
22
|
import v8, { takeCoverage } from "node:v8";
|
|
@@ -12046,10 +12046,14 @@ const jsenvPluginHtmlSupervisor = ({
|
|
|
12046
12046
|
dev: true,
|
|
12047
12047
|
test: true
|
|
12048
12048
|
},
|
|
12049
|
-
serve: (request, context) => {
|
|
12049
|
+
serve: async (request, context) => {
|
|
12050
12050
|
if (request.ressource.startsWith("/__get_code_frame__/")) {
|
|
12051
|
-
const
|
|
12052
|
-
|
|
12051
|
+
const {
|
|
12052
|
+
pathname,
|
|
12053
|
+
searchParams
|
|
12054
|
+
} = new URL(request.url);
|
|
12055
|
+
const urlWithLineAndColumn = pathname.slice("/__get_code_frame__/".length);
|
|
12056
|
+
const match = urlWithLineAndColumn.match(/:([0-9]+):([0-9]+)$/);
|
|
12053
12057
|
|
|
12054
12058
|
if (!match) {
|
|
12055
12059
|
return {
|
|
@@ -12058,9 +12062,9 @@ const jsenvPluginHtmlSupervisor = ({
|
|
|
12058
12062
|
};
|
|
12059
12063
|
}
|
|
12060
12064
|
|
|
12061
|
-
const file =
|
|
12062
|
-
|
|
12063
|
-
|
|
12065
|
+
const file = urlWithLineAndColumn.slice(0, match.index);
|
|
12066
|
+
let line = parseInt(match[1]);
|
|
12067
|
+
let column = parseInt(match[2]);
|
|
12064
12068
|
const urlInfo = context.urlGraph.getUrlInfo(file);
|
|
12065
12069
|
|
|
12066
12070
|
if (!urlInfo) {
|
|
@@ -12069,6 +12073,23 @@ const jsenvPluginHtmlSupervisor = ({
|
|
|
12069
12073
|
};
|
|
12070
12074
|
}
|
|
12071
12075
|
|
|
12076
|
+
const remap = searchParams.has("remap");
|
|
12077
|
+
|
|
12078
|
+
if (remap) {
|
|
12079
|
+
const sourcemap = urlInfo.sourcemap;
|
|
12080
|
+
|
|
12081
|
+
if (sourcemap) {
|
|
12082
|
+
const original = await getOriginalPosition({
|
|
12083
|
+
sourcemap,
|
|
12084
|
+
url: file,
|
|
12085
|
+
line,
|
|
12086
|
+
column
|
|
12087
|
+
});
|
|
12088
|
+
line = original.line;
|
|
12089
|
+
column = original.column;
|
|
12090
|
+
}
|
|
12091
|
+
}
|
|
12092
|
+
|
|
12072
12093
|
const codeFrame = stringifyUrlSite({
|
|
12073
12094
|
url: file,
|
|
12074
12095
|
line,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/core",
|
|
3
|
-
"version": "27.6.
|
|
3
|
+
"version": "27.6.1",
|
|
4
4
|
"description": "Tool to develop, test and build js projects",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"@jsenv/log": "3.1.0",
|
|
75
75
|
"@jsenv/node-esm-resolution": "0.1.0",
|
|
76
76
|
"@jsenv/server": "13.0.0",
|
|
77
|
-
"@jsenv/sourcemap": "1.0.
|
|
77
|
+
"@jsenv/sourcemap": "1.0.4",
|
|
78
78
|
"@jsenv/uneval": "1.6.0",
|
|
79
79
|
"@jsenv/url-meta": "7.0.0",
|
|
80
80
|
"@jsenv/urls": "1.2.7",
|
|
@@ -10,6 +10,9 @@ export const formatError = (
|
|
|
10
10
|
const errorMeta = extractErrorMeta(error, { url, line, column })
|
|
11
11
|
|
|
12
12
|
const resolveUrlSite = ({ url, line, column }) => {
|
|
13
|
+
if (typeof line === "string") line = parseInt(line)
|
|
14
|
+
if (typeof column === "string") column = parseInt(column)
|
|
15
|
+
|
|
13
16
|
const inlineUrlMatch = url.match(
|
|
14
17
|
/@L([0-9]+)C([0-9]+)\-L([0-9]+)C([0-9]+)(\.[\w]+)$/,
|
|
15
18
|
)
|
|
@@ -21,7 +24,7 @@ export const formatError = (
|
|
|
21
24
|
const tagColumnEnd = parseInt(inlineUrlMatch[4])
|
|
22
25
|
const extension = inlineUrlMatch[5]
|
|
23
26
|
url = htmlUrl
|
|
24
|
-
line = tagLineStart + (line ===
|
|
27
|
+
line = tagLineStart + (typeof line === "number" ? line : 0)
|
|
25
28
|
// stackTrace formatted by V8 (chrome)
|
|
26
29
|
if (Error.captureStackTrace) {
|
|
27
30
|
line--
|
|
@@ -35,7 +38,7 @@ export const formatError = (
|
|
|
35
38
|
line -= 2
|
|
36
39
|
}
|
|
37
40
|
}
|
|
38
|
-
column = tagColumnStart + (column ===
|
|
41
|
+
column = tagColumnStart + (typeof column === "number" ? column : 0)
|
|
39
42
|
const fileUrl = resolveFileUrl(url)
|
|
40
43
|
return {
|
|
41
44
|
isInline: true,
|
|
@@ -149,9 +152,13 @@ export const formatError = (
|
|
|
149
152
|
}
|
|
150
153
|
}
|
|
151
154
|
if (urlSite.line !== undefined) {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
)
|
|
155
|
+
let ressourceToFetch = `/__get_code_frame__/${formatUrlWithLineAndColumn(
|
|
156
|
+
urlSite,
|
|
157
|
+
)}`
|
|
158
|
+
if (!Error.captureStackTrace) {
|
|
159
|
+
ressourceToFetch += `?remap`
|
|
160
|
+
}
|
|
161
|
+
const response = await window.fetch(ressourceToFetch)
|
|
155
162
|
const codeFrame = await response.text()
|
|
156
163
|
return {
|
|
157
164
|
codeFrame: formatErrorText({ message: codeFrame }),
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
setHtmlNodeText,
|
|
21
21
|
} from "@jsenv/ast"
|
|
22
22
|
import { generateInlineContentUrl, stringifyUrlSite } from "@jsenv/urls"
|
|
23
|
+
import { getOriginalPosition } from "@jsenv/sourcemap"
|
|
23
24
|
|
|
24
25
|
import { requireFromJsenv } from "@jsenv/core/src/require_from_jsenv.js"
|
|
25
26
|
|
|
@@ -46,25 +47,42 @@ export const jsenvPluginHtmlSupervisor = ({
|
|
|
46
47
|
dev: true,
|
|
47
48
|
test: true,
|
|
48
49
|
},
|
|
49
|
-
serve: (request, context) => {
|
|
50
|
+
serve: async (request, context) => {
|
|
50
51
|
if (request.ressource.startsWith("/__get_code_frame__/")) {
|
|
51
|
-
const
|
|
52
|
-
const
|
|
52
|
+
const { pathname, searchParams } = new URL(request.url)
|
|
53
|
+
const urlWithLineAndColumn = pathname.slice(
|
|
54
|
+
"/__get_code_frame__/".length,
|
|
55
|
+
)
|
|
56
|
+
const match = urlWithLineAndColumn.match(/:([0-9]+):([0-9]+)$/)
|
|
53
57
|
if (!match) {
|
|
54
58
|
return {
|
|
55
59
|
status: 400,
|
|
56
60
|
body: "Missing line and column in url",
|
|
57
61
|
}
|
|
58
62
|
}
|
|
59
|
-
const file =
|
|
60
|
-
|
|
61
|
-
|
|
63
|
+
const file = urlWithLineAndColumn.slice(0, match.index)
|
|
64
|
+
let line = parseInt(match[1])
|
|
65
|
+
let column = parseInt(match[2])
|
|
62
66
|
const urlInfo = context.urlGraph.getUrlInfo(file)
|
|
63
67
|
if (!urlInfo) {
|
|
64
68
|
return {
|
|
65
69
|
status: 404,
|
|
66
70
|
}
|
|
67
71
|
}
|
|
72
|
+
const remap = searchParams.has("remap")
|
|
73
|
+
if (remap) {
|
|
74
|
+
const sourcemap = urlInfo.sourcemap
|
|
75
|
+
if (sourcemap) {
|
|
76
|
+
const original = await getOriginalPosition({
|
|
77
|
+
sourcemap,
|
|
78
|
+
url: file,
|
|
79
|
+
line,
|
|
80
|
+
column,
|
|
81
|
+
})
|
|
82
|
+
line = original.line
|
|
83
|
+
column = original.column
|
|
84
|
+
}
|
|
85
|
+
}
|
|
68
86
|
const codeFrame = stringifyUrlSite({
|
|
69
87
|
url: file,
|
|
70
88
|
line,
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import { memoize } from "@jsenv/utils/src/memoize/memoize.js"
|
|
2
|
-
import { remapSourcePosition } from "@jsenv/sourcemap/src/error_stack_remap/remap_source_position.js"
|
|
3
|
-
import { SOURCEMAP } from "@jsenv/sourcemap/src/sourcemap_comment.js"
|
|
4
|
-
import { DATA_URL } from "@jsenv/urls/src/data_url.js"
|
|
5
|
-
|
|
6
|
-
const loadSourceMapConsumer = memoize(async () => {
|
|
7
|
-
const script = document.createElement("script")
|
|
8
|
-
script.src = "https://unpkg.com/source-map@0.7.3/dist/source-map.js"
|
|
9
|
-
|
|
10
|
-
const scriptLoadedPromise = new Promise((resolve) => {
|
|
11
|
-
script.onload = resolve
|
|
12
|
-
})
|
|
13
|
-
document.head.appendChild(script)
|
|
14
|
-
await scriptLoadedPromise
|
|
15
|
-
const { SourceMapConsumer } = window.sourceMap
|
|
16
|
-
await SourceMapConsumer.initialize({
|
|
17
|
-
"lib/mappings.wasm": "https://unpkg.com/source-map@0.7.3/lib/mappings.wasm",
|
|
18
|
-
})
|
|
19
|
-
return SourceMapConsumer
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
export const remapErrorSite = async ({ url, line, column }) => {
|
|
23
|
-
const asServerUrl = (url) => {
|
|
24
|
-
if (url.startsWith("file:///")) {
|
|
25
|
-
url = `${window.origin}/@fs/${url.slice("file:///".length)}`
|
|
26
|
-
}
|
|
27
|
-
return url
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const SourceMapConsumer = await loadSourceMapConsumer()
|
|
31
|
-
const original = await remapSourcePosition({
|
|
32
|
-
source: url,
|
|
33
|
-
line,
|
|
34
|
-
column,
|
|
35
|
-
resolveFile: (specifier) => new URL(specifier, `${window.origin}/`).href,
|
|
36
|
-
urlToSourcemapConsumer: async (url) => {
|
|
37
|
-
const serverUrl = asServerUrl(url)
|
|
38
|
-
const fileResponse = await window.fetch(serverUrl)
|
|
39
|
-
const text = await fileResponse.text()
|
|
40
|
-
const jsSourcemapComment = SOURCEMAP.readComment({
|
|
41
|
-
contentType: "text/javascript",
|
|
42
|
-
content: text,
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
const jsSourcemapUrl = jsSourcemapComment.specifier
|
|
46
|
-
let sourcemapUrl
|
|
47
|
-
let sourcemapUrlContent
|
|
48
|
-
if (jsSourcemapUrl.startsWith("data:")) {
|
|
49
|
-
sourcemapUrl = url
|
|
50
|
-
sourcemapUrlContent = window.atob(DATA_URL.parse(jsSourcemapUrl).data)
|
|
51
|
-
} else {
|
|
52
|
-
sourcemapUrl = new URL(jsSourcemapUrl, url).href
|
|
53
|
-
const sourcemapResponse = await window.fetch(sourcemapUrl)
|
|
54
|
-
sourcemapUrlContent = await sourcemapResponse.text()
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const sourceMap = JSON.parse(sourcemapUrlContent)
|
|
58
|
-
let { sourcesContent } = sourceMap
|
|
59
|
-
if (!sourcesContent) {
|
|
60
|
-
sourcesContent = []
|
|
61
|
-
sourceMap.sourcesContent = sourcesContent
|
|
62
|
-
}
|
|
63
|
-
let firstSourceMapSourceFailure = null
|
|
64
|
-
await Promise.all(
|
|
65
|
-
sourceMap.sources.map(async (source, index) => {
|
|
66
|
-
if (index in sourcesContent) return
|
|
67
|
-
let sourceUrl = new URL(source, sourcemapUrl).href
|
|
68
|
-
sourceUrl = asServerUrl(sourceUrl)
|
|
69
|
-
try {
|
|
70
|
-
const sourceResponse = await window.fetch(sourceUrl)
|
|
71
|
-
const sourceContent = await sourceResponse.text()
|
|
72
|
-
sourcesContent[index] = sourceContent
|
|
73
|
-
} catch (e) {
|
|
74
|
-
firstSourceMapSourceFailure = e
|
|
75
|
-
}
|
|
76
|
-
}),
|
|
77
|
-
)
|
|
78
|
-
if (firstSourceMapSourceFailure) {
|
|
79
|
-
return null
|
|
80
|
-
}
|
|
81
|
-
return new SourceMapConsumer(sourceMap)
|
|
82
|
-
},
|
|
83
|
-
})
|
|
84
|
-
return original
|
|
85
|
-
}
|