@jsenv/core 27.0.0-alpha.5 → 27.0.0-alpha.8
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 +3 -4
- package/src/build/build.js +47 -16
- package/src/build/build_urls_generator.js +16 -7
- package/src/build/plugins/bundle_js_module/jsenv_plugin_bundle_js_module.js +16 -14
- package/src/omega/core_plugins/babel/helpers/babel_plugin_structure.js +1 -4
- package/src/omega/core_plugins/babel/jsenv_plugin_babel.js +18 -4
- package/src/omega/core_plugins/inline/jsenv_plugin_new_inline_content.js +1 -4
- package/src/omega/kitchen.js +3 -13
- package/src/omega/runtime_support/features_compatibility.js +40 -1
- package/src/omega/runtime_support/runtime_support.js +48 -16
- package/src/omega/url_graph/url_graph_load.js +1 -0
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.8",
|
|
4
4
|
"description": "Tool to develop, test and build js projects",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -11,8 +11,7 @@
|
|
|
11
11
|
"node": ">=16.13.0"
|
|
12
12
|
},
|
|
13
13
|
"publishConfig": {
|
|
14
|
-
"access": "public"
|
|
15
|
-
"registry": "https://registry.npmjs.org"
|
|
14
|
+
"access": "public"
|
|
16
15
|
},
|
|
17
16
|
"type": "module",
|
|
18
17
|
"imports": {},
|
|
@@ -107,4 +106,4 @@
|
|
|
107
106
|
"redux": "4.1.2",
|
|
108
107
|
"rollup": "2.70.1"
|
|
109
108
|
}
|
|
110
|
-
}
|
|
109
|
+
}
|
package/src/build/build.js
CHANGED
|
@@ -70,6 +70,8 @@ export const build = async ({
|
|
|
70
70
|
writeOnFileSystem = true,
|
|
71
71
|
buildDirectoryClean = true,
|
|
72
72
|
baseUrl = "/",
|
|
73
|
+
assetManifest = true,
|
|
74
|
+
assetManifestFileRelativeUrl = "asset-manifest.json",
|
|
73
75
|
}) => {
|
|
74
76
|
const logger = createLogger({ logLevel })
|
|
75
77
|
rootDirectoryUrl = assertAndNormalizeDirectoryUrl(rootDirectoryUrl)
|
|
@@ -84,7 +86,7 @@ export const build = async ({
|
|
|
84
86
|
const entryPointKeys = Object.keys(entryPoints)
|
|
85
87
|
if (entryPointKeys.length === 1) {
|
|
86
88
|
logger.info(`
|
|
87
|
-
build ${entryPointKeys[0]}`)
|
|
89
|
+
build "${entryPointKeys[0]}"`)
|
|
88
90
|
} else {
|
|
89
91
|
logger.info(`
|
|
90
92
|
build ${entryPointKeys.length} entry points`)
|
|
@@ -119,22 +121,23 @@ build ${entryPointKeys.length} entry points`)
|
|
|
119
121
|
scenario: "build",
|
|
120
122
|
sourcemaps,
|
|
121
123
|
})
|
|
122
|
-
const
|
|
123
|
-
Object.keys(entryPoints).forEach((key) => {
|
|
124
|
-
cookEntryFile({
|
|
125
|
-
trace: `"${key}" in entryPoints parameter`,
|
|
126
|
-
type: "entry_point",
|
|
127
|
-
specifier: key,
|
|
128
|
-
})
|
|
129
|
-
})
|
|
130
|
-
}
|
|
124
|
+
const entryUrls = []
|
|
131
125
|
try {
|
|
132
126
|
await loadUrlGraph({
|
|
133
127
|
urlGraph: rawGraph,
|
|
134
128
|
kitchen: rawGraphKitchen,
|
|
135
129
|
outDirectoryUrl: new URL(`.jsenv/build/`, rootDirectoryUrl),
|
|
136
130
|
runtimeSupport,
|
|
137
|
-
startLoading:
|
|
131
|
+
startLoading: (cookEntryFile) => {
|
|
132
|
+
Object.keys(entryPoints).forEach((key) => {
|
|
133
|
+
const [, entryUrlInfo] = cookEntryFile({
|
|
134
|
+
trace: `"${key}" in entryPoints parameter`,
|
|
135
|
+
type: "entry_point",
|
|
136
|
+
specifier: key,
|
|
137
|
+
})
|
|
138
|
+
entryUrls.push(entryUrlInfo.url)
|
|
139
|
+
})
|
|
140
|
+
},
|
|
138
141
|
})
|
|
139
142
|
} catch (e) {
|
|
140
143
|
prebuildTask.fail()
|
|
@@ -447,13 +450,23 @@ ${Object.keys(rawGraph.urlInfos).join("\n")}`,
|
|
|
447
450
|
sourcemaps,
|
|
448
451
|
})
|
|
449
452
|
const buildTask = createTaskLog(logger, "build")
|
|
453
|
+
const postBuildEntryUrls = []
|
|
450
454
|
try {
|
|
451
455
|
await loadUrlGraph({
|
|
452
456
|
urlGraph: finalGraph,
|
|
453
457
|
kitchen: finalGraphKitchen,
|
|
454
458
|
outDirectoryUrl: new URL(".jsenv/postbuild/", rootDirectoryUrl),
|
|
455
459
|
runtimeSupport,
|
|
456
|
-
startLoading:
|
|
460
|
+
startLoading: (cookEntryFile) => {
|
|
461
|
+
entryUrls.forEach((entryUrl) => {
|
|
462
|
+
const [, postBuildEntryUrlInfo] = cookEntryFile({
|
|
463
|
+
trace: `entryPoint`,
|
|
464
|
+
type: "entry_point",
|
|
465
|
+
specifier: entryUrl,
|
|
466
|
+
})
|
|
467
|
+
postBuildEntryUrls.push(postBuildEntryUrlInfo.url)
|
|
468
|
+
})
|
|
469
|
+
},
|
|
457
470
|
})
|
|
458
471
|
} catch (e) {
|
|
459
472
|
buildTask.fail()
|
|
@@ -540,12 +553,12 @@ ${Object.keys(finalGraph.urlInfos).join("\n")}`,
|
|
|
540
553
|
{
|
|
541
554
|
name: "jsenv:versioning",
|
|
542
555
|
appliesDuring: { build: true },
|
|
543
|
-
resolve: (
|
|
544
|
-
const buildUrl = buildUrls[specifier]
|
|
556
|
+
resolve: (reference) => {
|
|
557
|
+
const buildUrl = buildUrls[reference.specifier]
|
|
545
558
|
if (buildUrl) {
|
|
546
559
|
return buildUrl
|
|
547
560
|
}
|
|
548
|
-
const url = new URL(specifier, parentUrl).href
|
|
561
|
+
const url = new URL(reference.specifier, reference.parentUrl).href
|
|
549
562
|
return url
|
|
550
563
|
},
|
|
551
564
|
formatReferencedUrl: (reference) => {
|
|
@@ -616,7 +629,15 @@ ${Object.keys(finalGraph.urlInfos).join("\n")}`,
|
|
|
616
629
|
urlGraph: finalGraph,
|
|
617
630
|
kitchen: versioningKitchen,
|
|
618
631
|
runtimeSupport,
|
|
619
|
-
startLoading:
|
|
632
|
+
startLoading: (cookEntryFile) => {
|
|
633
|
+
postBuildEntryUrls.forEach((postBuildEntryUrl) => {
|
|
634
|
+
cookEntryFile({
|
|
635
|
+
trace: `entryPoint`,
|
|
636
|
+
type: "entry_point",
|
|
637
|
+
specifier: postBuildEntryUrl,
|
|
638
|
+
})
|
|
639
|
+
})
|
|
640
|
+
},
|
|
620
641
|
})
|
|
621
642
|
if (usedVersionMappings.length) {
|
|
622
643
|
const versionMappingsNeeded = {}
|
|
@@ -689,6 +710,16 @@ ${Object.keys(finalGraph.urlInfos).join("\n")}`,
|
|
|
689
710
|
)
|
|
690
711
|
}),
|
|
691
712
|
)
|
|
713
|
+
if (
|
|
714
|
+
versioning !== "none" &&
|
|
715
|
+
assetManifest &&
|
|
716
|
+
Object.keys(buildManifest).length
|
|
717
|
+
) {
|
|
718
|
+
await writeFile(
|
|
719
|
+
new URL(assetManifestFileRelativeUrl, buildDirectoryUrl),
|
|
720
|
+
JSON.stringify(buildManifest, null, " "),
|
|
721
|
+
)
|
|
722
|
+
}
|
|
692
723
|
}
|
|
693
724
|
logger.info(createUrlGraphSummary(finalGraph, { title: "build files" }))
|
|
694
725
|
return {
|
|
@@ -6,6 +6,12 @@ export const createBuilUrlsGenerator = ({ buildDirectoryUrl }) => {
|
|
|
6
6
|
const cache = {}
|
|
7
7
|
const generate = memoizeByUrl((url, urlInfo, parentUrlInfo) => {
|
|
8
8
|
const directoryPath = determineDirectoryPath(urlInfo, parentUrlInfo)
|
|
9
|
+
let names = cache[directoryPath]
|
|
10
|
+
if (!names) {
|
|
11
|
+
names = []
|
|
12
|
+
cache[directoryPath] = names
|
|
13
|
+
}
|
|
14
|
+
|
|
9
15
|
let name = urlToFilename(url)
|
|
10
16
|
const { searchParams } = new URL(url)
|
|
11
17
|
if (
|
|
@@ -15,12 +21,7 @@ export const createBuilUrlsGenerator = ({ buildDirectoryUrl }) => {
|
|
|
15
21
|
) {
|
|
16
22
|
name = `${name}.js`
|
|
17
23
|
}
|
|
18
|
-
|
|
19
|
-
if (!names) {
|
|
20
|
-
names = []
|
|
21
|
-
cache[directoryPath] = names
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
+
const [basename, extension] = splitFileExtension(name)
|
|
24
25
|
let nameCandidate = name
|
|
25
26
|
let integer = 1
|
|
26
27
|
// eslint-disable-next-line no-constant-condition
|
|
@@ -30,7 +31,7 @@ export const createBuilUrlsGenerator = ({ buildDirectoryUrl }) => {
|
|
|
30
31
|
break
|
|
31
32
|
}
|
|
32
33
|
integer++
|
|
33
|
-
nameCandidate = `${
|
|
34
|
+
nameCandidate = `${basename}${integer}${extension}`
|
|
34
35
|
}
|
|
35
36
|
return `${buildDirectoryUrl}${directoryPath}${nameCandidate}`
|
|
36
37
|
})
|
|
@@ -40,6 +41,14 @@ export const createBuilUrlsGenerator = ({ buildDirectoryUrl }) => {
|
|
|
40
41
|
}
|
|
41
42
|
}
|
|
42
43
|
|
|
44
|
+
const splitFileExtension = (filename) => {
|
|
45
|
+
const dotLastIndex = filename.lastIndexOf(".")
|
|
46
|
+
if (dotLastIndex === -1) {
|
|
47
|
+
return [filename, ""]
|
|
48
|
+
}
|
|
49
|
+
return [filename.slice(0, dotLastIndex), filename.slice(dotLastIndex)]
|
|
50
|
+
}
|
|
51
|
+
|
|
43
52
|
const determineDirectoryPath = (urlInfo, parentUrlInfo) => {
|
|
44
53
|
if (urlInfo.isInline) {
|
|
45
54
|
const parentDirectoryPath = determineDirectoryPath(parentUrlInfo)
|
|
@@ -131,15 +131,6 @@ const rollupPluginJsenv = ({
|
|
|
131
131
|
const rollupFileInfo = rollupResult[fileName]
|
|
132
132
|
// there is 3 types of file: "placeholder", "asset", "chunk"
|
|
133
133
|
if (rollupFileInfo.type === "chunk") {
|
|
134
|
-
const { facadeModuleId } = rollupFileInfo
|
|
135
|
-
let url
|
|
136
|
-
if (facadeModuleId) {
|
|
137
|
-
url = fileUrlConverter.asFileUrl(facadeModuleId)
|
|
138
|
-
} else {
|
|
139
|
-
const { sources } = rollupFileInfo.map
|
|
140
|
-
const sourcePath = sources[sources.length - 1]
|
|
141
|
-
url = fileUrlConverter.asFileUrl(sourcePath)
|
|
142
|
-
}
|
|
143
134
|
const jsModuleBundleUrlInfo = {
|
|
144
135
|
// buildRelativeUrl: rollupFileInfo.fileName,
|
|
145
136
|
data: {
|
|
@@ -149,6 +140,12 @@ const rollupPluginJsenv = ({
|
|
|
149
140
|
content: rollupFileInfo.code,
|
|
150
141
|
sourcemap: rollupFileInfo.map,
|
|
151
142
|
}
|
|
143
|
+
let url
|
|
144
|
+
if (rollupFileInfo.facadeModuleId) {
|
|
145
|
+
url = fileUrlConverter.asFileUrl(rollupFileInfo.facadeModuleId)
|
|
146
|
+
} else {
|
|
147
|
+
url = new URL(rollupFileInfo.fileName, rootDirectoryUrl).href
|
|
148
|
+
}
|
|
152
149
|
jsModuleBundleUrlInfos[url] = jsModuleBundleUrlInfo
|
|
153
150
|
}
|
|
154
151
|
})
|
|
@@ -171,13 +168,18 @@ const rollupPluginJsenv = ({
|
|
|
171
168
|
},
|
|
172
169
|
chunkFileNames: (chunkInfo) => {
|
|
173
170
|
// preserves relative path parts:
|
|
174
|
-
// the goal is to
|
|
171
|
+
// the goal is to maintain the original relative path (relative to the root directory)
|
|
175
172
|
// so that later in the build process, when resolving these urls, we are able to
|
|
176
173
|
// re-resolve the specifier againt the original parent url and find the original url
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
174
|
+
if (chunkInfo.facadeModuleId) {
|
|
175
|
+
const fileUrl = fileUrlConverter.asFileUrl(chunkInfo.facadeModuleId)
|
|
176
|
+
const relativePath = urlToRelativeUrl(fileUrl, rootDirectoryUrl)
|
|
177
|
+
return relativePath
|
|
178
|
+
}
|
|
179
|
+
// chunk generated dynamically by rollup to share code.
|
|
180
|
+
// we prefix with "__rollup__/" to avoid potential conflict of filename
|
|
181
|
+
// between this one and a file with the same name existing in the root directory
|
|
182
|
+
return `__rollup__/${chunkInfo.name}.js`
|
|
181
183
|
},
|
|
182
184
|
// https://rollupjs.org/guide/en/#outputpaths
|
|
183
185
|
// paths: (id) => {
|
|
@@ -10,10 +10,7 @@ export const getBaseBabelPluginStructure = ({
|
|
|
10
10
|
isJsModule,
|
|
11
11
|
}) => {
|
|
12
12
|
const isBabelPluginNeeded = (babelPluginName) => {
|
|
13
|
-
return !isSupportedOnRuntime(
|
|
14
|
-
babelPluginName,
|
|
15
|
-
babelPluginCompatMap[babelPluginName],
|
|
16
|
-
)
|
|
13
|
+
return !isSupportedOnRuntime(babelPluginCompatMap[babelPluginName])
|
|
17
14
|
}
|
|
18
15
|
|
|
19
16
|
const babelPluginStructure = {}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { applyBabelPlugins } from "@jsenv/utils/js_ast/apply_babel_plugins.js"
|
|
2
2
|
|
|
3
|
+
import { RUNTIME_SUPPORT } from "@jsenv/core/src/omega/runtime_support/runtime_support.js"
|
|
3
4
|
import { getBaseBabelPluginStructure } from "./helpers/babel_plugin_structure.js"
|
|
4
5
|
import { babelPluginBabelHelpersAsJsenvImports } from "./helpers/babel_plugin_babel_helpers_as_jsenv_imports.js"
|
|
5
6
|
import { babelPluginNewStylesheetAsJsenvImport } from "./new_stylesheet/babel_plugin_new_stylesheet_as_jsenv_import.js"
|
|
@@ -12,16 +13,29 @@ export const jsenvPluginBabel = ({
|
|
|
12
13
|
} = {}) => {
|
|
13
14
|
const transformWithBabel = async (urlInfo, context) => {
|
|
14
15
|
const isJsModule = urlInfo.type === "js_module"
|
|
15
|
-
const isWorker =
|
|
16
|
-
|
|
17
|
-
const
|
|
16
|
+
const isWorker = urlInfo.subtype === "worker"
|
|
17
|
+
const isServiceWorker = urlInfo.subtype === "service_worker"
|
|
18
|
+
const isWorkerContext = isWorker || isServiceWorker
|
|
19
|
+
let { runtimeSupport } = context
|
|
20
|
+
if (isServiceWorker) {
|
|
21
|
+
// when code is executed by a service worker we can assume
|
|
22
|
+
// the execution context supports more than the default one
|
|
23
|
+
// for instance arrow function are supported
|
|
24
|
+
runtimeSupport = RUNTIME_SUPPORT.add(runtimeSupport, "service_worker")
|
|
25
|
+
}
|
|
26
|
+
if (isWorker) {
|
|
27
|
+
runtimeSupport = RUNTIME_SUPPORT.add(runtimeSupport, "worker")
|
|
28
|
+
}
|
|
29
|
+
const { referenceUtils } = context
|
|
30
|
+
const isSupportedOnRuntime = (feature) =>
|
|
31
|
+
RUNTIME_SUPPORT.isSupported(runtimeSupport, feature)
|
|
18
32
|
const babelPluginStructure = getBaseBabelPluginStructure({
|
|
19
33
|
url: urlInfo.url,
|
|
20
34
|
isSupportedOnRuntime,
|
|
21
35
|
topLevelAwait,
|
|
22
36
|
usesTopLevelAwait: urlInfo.data.usesTopLevelAwait,
|
|
23
37
|
isJsModule,
|
|
24
|
-
|
|
38
|
+
isWorkerContext,
|
|
25
39
|
})
|
|
26
40
|
if (getCustomBabelPlugins) {
|
|
27
41
|
Object.assign(babelPluginStructure, getCustomBabelPlugins(context))
|
|
@@ -52,10 +52,7 @@ export const jsenvPluginNewInlineContent = ({ allowEscapeForVersioning }) => {
|
|
|
52
52
|
columnEnd: inlineContentCall.columnEnd,
|
|
53
53
|
})
|
|
54
54
|
let { quote } = inlineContentCall
|
|
55
|
-
if (
|
|
56
|
-
quote === "`" &&
|
|
57
|
-
!isSupportedOnRuntime("transform-template-literals")
|
|
58
|
-
) {
|
|
55
|
+
if (quote === "`" && !isSupportedOnRuntime("template_literals")) {
|
|
59
56
|
// if quote is "`" and template literals are not supported
|
|
60
57
|
// we'll use a regular string (single or double quote)
|
|
61
58
|
// when rendering the string
|
package/src/omega/kitchen.js
CHANGED
|
@@ -10,8 +10,7 @@ import {
|
|
|
10
10
|
import { stringifyUrlSite } from "@jsenv/utils/urls/url_trace.js"
|
|
11
11
|
|
|
12
12
|
import { createUrlInfoTransformer } from "./url_graph/url_info_transformations.js"
|
|
13
|
-
import {
|
|
14
|
-
import { isFeatureSupportedOnRuntimes } from "./runtime_support/runtime_support.js"
|
|
13
|
+
import { RUNTIME_SUPPORT } from "./runtime_support/runtime_support.js"
|
|
15
14
|
import { fileUrlConverter } from "./file_url_converter.js"
|
|
16
15
|
import { parseUrlMentions } from "./url_mentions/parse_url_mentions.js"
|
|
17
16
|
import {
|
|
@@ -185,14 +184,6 @@ export const createKitchen = ({
|
|
|
185
184
|
},
|
|
186
185
|
})
|
|
187
186
|
|
|
188
|
-
const isSupported = ({
|
|
189
|
-
runtimeSupport,
|
|
190
|
-
featureName,
|
|
191
|
-
featureCompat = featuresCompatMap[featureName],
|
|
192
|
-
}) => {
|
|
193
|
-
return isFeatureSupportedOnRuntimes(runtimeSupport, featureCompat)
|
|
194
|
-
}
|
|
195
|
-
|
|
196
187
|
const load = async ({ reference, urlInfo, context }) => {
|
|
197
188
|
try {
|
|
198
189
|
const loadReturnValue = urlInfo.isInline
|
|
@@ -274,8 +265,8 @@ export const createKitchen = ({
|
|
|
274
265
|
reference,
|
|
275
266
|
outDirectoryUrl,
|
|
276
267
|
runtimeSupport,
|
|
277
|
-
isSupportedOnRuntime: (
|
|
278
|
-
return isSupported(
|
|
268
|
+
isSupportedOnRuntime: (feature) => {
|
|
269
|
+
return RUNTIME_SUPPORT.isSupported(runtimeSupport, feature)
|
|
279
270
|
},
|
|
280
271
|
cook: (params) => {
|
|
281
272
|
return cookDuringCook({
|
|
@@ -585,7 +576,6 @@ export const createKitchen = ({
|
|
|
585
576
|
urlInfoTransformer,
|
|
586
577
|
rootDirectoryUrl,
|
|
587
578
|
jsenvDirectoryUrl,
|
|
588
|
-
isSupported,
|
|
589
579
|
createReference,
|
|
590
580
|
resolveReference,
|
|
591
581
|
cook,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const
|
|
1
|
+
export const featureCompats = {
|
|
2
2
|
script_type_module: {
|
|
3
3
|
edge: "16",
|
|
4
4
|
firefox: "60",
|
|
@@ -52,6 +52,7 @@ export const featuresCompatMap = {
|
|
|
52
52
|
chrome: "93",
|
|
53
53
|
edge: "93",
|
|
54
54
|
},
|
|
55
|
+
import_type_text: {},
|
|
55
56
|
// https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet#browser_compatibility
|
|
56
57
|
new_stylesheet: {
|
|
57
58
|
chrome: "73",
|
|
@@ -59,6 +60,33 @@ export const featuresCompatMap = {
|
|
|
59
60
|
opera: "53",
|
|
60
61
|
android: "73",
|
|
61
62
|
},
|
|
63
|
+
// https://caniuse.com/?search=worker
|
|
64
|
+
worker: {
|
|
65
|
+
ie: "10",
|
|
66
|
+
edge: "12",
|
|
67
|
+
firefox: "3.5",
|
|
68
|
+
chrome: "4",
|
|
69
|
+
opera: "11.5",
|
|
70
|
+
safari: "4",
|
|
71
|
+
ios: "5",
|
|
72
|
+
android: "4.4",
|
|
73
|
+
},
|
|
74
|
+
service_worker: {
|
|
75
|
+
edge: "17",
|
|
76
|
+
firefox: "44",
|
|
77
|
+
chrome: "40",
|
|
78
|
+
safari: "11.1",
|
|
79
|
+
opera: "27",
|
|
80
|
+
ios: "11.3",
|
|
81
|
+
android: "12.12",
|
|
82
|
+
},
|
|
83
|
+
service_worker_type_module: {
|
|
84
|
+
chrome: "80",
|
|
85
|
+
edge: "80",
|
|
86
|
+
opera: "67",
|
|
87
|
+
android: "80",
|
|
88
|
+
},
|
|
89
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/Worker/Worker#browser_compatibility
|
|
62
90
|
worker_type_module: {
|
|
63
91
|
chrome: "80",
|
|
64
92
|
edge: "80",
|
|
@@ -88,4 +116,15 @@ export const featuresCompatMap = {
|
|
|
88
116
|
samsung: "8",
|
|
89
117
|
electron: "3",
|
|
90
118
|
},
|
|
119
|
+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#browser_compatibility
|
|
120
|
+
template_literals: {
|
|
121
|
+
chrome: "41",
|
|
122
|
+
edge: "12",
|
|
123
|
+
firefox: "34",
|
|
124
|
+
opera: "28",
|
|
125
|
+
safari: "9",
|
|
126
|
+
ios: "9",
|
|
127
|
+
android: "4",
|
|
128
|
+
node: "4",
|
|
129
|
+
},
|
|
91
130
|
}
|
|
@@ -1,20 +1,52 @@
|
|
|
1
1
|
import { findHighestVersion } from "@jsenv/utils/semantic_versioning/highest_version.js"
|
|
2
|
+
import { featureCompats } from "./features_compatibility.js"
|
|
2
3
|
|
|
3
|
-
export const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
) => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
4
|
+
export const RUNTIME_SUPPORT = {
|
|
5
|
+
featureCompats,
|
|
6
|
+
|
|
7
|
+
add: (originalRuntimeSupport, feature) => {
|
|
8
|
+
const featureCompat = getFeatureCompat(feature)
|
|
9
|
+
const runtimeSupport = {
|
|
10
|
+
...originalRuntimeSupport,
|
|
11
|
+
}
|
|
12
|
+
Object.keys(featureCompat).forEach((runtimeName) => {
|
|
13
|
+
const firstVersion = originalRuntimeSupport[runtimeName]
|
|
14
|
+
const secondVersion = featureCompat[runtimeName]
|
|
15
|
+
runtimeSupport[runtimeName] = firstVersion
|
|
16
|
+
? findHighestVersion(firstVersion, secondVersion)
|
|
17
|
+
: secondVersion
|
|
18
|
+
})
|
|
19
|
+
return runtimeSupport
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
isSupported: (runtimeSupport, feature) => {
|
|
23
|
+
const featureCompat = getFeatureCompat(feature)
|
|
24
|
+
const runtimeNames = Object.keys(runtimeSupport)
|
|
25
|
+
return runtimeNames.every((runtimeName) => {
|
|
26
|
+
const runtimeVersion = runtimeSupport[runtimeName]
|
|
27
|
+
const runtimeVersionCompatible = featureCompat[runtimeName] || "Infinity"
|
|
28
|
+
const highestVersion = findHighestVersion(
|
|
29
|
+
runtimeVersion,
|
|
30
|
+
runtimeVersionCompatible,
|
|
31
|
+
)
|
|
32
|
+
if (highestVersion !== runtimeVersion) {
|
|
33
|
+
return false
|
|
34
|
+
}
|
|
35
|
+
return true
|
|
36
|
+
})
|
|
37
|
+
},
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const getFeatureCompat = (feature) => {
|
|
41
|
+
if (typeof feature === "string") {
|
|
42
|
+
const compat = featureCompats[feature]
|
|
43
|
+
if (!compat) {
|
|
44
|
+
throw new Error(`"${feature}" feature is unknown`)
|
|
17
45
|
}
|
|
18
|
-
return
|
|
19
|
-
}
|
|
46
|
+
return compat
|
|
47
|
+
}
|
|
48
|
+
if (typeof feature !== "object") {
|
|
49
|
+
throw new TypeError(`feature must be a string or an object, got ${feature}`)
|
|
50
|
+
}
|
|
51
|
+
return feature
|
|
20
52
|
}
|