@jsenv/core 27.0.0-alpha.50 → 27.0.0-alpha.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/build/build.js +5 -3
- package/src/build/build_urls_generator.js +1 -1
- package/src/execute/runtimes/browsers/from_playwright.js +3 -0
- package/src/omega/kitchen.js +6 -0
- package/src/omega/url_graph/url_graph_load.js +4 -0
- package/src/plugins/bundling/css/bundle_css.js +127 -8
- package/src/plugins/html_supervisor/jsenv_plugin_html_supervisor.js +0 -3
- package/src/plugins/inline/jsenv_plugin_js_inline_content.js +3 -2
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js +9 -1
- package/src/plugins/transpilation/import_assertions/jsenv_plugin_import_assertions.js +2 -2
- package/src/plugins/url_analysis/css/css_urls.js +14 -7
- package/src/test/logs_file_execution.js +1 -1
- package/src/omega/url_graph/url_graph_sort.js +0 -29
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/core",
|
|
3
|
-
"version": "27.0.0-alpha.
|
|
3
|
+
"version": "27.0.0-alpha.53",
|
|
4
4
|
"description": "Tool to develop, test and build js projects",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"@jsenv/node-esm-resolution": "0.0.6",
|
|
69
69
|
"@jsenv/server": "12.6.2",
|
|
70
70
|
"@jsenv/uneval": "1.6.0",
|
|
71
|
-
"@jsenv/utils": "1.7.
|
|
71
|
+
"@jsenv/utils": "1.7.2",
|
|
72
72
|
"construct-style-sheets-polyfill": "3.1.0",
|
|
73
73
|
"cssnano": "5.1.7",
|
|
74
74
|
"cssnano-preset-default": "5.2.7",
|
package/src/build/build.js
CHANGED
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
parseHtmlString,
|
|
30
30
|
stringifyHtmlAst,
|
|
31
31
|
} from "@jsenv/utils/html_ast/html_ast.js"
|
|
32
|
+
import { sortByDependencies } from "@jsenv/utils/graph/sort_by_dependencies.js"
|
|
32
33
|
|
|
33
34
|
import { jsenvPluginUrlAnalysis } from "../plugins/url_analysis/jsenv_plugin_url_analysis.js"
|
|
34
35
|
import { jsenvPluginInline } from "../plugins/inline/jsenv_plugin_inline.js"
|
|
@@ -38,7 +39,6 @@ import { getCorePlugins } from "../plugins/plugins.js"
|
|
|
38
39
|
import { createKitchen } from "../omega/kitchen.js"
|
|
39
40
|
import { loadUrlGraph } from "../omega/url_graph/url_graph_load.js"
|
|
40
41
|
import { createUrlGraphSummary } from "../omega/url_graph/url_graph_report.js"
|
|
41
|
-
import { sortUrlGraphByDependencies } from "../omega/url_graph/url_graph_sort.js"
|
|
42
42
|
import { isWebWorkerEntryPointReference } from "../omega/web_workers.js"
|
|
43
43
|
|
|
44
44
|
import { GRAPH } from "./graph_utils.js"
|
|
@@ -618,6 +618,7 @@ ${Object.keys(rawGraph.urlInfos).join("\n")}`,
|
|
|
618
618
|
urlGraph: finalGraph,
|
|
619
619
|
kitchen: finalGraphKitchen,
|
|
620
620
|
outDirectoryUrl: new URL(".jsenv/postbuild/", rootDirectoryUrl),
|
|
621
|
+
skipRessourceHint: true,
|
|
621
622
|
startLoading: (cookEntryFile) => {
|
|
622
623
|
entryUrls.forEach((entryUrl) => {
|
|
623
624
|
const [, postBuildEntryUrlInfo] = cookEntryFile({
|
|
@@ -698,7 +699,7 @@ ${Object.keys(finalGraph.urlInfos).join("\n")}`,
|
|
|
698
699
|
urlInfo.dependents.size === 0
|
|
699
700
|
) {
|
|
700
701
|
cleanupActions.push(() => {
|
|
701
|
-
|
|
702
|
+
finalGraph.deleteUrlInfo(urlInfo.url)
|
|
702
703
|
})
|
|
703
704
|
}
|
|
704
705
|
})
|
|
@@ -783,7 +784,7 @@ const applyUrlVersioning = async ({
|
|
|
783
784
|
}) => {
|
|
784
785
|
const versioningTask = createTaskLog(logger, "inject version in urls")
|
|
785
786
|
try {
|
|
786
|
-
const urlsSorted =
|
|
787
|
+
const urlsSorted = sortByDependencies(finalGraph.urlInfos)
|
|
787
788
|
urlsSorted.forEach((url) => {
|
|
788
789
|
if (url.startsWith("data:")) {
|
|
789
790
|
return
|
|
@@ -969,6 +970,7 @@ const applyUrlVersioning = async ({
|
|
|
969
970
|
await loadUrlGraph({
|
|
970
971
|
urlGraph: finalGraph,
|
|
971
972
|
kitchen: versioningKitchen,
|
|
973
|
+
skipRessourceHint: true,
|
|
972
974
|
startLoading: (cookEntryFile) => {
|
|
973
975
|
postBuildEntryUrls.forEach((postBuildEntryUrl) => {
|
|
974
976
|
cookEntryFile({
|
|
@@ -56,8 +56,8 @@ export const createBuilUrlsGenerator = ({ buildDirectoryUrl }) => {
|
|
|
56
56
|
// To keep in mind: if you have "user.jsx" and "user.js" AND both file are not bundled
|
|
57
57
|
// you end up with "dist/js/user.js" and "dist/js/user2.js"
|
|
58
58
|
const extensionMappings = {
|
|
59
|
-
".ts": ".js",
|
|
60
59
|
".jsx": ".js",
|
|
60
|
+
".ts": ".js",
|
|
61
61
|
".tsx": ".js",
|
|
62
62
|
}
|
|
63
63
|
|
|
@@ -262,6 +262,9 @@ export const createRuntimeFromPlaywright = ({
|
|
|
262
262
|
cb({ reason: "page closed" })
|
|
263
263
|
})
|
|
264
264
|
cleanupCallbackList.add(closePage)
|
|
265
|
+
cleanupCallbackList.add(() => {
|
|
266
|
+
browser.removeListener("disconnected", disconnectedCallback)
|
|
267
|
+
})
|
|
265
268
|
const notifyPrevious = stopAfterAllSignal.notify
|
|
266
269
|
stopAfterAllSignal.notify = async () => {
|
|
267
270
|
await notifyPrevious()
|
package/src/omega/kitchen.js
CHANGED
|
@@ -164,6 +164,12 @@ export const createKitchen = ({
|
|
|
164
164
|
if (returnValue === reference.url) {
|
|
165
165
|
return
|
|
166
166
|
}
|
|
167
|
+
const normalizedReturnValue = returnValue.startsWith("data:")
|
|
168
|
+
? returnValue
|
|
169
|
+
: returnValue.replace(/[=](?=&|$)/g, "")
|
|
170
|
+
if (normalizedReturnValue === reference.url) {
|
|
171
|
+
return
|
|
172
|
+
}
|
|
167
173
|
const previousReference = { ...reference }
|
|
168
174
|
reference.url = returnValue
|
|
169
175
|
mutateReference(previousReference, reference)
|
|
@@ -6,6 +6,7 @@ export const loadUrlGraph = async ({
|
|
|
6
6
|
startLoading,
|
|
7
7
|
outDirectoryUrl,
|
|
8
8
|
clientRuntimeCompat,
|
|
9
|
+
skipRessourceHint = false,
|
|
9
10
|
}) => {
|
|
10
11
|
if (outDirectoryUrl) {
|
|
11
12
|
await ensureEmptyDirectory(outDirectoryUrl)
|
|
@@ -33,6 +34,9 @@ export const loadUrlGraph = async ({
|
|
|
33
34
|
})
|
|
34
35
|
const { references } = urlInfo
|
|
35
36
|
references.forEach((reference) => {
|
|
37
|
+
if (skipRessourceHint && reference.isRessourceHint) {
|
|
38
|
+
return
|
|
39
|
+
}
|
|
36
40
|
// we use reference.generatedUrl to mimic what a browser would do:
|
|
37
41
|
// do a fetch to the specifier as found in the file
|
|
38
42
|
const referencedUrlInfo = urlGraph.reuseOrCreateUrlInfo(
|
|
@@ -1,21 +1,140 @@
|
|
|
1
|
-
|
|
1
|
+
/*
|
|
2
|
+
* Each @import found in css is replaced by the file content
|
|
3
|
+
* - There is no need to worry about urls (such as background-image: url())
|
|
4
|
+
* because they are absolute (file://*) and will be made relative again by jsenv build
|
|
5
|
+
* - The sourcemap are not generated but ideally they should be
|
|
6
|
+
* It can be quite challenging, see "bundle_sourcemap.js"
|
|
7
|
+
*/
|
|
2
8
|
|
|
9
|
+
import { applyPostCss } from "@jsenv/utils/css_ast/apply_post_css.js"
|
|
10
|
+
import { postCssPluginUrlVisitor } from "@jsenv/utils/css_ast/postcss_plugin_url_visitor.js"
|
|
11
|
+
import { createMagicSource } from "@jsenv/utils/sourcemap/magic_source.js"
|
|
12
|
+
import { sortByDependencies } from "@jsenv/utils/graph/sort_by_dependencies.js"
|
|
13
|
+
|
|
14
|
+
// Do not use until https://github.com/parcel-bundler/parcel-css/issues/181
|
|
3
15
|
export const bundleCss = async ({ cssUrlInfos, context }) => {
|
|
4
16
|
const bundledCssUrlInfos = {}
|
|
17
|
+
const cssBundleInfos = await performCssBundling({
|
|
18
|
+
cssEntryUrlInfos: cssUrlInfos,
|
|
19
|
+
context,
|
|
20
|
+
})
|
|
5
21
|
cssUrlInfos.forEach((cssUrlInfo) => {
|
|
6
|
-
const { code, map } = bundleWithParcel(cssUrlInfo, context)
|
|
7
|
-
const content = String(code)
|
|
8
|
-
const sourcemap = map
|
|
9
|
-
// here we need to replace css urls to ensure
|
|
10
|
-
// all urls targets the correct stuff
|
|
11
22
|
bundledCssUrlInfos[cssUrlInfo.url] = {
|
|
12
23
|
data: {
|
|
13
24
|
generatedBy: "parcel",
|
|
14
25
|
},
|
|
15
26
|
contentType: "text/css",
|
|
16
|
-
content,
|
|
17
|
-
sourcemap,
|
|
27
|
+
content: cssBundleInfos[cssUrlInfo.url].bundleContent,
|
|
18
28
|
}
|
|
19
29
|
})
|
|
20
30
|
return bundledCssUrlInfos
|
|
21
31
|
}
|
|
32
|
+
|
|
33
|
+
const performCssBundling = async ({ cssEntryUrlInfos, context }) => {
|
|
34
|
+
const cssBundleInfos = await loadCssUrls({
|
|
35
|
+
cssEntryUrlInfos,
|
|
36
|
+
context,
|
|
37
|
+
})
|
|
38
|
+
const cssUrlsSorted = sortByDependencies(cssBundleInfos)
|
|
39
|
+
cssUrlsSorted.forEach((cssUrl) => {
|
|
40
|
+
const cssBundleInfo = cssBundleInfos[cssUrl]
|
|
41
|
+
const magicSource = createMagicSource(cssBundleInfo.content)
|
|
42
|
+
cssBundleInfo.cssUrls.forEach((cssUrl) => {
|
|
43
|
+
if (cssUrl.type === "@import") {
|
|
44
|
+
magicSource.replace({
|
|
45
|
+
start: cssUrl.atRuleStart,
|
|
46
|
+
end: cssUrl.atRuleEnd,
|
|
47
|
+
replacement: cssBundleInfos[cssUrl.url].bundleContent,
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
const { content } = magicSource.toContentAndSourcemap()
|
|
52
|
+
cssBundleInfo.bundleContent = content.trim()
|
|
53
|
+
})
|
|
54
|
+
return cssBundleInfos
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const parseCssUrls = async ({ css, url }) => {
|
|
58
|
+
const cssUrls = []
|
|
59
|
+
await applyPostCss({
|
|
60
|
+
sourcemaps: false,
|
|
61
|
+
plugins: [
|
|
62
|
+
postCssPluginUrlVisitor({
|
|
63
|
+
urlVisitor: ({
|
|
64
|
+
type,
|
|
65
|
+
specifier,
|
|
66
|
+
specifierStart,
|
|
67
|
+
specifierEnd,
|
|
68
|
+
atRuleStart,
|
|
69
|
+
atRuleEnd,
|
|
70
|
+
}) => {
|
|
71
|
+
cssUrls.push({
|
|
72
|
+
type,
|
|
73
|
+
url: new URL(specifier, url).href,
|
|
74
|
+
specifierStart,
|
|
75
|
+
specifierEnd,
|
|
76
|
+
atRuleStart,
|
|
77
|
+
atRuleEnd,
|
|
78
|
+
})
|
|
79
|
+
},
|
|
80
|
+
}),
|
|
81
|
+
],
|
|
82
|
+
url,
|
|
83
|
+
content: css,
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
return cssUrls
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const loadCssUrls = async ({ cssEntryUrlInfos, context }) => {
|
|
90
|
+
const cssBundleInfos = {}
|
|
91
|
+
const promises = []
|
|
92
|
+
const promiseMap = new Map()
|
|
93
|
+
|
|
94
|
+
const load = (cssUrlInfo) => {
|
|
95
|
+
const promiseFromData = promiseMap.get(cssUrlInfo.url)
|
|
96
|
+
if (promiseFromData) return promiseFromData
|
|
97
|
+
const promise = _load(cssUrlInfo)
|
|
98
|
+
promises.push(promise)
|
|
99
|
+
promiseMap.set(cssUrlInfo.url, promise)
|
|
100
|
+
return promise
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const _load = async (cssUrlInfo) => {
|
|
104
|
+
const cssUrls = await parseCssUrls({
|
|
105
|
+
css: cssUrlInfo.content,
|
|
106
|
+
url: cssUrlInfo.url,
|
|
107
|
+
})
|
|
108
|
+
const cssBundleInfo = {
|
|
109
|
+
content: cssUrlInfo.content,
|
|
110
|
+
cssUrls,
|
|
111
|
+
dependencies: [],
|
|
112
|
+
}
|
|
113
|
+
cssBundleInfos[cssUrlInfo.url] = cssBundleInfo
|
|
114
|
+
cssUrls.forEach((cssUrl) => {
|
|
115
|
+
if (cssUrl.type === "@import") {
|
|
116
|
+
cssBundleInfo.dependencies.push(cssUrl.url)
|
|
117
|
+
const importedCssUrlInfo = context.urlGraph.getUrlInfo(cssUrl.url)
|
|
118
|
+
load(importedCssUrlInfo)
|
|
119
|
+
}
|
|
120
|
+
})
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
cssEntryUrlInfos.forEach((cssEntryUrlInfo) => {
|
|
124
|
+
load(cssEntryUrlInfo)
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
const waitAll = async () => {
|
|
128
|
+
if (promises.length === 0) {
|
|
129
|
+
return
|
|
130
|
+
}
|
|
131
|
+
const promisesToWait = promises.slice()
|
|
132
|
+
promises.length = 0
|
|
133
|
+
await Promise.all(promisesToWait)
|
|
134
|
+
await waitAll()
|
|
135
|
+
}
|
|
136
|
+
await waitAll()
|
|
137
|
+
promiseMap.clear()
|
|
138
|
+
|
|
139
|
+
return cssBundleInfos
|
|
140
|
+
}
|
|
@@ -147,9 +147,6 @@ export const jsenvPluginHtmlSupervisor = ({
|
|
|
147
147
|
return
|
|
148
148
|
}
|
|
149
149
|
})
|
|
150
|
-
if (scriptsToSupervise.length === 0) {
|
|
151
|
-
return null
|
|
152
|
-
}
|
|
153
150
|
const [htmlSupervisorInstallerFileReference] = referenceUtils.inject({
|
|
154
151
|
type: "js_import_export",
|
|
155
152
|
expectedType: "js_module",
|
|
@@ -274,8 +274,9 @@ const getOriginalName = (path, name) => {
|
|
|
274
274
|
return getOriginalName(path, importedName)
|
|
275
275
|
}
|
|
276
276
|
if (binding.path.type === "VariableDeclarator") {
|
|
277
|
-
|
|
278
|
-
|
|
277
|
+
const { init } = binding.path.node
|
|
278
|
+
if (init && init.type === "Identifier") {
|
|
279
|
+
const previousName = init.name
|
|
279
280
|
return getOriginalName(path, previousName)
|
|
280
281
|
}
|
|
281
282
|
}
|
|
@@ -119,7 +119,15 @@ const asJsClassic = ({ systemJsInjection, systemJsClientFileUrl }) => {
|
|
|
119
119
|
|
|
120
120
|
const generateJsClassicFilename = (url) => {
|
|
121
121
|
const filename = urlToFilename(url)
|
|
122
|
-
|
|
122
|
+
let [basename, extension] = splitFileExtension(filename)
|
|
123
|
+
const { searchParams } = new URL(url)
|
|
124
|
+
if (
|
|
125
|
+
searchParams.has("as_json_module") ||
|
|
126
|
+
searchParams.has("as_css_module") ||
|
|
127
|
+
searchParams.has("as_text_module")
|
|
128
|
+
) {
|
|
129
|
+
extension = ".js"
|
|
130
|
+
}
|
|
123
131
|
return `${basename}.es5${extension}`
|
|
124
132
|
}
|
|
125
133
|
|
|
@@ -27,10 +27,10 @@ export const jsenvPluginImportAssertions = () => {
|
|
|
27
27
|
end: reference.assertNode.end,
|
|
28
28
|
})
|
|
29
29
|
}
|
|
30
|
-
|
|
31
|
-
return injectQueryParams(reference.url, {
|
|
30
|
+
const newUrl = injectQueryParams(reference.url, {
|
|
32
31
|
[searchParam]: "",
|
|
33
32
|
})
|
|
33
|
+
return newUrl
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
const importAssertions = {
|
|
@@ -13,19 +13,26 @@ export const parseAndTransformCssUrls = async (urlInfo, context) => {
|
|
|
13
13
|
sourcemaps: false,
|
|
14
14
|
plugins: [
|
|
15
15
|
postCssPluginUrlVisitor({
|
|
16
|
-
urlVisitor: ({
|
|
16
|
+
urlVisitor: ({
|
|
17
|
+
type,
|
|
18
|
+
specifier,
|
|
19
|
+
specifierStart,
|
|
20
|
+
specifierEnd,
|
|
21
|
+
specifierLine,
|
|
22
|
+
specifierColumn,
|
|
23
|
+
}) => {
|
|
17
24
|
const [reference] = context.referenceUtils.found({
|
|
18
25
|
type: `css_${type}`,
|
|
19
26
|
specifier,
|
|
20
|
-
specifierStart
|
|
21
|
-
specifierEnd
|
|
22
|
-
specifierLine
|
|
23
|
-
specifierColumn
|
|
27
|
+
specifierStart,
|
|
28
|
+
specifierEnd,
|
|
29
|
+
specifierLine,
|
|
30
|
+
specifierColumn,
|
|
24
31
|
})
|
|
25
32
|
actions.push(async () => {
|
|
26
33
|
magicSource.replace({
|
|
27
|
-
start,
|
|
28
|
-
end,
|
|
34
|
+
start: specifierStart,
|
|
35
|
+
end: specifierEnd,
|
|
29
36
|
replacement: await context.referenceUtils.readGeneratedSpecifier(
|
|
30
37
|
reference,
|
|
31
38
|
),
|
|
@@ -60,7 +60,7 @@ export const formatExecutionResult = (
|
|
|
60
60
|
file: fileRelativeUrl,
|
|
61
61
|
runtime: `${runtimeName}/${runtimeVersion}`,
|
|
62
62
|
duration: msAsDuration(duration),
|
|
63
|
-
...(error ? { error: error.stack } : {}),
|
|
63
|
+
...(error ? { error: error.stack || error.message || error } : {}),
|
|
64
64
|
},
|
|
65
65
|
consoleOutput,
|
|
66
66
|
})
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
export const sortUrlGraphByDependencies = (urlGraph) => {
|
|
2
|
-
const { urlInfos } = urlGraph
|
|
3
|
-
|
|
4
|
-
const visited = []
|
|
5
|
-
const sorted = []
|
|
6
|
-
const circular = []
|
|
7
|
-
const visit = (url) => {
|
|
8
|
-
const isSorted = sorted.includes(url)
|
|
9
|
-
if (isSorted) {
|
|
10
|
-
return
|
|
11
|
-
}
|
|
12
|
-
const isVisited = visited.includes(url)
|
|
13
|
-
if (isVisited) {
|
|
14
|
-
circular.push(url)
|
|
15
|
-
sorted.push(url)
|
|
16
|
-
} else {
|
|
17
|
-
visited.push(url)
|
|
18
|
-
urlInfos[url].dependencies.forEach((dependencyUrl) => {
|
|
19
|
-
visit(dependencyUrl, url)
|
|
20
|
-
})
|
|
21
|
-
sorted.push(url)
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
Object.keys(urlInfos).forEach((url) => {
|
|
25
|
-
visit(url)
|
|
26
|
-
})
|
|
27
|
-
sorted.circular = circular
|
|
28
|
-
return sorted
|
|
29
|
-
}
|