@jsenv/core 30.3.9 → 30.4.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/README.md +1 -3
- package/dist/js/s.js +0 -1
- package/dist/js/s.js.map +3 -3
- package/dist/js/server_events_client.js +0 -1
- package/dist/main.js +111 -46
- package/package.json +8 -8
- package/src/build/build.js +15 -10
- package/src/build/readme.md +3 -0
- package/src/dev/file_service.js +10 -1
- package/src/dev/readme.md +13 -0
- package/src/dev/start_dev_server.js +2 -0
- package/src/execute/execute.js +14 -2
- package/src/execute/run.js +12 -0
- package/src/execute/runtimes/browsers/chromium.js +3 -1
- package/src/execute/runtimes/browsers/firefox.js +3 -1
- package/src/execute/runtimes/browsers/from_playwright.js +8 -5
- package/src/execute/runtimes/browsers/webkit.js +3 -1
- package/src/execute/runtimes/readme.md +13 -0
- package/src/kitchen/kitchen.js +8 -3
- package/src/kitchen/readme.md +8 -0
- package/src/kitchen/url_graph.js +23 -5
- package/src/plugins/cache_control/jsenv_plugin_cache_control.js +6 -2
- package/src/plugins/plugins.js +6 -1
- package/src/plugins/readme.md +18 -0
- package/src/plugins/server_events/client/server_events_client.js +0 -2
- package/src/plugins/transpilation/as_js_classic/client/s.js +0 -1
- package/src/plugins/transpilation/babel/jsenv_plugin_babel.js +3 -23
- package/src/test/execute_plan.js +1 -0
- package/src/test/readme.md +3 -0
package/dist/main.js
CHANGED
|
@@ -7093,10 +7093,30 @@ const createUrlGraph = () => {
|
|
|
7093
7093
|
if (!parentUrlInfo) {
|
|
7094
7094
|
return null;
|
|
7095
7095
|
}
|
|
7096
|
-
const
|
|
7097
|
-
|
|
7098
|
-
|
|
7099
|
-
|
|
7096
|
+
const seen = [];
|
|
7097
|
+
const search = urlInfo => {
|
|
7098
|
+
const firstReferenceFound = urlInfo.references.find(reference => {
|
|
7099
|
+
return urlSpecifierEncoding.decode(reference) === specifier;
|
|
7100
|
+
});
|
|
7101
|
+
if (firstReferenceFound) {
|
|
7102
|
+
return firstReferenceFound;
|
|
7103
|
+
}
|
|
7104
|
+
for (const dependencyUrl of parentUrlInfo.dependencies) {
|
|
7105
|
+
if (seen.includes(dependencyUrl)) {
|
|
7106
|
+
continue;
|
|
7107
|
+
}
|
|
7108
|
+
seen.push(dependencyUrl);
|
|
7109
|
+
const dependencyUrlInfo = getUrlInfo(dependencyUrl);
|
|
7110
|
+
if (dependencyUrlInfo.isInline) {
|
|
7111
|
+
const firstRef = search(dependencyUrlInfo);
|
|
7112
|
+
if (firstRef) {
|
|
7113
|
+
return firstRef;
|
|
7114
|
+
}
|
|
7115
|
+
}
|
|
7116
|
+
}
|
|
7117
|
+
return null;
|
|
7118
|
+
};
|
|
7119
|
+
return search(parentUrlInfo);
|
|
7100
7120
|
};
|
|
7101
7121
|
const findDependent = (urlInfo, visitor) => {
|
|
7102
7122
|
const seen = [urlInfo.url];
|
|
@@ -8852,7 +8872,7 @@ ${ANSI.color(normalizedReturnValue, ANSI.YELLOW)}
|
|
|
8852
8872
|
type,
|
|
8853
8873
|
subtype,
|
|
8854
8874
|
originalUrl,
|
|
8855
|
-
originalContent,
|
|
8875
|
+
originalContent = content,
|
|
8856
8876
|
sourcemap,
|
|
8857
8877
|
filename,
|
|
8858
8878
|
status = 200,
|
|
@@ -8875,7 +8895,15 @@ ${ANSI.color(normalizedReturnValue, ANSI.YELLOW)}
|
|
|
8875
8895
|
urlInfo.subtype = subtype || reference.expectedSubtype || "";
|
|
8876
8896
|
// during build urls info are reused and load returns originalUrl/originalContent
|
|
8877
8897
|
urlInfo.originalUrl = originalUrl || urlInfo.originalUrl;
|
|
8878
|
-
|
|
8898
|
+
if (originalContent !== urlInfo.originalContent) {
|
|
8899
|
+
urlInfo.originalContentEtag = undefined; // set by "initTransformations"
|
|
8900
|
+
}
|
|
8901
|
+
|
|
8902
|
+
if (content !== urlInfo.content) {
|
|
8903
|
+
urlInfo.contentEtag = undefined; // set by "applyFinalTransformations"
|
|
8904
|
+
}
|
|
8905
|
+
|
|
8906
|
+
urlInfo.originalContent = originalContent;
|
|
8879
8907
|
urlInfo.content = content;
|
|
8880
8908
|
urlInfo.sourcemap = sourcemap;
|
|
8881
8909
|
if (data) {
|
|
@@ -19180,17 +19208,6 @@ const jsenvPluginBabel = ({
|
|
|
19180
19208
|
return {
|
|
19181
19209
|
name: "jsenv:babel",
|
|
19182
19210
|
appliesDuring: "*",
|
|
19183
|
-
transformUrlContent: urlInfo => {
|
|
19184
|
-
if (urlInfo.url === regeneratorRuntimeClientFileUrl) {
|
|
19185
|
-
urlInfo.data.isBabelClientFile = true;
|
|
19186
|
-
}
|
|
19187
|
-
if (urlInfo.url === globalThisClientFileUrl) {
|
|
19188
|
-
urlInfo.data.isBabelClientFile = true;
|
|
19189
|
-
}
|
|
19190
|
-
if (urlInfo.url === newStylesheetClientFileUrl) {
|
|
19191
|
-
urlInfo.data.isBabelClientFile = true;
|
|
19192
|
-
}
|
|
19193
|
-
},
|
|
19194
19211
|
finalizeUrlContent: {
|
|
19195
19212
|
js_classic: transformWithBabel,
|
|
19196
19213
|
js_module: transformWithBabel
|
|
@@ -20017,17 +20034,20 @@ const jsenvPluginAutoreload = ({
|
|
|
20017
20034
|
})];
|
|
20018
20035
|
};
|
|
20019
20036
|
|
|
20020
|
-
const jsenvPluginCacheControl = (
|
|
20037
|
+
const jsenvPluginCacheControl = ({
|
|
20038
|
+
versionedUrls = true,
|
|
20039
|
+
maxAge = SECONDS_IN_30_DAYS$1
|
|
20040
|
+
}) => {
|
|
20021
20041
|
return {
|
|
20022
20042
|
name: "jsenv:cache_control",
|
|
20023
20043
|
appliesDuring: "dev",
|
|
20024
20044
|
augmentResponse: ({
|
|
20025
20045
|
reference
|
|
20026
20046
|
}) => {
|
|
20027
|
-
if (reference.searchParams.has("v") && !reference.searchParams.has("hmr")) {
|
|
20047
|
+
if (versionedUrls && reference.searchParams.has("v") && !reference.searchParams.has("hmr")) {
|
|
20028
20048
|
return {
|
|
20029
20049
|
headers: {
|
|
20030
|
-
"cache-control": `private,max-age=${
|
|
20050
|
+
"cache-control": `private,max-age=${maxAge},immutable`
|
|
20031
20051
|
}
|
|
20032
20052
|
};
|
|
20033
20053
|
}
|
|
@@ -20169,11 +20189,15 @@ const getCorePlugins = ({
|
|
|
20169
20189
|
clientFileChangeCallbackList,
|
|
20170
20190
|
clientFilesPruneCallbackList,
|
|
20171
20191
|
explorer,
|
|
20192
|
+
cacheControl,
|
|
20172
20193
|
ribbon = true
|
|
20173
20194
|
} = {}) => {
|
|
20174
20195
|
if (explorer === true) {
|
|
20175
20196
|
explorer = {};
|
|
20176
20197
|
}
|
|
20198
|
+
if (cacheControl === true) {
|
|
20199
|
+
cacheControl = {};
|
|
20200
|
+
}
|
|
20177
20201
|
if (supervisor === true) {
|
|
20178
20202
|
supervisor = {};
|
|
20179
20203
|
}
|
|
@@ -20214,7 +20238,7 @@ const getCorePlugins = ({
|
|
|
20214
20238
|
...clientAutoreload,
|
|
20215
20239
|
clientFileChangeCallbackList,
|
|
20216
20240
|
clientFilesPruneCallbackList
|
|
20217
|
-
})] : []), jsenvPluginCacheControl(), ...(explorer ? [jsenvPluginExplorer({
|
|
20241
|
+
})] : []), ...(cacheControl ? [jsenvPluginCacheControl(cacheControl)] : []), ...(explorer ? [jsenvPluginExplorer({
|
|
20218
20242
|
...explorer,
|
|
20219
20243
|
clientMainFileUrl
|
|
20220
20244
|
})] : []), ...(ribbon ? [jsenvPluginRibbon({
|
|
@@ -21392,7 +21416,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
21392
21416
|
}
|
|
21393
21417
|
if (preferWithoutVersioning(reference)) {
|
|
21394
21418
|
// when versioning is dynamic no need to take into account
|
|
21395
|
-
//
|
|
21419
|
+
// happens for:
|
|
21396
21420
|
// - specifier mapped by window.__v__()
|
|
21397
21421
|
// - specifier mapped by importmap
|
|
21398
21422
|
return null;
|
|
@@ -21752,7 +21776,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
21752
21776
|
return finalUrlInfo.subtype === "service_worker" && finalUrlInfo.isEntryPoint;
|
|
21753
21777
|
});
|
|
21754
21778
|
if (serviceWorkerEntryUrlInfos.length > 0) {
|
|
21755
|
-
const
|
|
21779
|
+
const serviceWorkerResources = {};
|
|
21756
21780
|
GRAPH.forEach(finalGraph, urlInfo => {
|
|
21757
21781
|
if (urlInfo.isInline || !urlInfo.shouldHandle) {
|
|
21758
21782
|
return;
|
|
@@ -21765,26 +21789,27 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
21765
21789
|
// so that service worker source still changes and navigator
|
|
21766
21790
|
// detect there is a change
|
|
21767
21791
|
const specifier = findKey(buildUrls, urlInfo.url);
|
|
21768
|
-
|
|
21769
|
-
versioned: false,
|
|
21792
|
+
serviceWorkerResources[specifier] = {
|
|
21770
21793
|
version: versionMap.get(urlInfo.url)
|
|
21771
21794
|
};
|
|
21772
21795
|
return;
|
|
21773
21796
|
}
|
|
21797
|
+
const specifier = findKey(buildUrls, urlInfo.url);
|
|
21774
21798
|
const versionedUrl = versionedUrlMap.get(urlInfo.url);
|
|
21775
21799
|
const versionedSpecifier = findKey(buildUrls, versionedUrl);
|
|
21776
|
-
|
|
21777
|
-
|
|
21800
|
+
serviceWorkerResources[specifier] = {
|
|
21801
|
+
version: versionMap.get(urlInfo.url),
|
|
21802
|
+
versionedUrl: versionedSpecifier
|
|
21778
21803
|
};
|
|
21779
21804
|
});
|
|
21780
21805
|
serviceWorkerEntryUrlInfos.forEach(serviceWorkerEntryUrlInfo => {
|
|
21781
21806
|
const magicSource = createMagicSource(serviceWorkerEntryUrlInfo.content);
|
|
21782
|
-
const
|
|
21783
|
-
...
|
|
21807
|
+
const serviceWorkerResourcesWithoutSwScriptItSelf = {
|
|
21808
|
+
...serviceWorkerResources
|
|
21784
21809
|
};
|
|
21785
21810
|
const serviceWorkerSpecifier = findKey(buildUrls, serviceWorkerEntryUrlInfo.url);
|
|
21786
|
-
delete
|
|
21787
|
-
magicSource.prepend(`\nself.
|
|
21811
|
+
delete serviceWorkerResourcesWithoutSwScriptItSelf[serviceWorkerSpecifier];
|
|
21812
|
+
magicSource.prepend(`\nself.resourcesFromJsenvBuild = ${JSON.stringify(serviceWorkerResourcesWithoutSwScriptItSelf, null, " ")};\n`);
|
|
21788
21813
|
const {
|
|
21789
21814
|
content,
|
|
21790
21815
|
sourcemap
|
|
@@ -22157,6 +22182,7 @@ const createFileService = ({
|
|
|
22157
22182
|
clientMainFileUrl,
|
|
22158
22183
|
cooldownBetweenFileEvents,
|
|
22159
22184
|
explorer,
|
|
22185
|
+
cacheControl,
|
|
22160
22186
|
ribbon,
|
|
22161
22187
|
sourcemaps,
|
|
22162
22188
|
sourcemapsSourcesProtocol,
|
|
@@ -22264,6 +22290,7 @@ const createFileService = ({
|
|
|
22264
22290
|
clientFileChangeCallbackList,
|
|
22265
22291
|
clientFilesPruneCallbackList,
|
|
22266
22292
|
explorer,
|
|
22293
|
+
cacheControl,
|
|
22267
22294
|
ribbon
|
|
22268
22295
|
})],
|
|
22269
22296
|
minification: false,
|
|
@@ -22293,18 +22320,25 @@ const createFileService = ({
|
|
|
22293
22320
|
// when file is modified
|
|
22294
22321
|
return false;
|
|
22295
22322
|
}
|
|
22296
|
-
if (!watch) {
|
|
22323
|
+
if (!watch && urlInfo.contentEtag) {
|
|
22324
|
+
// file is not watched, check the filesystem
|
|
22297
22325
|
let fileContentAsBuffer;
|
|
22298
22326
|
try {
|
|
22299
22327
|
fileContentAsBuffer = readFileSync$1(new URL(urlInfo.url));
|
|
22300
22328
|
} catch (e) {
|
|
22301
22329
|
if (e.code === "ENOENT") {
|
|
22330
|
+
// we should consider calling urlGraph.deleteUrlInfo(urlInfo)
|
|
22331
|
+
urlInfo.originalContentEtag = undefined;
|
|
22332
|
+
urlInfo.contentEtag = undefined;
|
|
22302
22333
|
return false;
|
|
22303
22334
|
}
|
|
22304
22335
|
return false;
|
|
22305
22336
|
}
|
|
22306
22337
|
const fileContentEtag = bufferToEtag$1(fileContentAsBuffer);
|
|
22307
22338
|
if (fileContentEtag !== urlInfo.originalContentEtag) {
|
|
22339
|
+
// we should consider calling urlGraph.considerModified(urlInfo)
|
|
22340
|
+
urlInfo.originalContentEtag = undefined;
|
|
22341
|
+
urlInfo.contentEtag = undefined;
|
|
22308
22342
|
return false;
|
|
22309
22343
|
}
|
|
22310
22344
|
}
|
|
@@ -22622,6 +22656,7 @@ const startDevServer = async ({
|
|
|
22622
22656
|
transpilation,
|
|
22623
22657
|
explorer = true,
|
|
22624
22658
|
// see jsenv_plugin_explorer.js
|
|
22659
|
+
cacheControl = true,
|
|
22625
22660
|
ribbon = true,
|
|
22626
22661
|
// toolbar = false,
|
|
22627
22662
|
|
|
@@ -22760,6 +22795,7 @@ const startDevServer = async ({
|
|
|
22760
22795
|
clientMainFileUrl,
|
|
22761
22796
|
cooldownBetweenFileEvents,
|
|
22762
22797
|
explorer,
|
|
22798
|
+
cacheControl,
|
|
22763
22799
|
ribbon,
|
|
22764
22800
|
sourcemaps,
|
|
22765
22801
|
sourcemapsSourcesProtocol,
|
|
@@ -23394,6 +23430,17 @@ const getCoverageFromReport = async ({
|
|
|
23394
23430
|
};
|
|
23395
23431
|
const isV8Coverage = coverage => Boolean(coverage.result);
|
|
23396
23432
|
|
|
23433
|
+
/*
|
|
23434
|
+
* Export a function capable to run a file on a runtime.
|
|
23435
|
+
*
|
|
23436
|
+
* - Used internally by "executeTestPlan" part of the documented API
|
|
23437
|
+
* - Used internally by "execute" an advanced API not documented
|
|
23438
|
+
* - logs generated during file execution can be collected
|
|
23439
|
+
* - logs generated during file execution can be mirrored (re-logged to the console)
|
|
23440
|
+
* - File is given allocatedMs to complete
|
|
23441
|
+
* - Errors are collected
|
|
23442
|
+
* - File execution result is returned, it contains status/errors/namespace/consoleCalls
|
|
23443
|
+
*/
|
|
23397
23444
|
const run = async ({
|
|
23398
23445
|
signal = new AbortController().signal,
|
|
23399
23446
|
logger,
|
|
@@ -24244,6 +24291,7 @@ const executePlan = async (plan, {
|
|
|
24244
24291
|
}
|
|
24245
24292
|
const afterExecutionInfo = {
|
|
24246
24293
|
...beforeExecutionInfo,
|
|
24294
|
+
runtimeVersion: runtime.version,
|
|
24247
24295
|
endMs: Date.now(),
|
|
24248
24296
|
executionResult
|
|
24249
24297
|
};
|
|
@@ -24636,8 +24684,8 @@ const createRuntimeFromPlaywright = ({
|
|
|
24636
24684
|
stopSignal,
|
|
24637
24685
|
keepRunning,
|
|
24638
24686
|
onConsole,
|
|
24639
|
-
executablePath,
|
|
24640
24687
|
headful = keepRunning,
|
|
24688
|
+
playwrightLaunchOptions = {},
|
|
24641
24689
|
ignoreHTTPSErrors = true
|
|
24642
24690
|
}) => {
|
|
24643
24691
|
const cleanupCallbackList = createCallbackListNotifiedOnce();
|
|
@@ -24653,11 +24701,14 @@ const createRuntimeFromPlaywright = ({
|
|
|
24653
24701
|
signal,
|
|
24654
24702
|
browserName,
|
|
24655
24703
|
stopOnExit: true,
|
|
24656
|
-
|
|
24657
|
-
|
|
24658
|
-
|
|
24704
|
+
playwrightLaunchOptions: {
|
|
24705
|
+
...playwrightLaunchOptions,
|
|
24706
|
+
headless: !headful
|
|
24659
24707
|
}
|
|
24660
24708
|
});
|
|
24709
|
+
if (browser._initializer.version) {
|
|
24710
|
+
runtime.version = browser._initializer.version;
|
|
24711
|
+
}
|
|
24661
24712
|
const browserContext = await browser.newContext({
|
|
24662
24713
|
ignoreHTTPSErrors
|
|
24663
24714
|
});
|
|
@@ -24974,7 +25025,7 @@ const launchBrowserUsingPlaywright = async ({
|
|
|
24974
25025
|
signal,
|
|
24975
25026
|
browserName,
|
|
24976
25027
|
stopOnExit,
|
|
24977
|
-
|
|
25028
|
+
playwrightLaunchOptions
|
|
24978
25029
|
}) => {
|
|
24979
25030
|
const launchBrowserOperation = Abort.startOperation();
|
|
24980
25031
|
launchBrowserOperation.addAbortSignal(signal);
|
|
@@ -24995,7 +25046,7 @@ const launchBrowserUsingPlaywright = async ({
|
|
|
24995
25046
|
const browserClass = playwright[browserName];
|
|
24996
25047
|
try {
|
|
24997
25048
|
const browser = await browserClass.launch({
|
|
24998
|
-
...
|
|
25049
|
+
...playwrightLaunchOptions,
|
|
24999
25050
|
// let's handle them to close properly browser + remove listener
|
|
25000
25051
|
// instead of relying on playwright to do so
|
|
25001
25052
|
handleSIGINT: false,
|
|
@@ -25086,23 +25137,26 @@ const registerEvent = ({
|
|
|
25086
25137
|
|
|
25087
25138
|
const chromium = createRuntimeFromPlaywright({
|
|
25088
25139
|
browserName: "chromium",
|
|
25089
|
-
browserVersion
|
|
25090
|
-
//
|
|
25140
|
+
// browserVersion will be set by "browser._initializer.version"
|
|
25141
|
+
// see also https://github.com/microsoft/playwright/releases
|
|
25142
|
+
browserVersion: "unset",
|
|
25091
25143
|
coveragePlaywrightAPIAvailable: true
|
|
25092
25144
|
});
|
|
25093
25145
|
const chromiumIsolatedTab = chromium.isolatedTab;
|
|
25094
25146
|
|
|
25095
25147
|
const firefox = createRuntimeFromPlaywright({
|
|
25096
25148
|
browserName: "firefox",
|
|
25097
|
-
browserVersion
|
|
25149
|
+
// browserVersion will be set by "browser._initializer.version"
|
|
25150
|
+
// see also https://github.com/microsoft/playwright/releases
|
|
25151
|
+
browserVersion: "unset"
|
|
25098
25152
|
});
|
|
25099
|
-
|
|
25100
25153
|
const firefoxIsolatedTab = firefox.isolatedTab;
|
|
25101
25154
|
|
|
25102
25155
|
const webkit = createRuntimeFromPlaywright({
|
|
25103
25156
|
browserName: "webkit",
|
|
25104
|
-
browserVersion
|
|
25105
|
-
//
|
|
25157
|
+
// browserVersion will be set by "browser._initializer.version"
|
|
25158
|
+
// see also https://github.com/microsoft/playwright/releases
|
|
25159
|
+
browserVersion: "unset",
|
|
25106
25160
|
ignoreErrorHook: error => {
|
|
25107
25161
|
// we catch error during execution but safari throw unhandled rejection
|
|
25108
25162
|
// in a non-deterministic way.
|
|
@@ -26176,6 +26230,17 @@ const createBuildFilesService = ({
|
|
|
26176
26230
|
};
|
|
26177
26231
|
const SECONDS_IN_30_DAYS = 60 * 60 * 24 * 30;
|
|
26178
26232
|
|
|
26233
|
+
/*
|
|
26234
|
+
* Export a function capable to execute a file on a runtime (browser or node) and return how it goes.
|
|
26235
|
+
*
|
|
26236
|
+
* - can be useful to execute a file in a browser/node.js programmatically
|
|
26237
|
+
* - not documented
|
|
26238
|
+
* - the most importants parts:
|
|
26239
|
+
* - fileRelativeUrl: the file to execute inside rootDirectoryUrl
|
|
26240
|
+
* - runtime: an object with a "run" method.
|
|
26241
|
+
* The run method will start a browser/node process and execute file in it
|
|
26242
|
+
* - Most of the logic lives in "./run.js" used by executeTestPlan to run tests
|
|
26243
|
+
*/
|
|
26179
26244
|
const execute = async ({
|
|
26180
26245
|
signal = new AbortController().signal,
|
|
26181
26246
|
handleSIGINT = true,
|
|
@@ -26216,11 +26281,11 @@ const execute = async ({
|
|
|
26216
26281
|
};
|
|
26217
26282
|
if (runtime.type === "browser") {
|
|
26218
26283
|
if (!devServerOrigin) {
|
|
26219
|
-
throw new TypeError(`devServerOrigin is required
|
|
26284
|
+
throw new TypeError(`devServerOrigin is required to execute file on a browser`);
|
|
26220
26285
|
}
|
|
26221
26286
|
const devServerStarted = await pingServer(devServerOrigin);
|
|
26222
26287
|
if (!devServerStarted) {
|
|
26223
|
-
throw new Error(`
|
|
26288
|
+
throw new Error(`no server listening at ${devServerOrigin}. It is required to execute file`);
|
|
26224
26289
|
}
|
|
26225
26290
|
}
|
|
26226
26291
|
let result = await run({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/core",
|
|
3
|
-
"version": "30.
|
|
3
|
+
"version": "30.4.1",
|
|
4
4
|
"description": "Tool to develop, test and build js projects",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
"dev": "node --conditions=development ./scripts/dev/dev.mjs",
|
|
45
45
|
"test": "node --conditions=development ./scripts/test/test.mjs",
|
|
46
46
|
"test:resource_hints": "npm run test -- --only-resource-hints",
|
|
47
|
-
"test:workspace": "npm run test --workspaces --if-present -- --workspace",
|
|
48
47
|
"build": "node --conditions=development ./scripts/build/build.mjs",
|
|
48
|
+
"workspace:test": "npm run test --workspaces --if-present -- --workspace",
|
|
49
49
|
"workspace:versions": "node ./scripts/publish/workspace_versions.mjs",
|
|
50
50
|
"workspace:publish": "node ./scripts/publish/workspace_publish.mjs",
|
|
51
51
|
"performances": "node --expose-gc ./scripts/performance/generate_performance_report.mjs --log --once",
|
|
@@ -68,8 +68,8 @@
|
|
|
68
68
|
"@financial-times/polyfill-useragent-normaliser": "1.10.2",
|
|
69
69
|
"@jsenv/abort": "4.2.4",
|
|
70
70
|
"@jsenv/ast": "3.0.2",
|
|
71
|
-
"@jsenv/babel-plugins": "1.1.
|
|
72
|
-
"@jsenv/plugin-bundling": "1.1
|
|
71
|
+
"@jsenv/babel-plugins": "1.1.4",
|
|
72
|
+
"@jsenv/plugin-bundling": "1.2.1",
|
|
73
73
|
"@jsenv/filesystem": "4.1.9",
|
|
74
74
|
"@jsenv/importmap": "1.2.1",
|
|
75
75
|
"@jsenv/integrity": "0.0.1",
|
|
@@ -107,11 +107,11 @@
|
|
|
107
107
|
"@jsenv/plugin-globals": "./packages/jsenv-plugin-globals/",
|
|
108
108
|
"@jsenv/plugin-placeholders": "./packages/jsenv-plugin-placeholders/",
|
|
109
109
|
"@jsenv/performance-impact": "4.1.0",
|
|
110
|
-
"eslint": "8.
|
|
110
|
+
"eslint": "8.35.0",
|
|
111
111
|
"eslint-plugin-html": "7.1.0",
|
|
112
112
|
"eslint-plugin-import": "2.27.5",
|
|
113
|
-
"eslint-plugin-react": "7.32.
|
|
114
|
-
"playwright": "1.
|
|
115
|
-
"prettier": "2.8.
|
|
113
|
+
"eslint-plugin-react": "7.32.2",
|
|
114
|
+
"playwright": "1.31.2",
|
|
115
|
+
"prettier": "2.8.4"
|
|
116
116
|
}
|
|
117
117
|
}
|
package/src/build/build.js
CHANGED
|
@@ -1042,7 +1042,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
1042
1042
|
}
|
|
1043
1043
|
if (preferWithoutVersioning(reference)) {
|
|
1044
1044
|
// when versioning is dynamic no need to take into account
|
|
1045
|
-
//
|
|
1045
|
+
// happens for:
|
|
1046
1046
|
// - specifier mapped by window.__v__()
|
|
1047
1047
|
// - specifier mapped by importmap
|
|
1048
1048
|
return null
|
|
@@ -1477,7 +1477,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
1477
1477
|
},
|
|
1478
1478
|
)
|
|
1479
1479
|
if (serviceWorkerEntryUrlInfos.length > 0) {
|
|
1480
|
-
const
|
|
1480
|
+
const serviceWorkerResources = {}
|
|
1481
1481
|
GRAPH.forEach(finalGraph, (urlInfo) => {
|
|
1482
1482
|
if (urlInfo.isInline || !urlInfo.shouldHandle) {
|
|
1483
1483
|
return
|
|
@@ -1490,31 +1490,36 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
|
|
|
1490
1490
|
// so that service worker source still changes and navigator
|
|
1491
1491
|
// detect there is a change
|
|
1492
1492
|
const specifier = findKey(buildUrls, urlInfo.url)
|
|
1493
|
-
|
|
1494
|
-
versioned: false,
|
|
1493
|
+
serviceWorkerResources[specifier] = {
|
|
1495
1494
|
version: versionMap.get(urlInfo.url),
|
|
1496
1495
|
}
|
|
1497
1496
|
return
|
|
1498
1497
|
}
|
|
1498
|
+
const specifier = findKey(buildUrls, urlInfo.url)
|
|
1499
1499
|
const versionedUrl = versionedUrlMap.get(urlInfo.url)
|
|
1500
1500
|
const versionedSpecifier = findKey(buildUrls, versionedUrl)
|
|
1501
|
-
|
|
1501
|
+
serviceWorkerResources[specifier] = {
|
|
1502
|
+
version: versionMap.get(urlInfo.url),
|
|
1503
|
+
versionedUrl: versionedSpecifier,
|
|
1504
|
+
}
|
|
1502
1505
|
})
|
|
1503
1506
|
serviceWorkerEntryUrlInfos.forEach((serviceWorkerEntryUrlInfo) => {
|
|
1504
1507
|
const magicSource = createMagicSource(
|
|
1505
1508
|
serviceWorkerEntryUrlInfo.content,
|
|
1506
1509
|
)
|
|
1507
|
-
const
|
|
1508
|
-
...
|
|
1510
|
+
const serviceWorkerResourcesWithoutSwScriptItSelf = {
|
|
1511
|
+
...serviceWorkerResources,
|
|
1509
1512
|
}
|
|
1510
1513
|
const serviceWorkerSpecifier = findKey(
|
|
1511
1514
|
buildUrls,
|
|
1512
1515
|
serviceWorkerEntryUrlInfo.url,
|
|
1513
1516
|
)
|
|
1514
|
-
delete
|
|
1517
|
+
delete serviceWorkerResourcesWithoutSwScriptItSelf[
|
|
1518
|
+
serviceWorkerSpecifier
|
|
1519
|
+
]
|
|
1515
1520
|
magicSource.prepend(
|
|
1516
|
-
`\nself.
|
|
1517
|
-
|
|
1521
|
+
`\nself.resourcesFromJsenvBuild = ${JSON.stringify(
|
|
1522
|
+
serviceWorkerResourcesWithoutSwScriptItSelf,
|
|
1518
1523
|
null,
|
|
1519
1524
|
" ",
|
|
1520
1525
|
)};\n`,
|
package/src/dev/file_service.js
CHANGED
|
@@ -35,6 +35,7 @@ export const createFileService = ({
|
|
|
35
35
|
clientMainFileUrl,
|
|
36
36
|
cooldownBetweenFileEvents,
|
|
37
37
|
explorer,
|
|
38
|
+
cacheControl,
|
|
38
39
|
ribbon,
|
|
39
40
|
sourcemaps,
|
|
40
41
|
sourcemapsSourcesProtocol,
|
|
@@ -145,6 +146,7 @@ export const createFileService = ({
|
|
|
145
146
|
clientFileChangeCallbackList,
|
|
146
147
|
clientFilesPruneCallbackList,
|
|
147
148
|
explorer,
|
|
149
|
+
cacheControl,
|
|
148
150
|
ribbon,
|
|
149
151
|
}),
|
|
150
152
|
],
|
|
@@ -173,18 +175,25 @@ export const createFileService = ({
|
|
|
173
175
|
// when file is modified
|
|
174
176
|
return false
|
|
175
177
|
}
|
|
176
|
-
if (!watch) {
|
|
178
|
+
if (!watch && urlInfo.contentEtag) {
|
|
179
|
+
// file is not watched, check the filesystem
|
|
177
180
|
let fileContentAsBuffer
|
|
178
181
|
try {
|
|
179
182
|
fileContentAsBuffer = readFileSync(new URL(urlInfo.url))
|
|
180
183
|
} catch (e) {
|
|
181
184
|
if (e.code === "ENOENT") {
|
|
185
|
+
// we should consider calling urlGraph.deleteUrlInfo(urlInfo)
|
|
186
|
+
urlInfo.originalContentEtag = undefined
|
|
187
|
+
urlInfo.contentEtag = undefined
|
|
182
188
|
return false
|
|
183
189
|
}
|
|
184
190
|
return false
|
|
185
191
|
}
|
|
186
192
|
const fileContentEtag = bufferToEtag(fileContentAsBuffer)
|
|
187
193
|
if (fileContentEtag !== urlInfo.originalContentEtag) {
|
|
194
|
+
// we should consider calling urlGraph.considerModified(urlInfo)
|
|
195
|
+
urlInfo.originalContentEtag = undefined
|
|
196
|
+
urlInfo.contentEtag = undefined
|
|
188
197
|
return false
|
|
189
198
|
}
|
|
190
199
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# dev/
|
|
2
|
+
|
|
3
|
+
Code implementing jsenv dev server can be found here.
|
|
4
|
+
|
|
5
|
+
# Description
|
|
6
|
+
|
|
7
|
+
Jsenv dev server is a file server injecting code into HTML to autoreload when a file is saved.
|
|
8
|
+
|
|
9
|
+
It uses a plugin pattern allowing to control dev server behaviour
|
|
10
|
+
|
|
11
|
+
- Plugins can be used to transform file content before serving them; And many more things
|
|
12
|
+
- Some plugins are internal to jsenv and can be configured through parameters
|
|
13
|
+
- Some plugins are published in their own packages and can be passed via startDevServer "plugins" parameter
|
|
@@ -72,6 +72,7 @@ export const startDevServer = async ({
|
|
|
72
72
|
fileSystemMagicRedirection,
|
|
73
73
|
transpilation,
|
|
74
74
|
explorer = true, // see jsenv_plugin_explorer.js
|
|
75
|
+
cacheControl = true,
|
|
75
76
|
ribbon = true,
|
|
76
77
|
// toolbar = false,
|
|
77
78
|
|
|
@@ -209,6 +210,7 @@ export const startDevServer = async ({
|
|
|
209
210
|
clientMainFileUrl,
|
|
210
211
|
cooldownBetweenFileEvents,
|
|
211
212
|
explorer,
|
|
213
|
+
cacheControl,
|
|
212
214
|
ribbon,
|
|
213
215
|
sourcemaps,
|
|
214
216
|
sourcemapsSourcesProtocol,
|
package/src/execute/execute.js
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Export a function capable to execute a file on a runtime (browser or node) and return how it goes.
|
|
3
|
+
*
|
|
4
|
+
* - can be useful to execute a file in a browser/node.js programmatically
|
|
5
|
+
* - not documented
|
|
6
|
+
* - the most importants parts:
|
|
7
|
+
* - fileRelativeUrl: the file to execute inside rootDirectoryUrl
|
|
8
|
+
* - runtime: an object with a "run" method.
|
|
9
|
+
* The run method will start a browser/node process and execute file in it
|
|
10
|
+
* - Most of the logic lives in "./run.js" used by executeTestPlan to run tests
|
|
11
|
+
*/
|
|
12
|
+
|
|
1
13
|
import { Abort, raceProcessTeardownEvents } from "@jsenv/abort"
|
|
2
14
|
import { assertAndNormalizeDirectoryUrl } from "@jsenv/filesystem"
|
|
3
15
|
import { createLogger } from "@jsenv/log"
|
|
@@ -51,13 +63,13 @@ export const execute = async ({
|
|
|
51
63
|
if (runtime.type === "browser") {
|
|
52
64
|
if (!devServerOrigin) {
|
|
53
65
|
throw new TypeError(
|
|
54
|
-
`devServerOrigin is required
|
|
66
|
+
`devServerOrigin is required to execute file on a browser`,
|
|
55
67
|
)
|
|
56
68
|
}
|
|
57
69
|
const devServerStarted = await pingServer(devServerOrigin)
|
|
58
70
|
if (!devServerStarted) {
|
|
59
71
|
throw new Error(
|
|
60
|
-
`
|
|
72
|
+
`no server listening at ${devServerOrigin}. It is required to execute file`,
|
|
61
73
|
)
|
|
62
74
|
}
|
|
63
75
|
}
|
package/src/execute/run.js
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Export a function capable to run a file on a runtime.
|
|
3
|
+
*
|
|
4
|
+
* - Used internally by "executeTestPlan" part of the documented API
|
|
5
|
+
* - Used internally by "execute" an advanced API not documented
|
|
6
|
+
* - logs generated during file execution can be collected
|
|
7
|
+
* - logs generated during file execution can be mirrored (re-logged to the console)
|
|
8
|
+
* - File is given allocatedMs to complete
|
|
9
|
+
* - Errors are collected
|
|
10
|
+
* - File execution result is returned, it contains status/errors/namespace/consoleCalls
|
|
11
|
+
*/
|
|
12
|
+
|
|
1
13
|
import { createId } from "@paralleldrive/cuid2"
|
|
2
14
|
import { Abort, raceCallbacks } from "@jsenv/abort"
|
|
3
15
|
import { ensureParentDirectories } from "@jsenv/filesystem"
|
|
@@ -2,7 +2,9 @@ import { createRuntimeFromPlaywright } from "./from_playwright.js"
|
|
|
2
2
|
|
|
3
3
|
export const chromium = createRuntimeFromPlaywright({
|
|
4
4
|
browserName: "chromium",
|
|
5
|
-
browserVersion
|
|
5
|
+
// browserVersion will be set by "browser._initializer.version"
|
|
6
|
+
// see also https://github.com/microsoft/playwright/releases
|
|
7
|
+
browserVersion: "unset",
|
|
6
8
|
coveragePlaywrightAPIAvailable: true,
|
|
7
9
|
})
|
|
8
10
|
export const chromiumIsolatedTab = chromium.isolatedTab
|
|
@@ -2,6 +2,8 @@ import { createRuntimeFromPlaywright } from "./from_playwright.js"
|
|
|
2
2
|
|
|
3
3
|
export const firefox = createRuntimeFromPlaywright({
|
|
4
4
|
browserName: "firefox",
|
|
5
|
-
browserVersion
|
|
5
|
+
// browserVersion will be set by "browser._initializer.version"
|
|
6
|
+
// see also https://github.com/microsoft/playwright/releases
|
|
7
|
+
browserVersion: "unset",
|
|
6
8
|
})
|
|
7
9
|
export const firefoxIsolatedTab = firefox.isolatedTab
|
|
@@ -46,8 +46,8 @@ export const createRuntimeFromPlaywright = ({
|
|
|
46
46
|
keepRunning,
|
|
47
47
|
onConsole,
|
|
48
48
|
|
|
49
|
-
executablePath,
|
|
50
49
|
headful = keepRunning,
|
|
50
|
+
playwrightLaunchOptions = {},
|
|
51
51
|
ignoreHTTPSErrors = true,
|
|
52
52
|
}) => {
|
|
53
53
|
const cleanupCallbackList = createCallbackListNotifiedOnce()
|
|
@@ -62,11 +62,14 @@ export const createRuntimeFromPlaywright = ({
|
|
|
62
62
|
signal,
|
|
63
63
|
browserName,
|
|
64
64
|
stopOnExit: true,
|
|
65
|
-
|
|
65
|
+
playwrightLaunchOptions: {
|
|
66
|
+
...playwrightLaunchOptions,
|
|
66
67
|
headless: !headful,
|
|
67
|
-
executablePath,
|
|
68
68
|
},
|
|
69
69
|
})
|
|
70
|
+
if (browser._initializer.version) {
|
|
71
|
+
runtime.version = browser._initializer.version
|
|
72
|
+
}
|
|
70
73
|
const browserContext = await browser.newContext({ ignoreHTTPSErrors })
|
|
71
74
|
return { browser, browserContext }
|
|
72
75
|
})()
|
|
@@ -409,7 +412,7 @@ const launchBrowserUsingPlaywright = async ({
|
|
|
409
412
|
signal,
|
|
410
413
|
browserName,
|
|
411
414
|
stopOnExit,
|
|
412
|
-
|
|
415
|
+
playwrightLaunchOptions,
|
|
413
416
|
}) => {
|
|
414
417
|
const launchBrowserOperation = Abort.startOperation()
|
|
415
418
|
launchBrowserOperation.addAbortSignal(signal)
|
|
@@ -431,7 +434,7 @@ const launchBrowserUsingPlaywright = async ({
|
|
|
431
434
|
const browserClass = playwright[browserName]
|
|
432
435
|
try {
|
|
433
436
|
const browser = await browserClass.launch({
|
|
434
|
-
...
|
|
437
|
+
...playwrightLaunchOptions,
|
|
435
438
|
// let's handle them to close properly browser + remove listener
|
|
436
439
|
// instead of relying on playwright to do so
|
|
437
440
|
handleSIGINT: false,
|