@jsenv/core 27.0.0-alpha.92 → 27.0.0-alpha.95
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/main.js +211 -170
- package/package.json +10 -10
- package/src/build/build.js +7 -6
- package/src/build/start_build_server.js +72 -50
- package/src/dev/start_dev_server.js +63 -53
- package/src/execute/run.js +7 -1
- package/src/execute/runtimes/browsers/from_playwright.js +1 -1
- package/src/helpers/worker_reload.js +4 -4
- package/src/main.js +1 -4
- package/src/omega/compat/features_compats.js +5 -3
- package/src/plugins/plugins.js +4 -0
- package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic_html.js +2 -1
- package/src/test/execute_test_plan.js +6 -9
package/dist/main.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { workerData, Worker, parentPort } from "node:worker_threads";
|
|
1
2
|
import http from "node:http";
|
|
2
3
|
import cluster from "node:cluster";
|
|
3
4
|
import process$1, { memoryUsage } from "node:process";
|
|
@@ -12,7 +13,6 @@ import { performance } from "node:perf_hooks";
|
|
|
12
13
|
import { extname, dirname, basename } from "node:path";
|
|
13
14
|
import { pathToFileURL, fileURLToPath } from "node:url";
|
|
14
15
|
import crypto, { createHash } from "node:crypto";
|
|
15
|
-
import { workerData, Worker } from "node:worker_threads";
|
|
16
16
|
import { parseHtmlString, stringifyHtmlAst, visitHtmlNodes, getHtmlNodeAttribute, setHtmlNodeAttributes, parseSrcSet, getHtmlNodePosition, getHtmlNodeAttributePosition, applyPostCss, postCssPluginUrlVisitor, parseJsUrls, findHtmlNode, getHtmlNodeText, removeHtmlNode, setHtmlNodeText, analyzeScriptNode, applyBabelPlugins, injectScriptNodeAsEarlyAsPossible, createHtmlNode, removeHtmlNodeText, transpileWithParcel, injectJsImport, minifyWithParcel, analyzeLinkNode } from "@jsenv/ast";
|
|
17
17
|
import { createMagicSource, composeTwoSourcemaps, sourcemapConverter, SOURCEMAP, generateSourcemapFileUrl, generateSourcemapDataUrl } from "@jsenv/sourcemap";
|
|
18
18
|
import { createRequire } from "node:module";
|
|
@@ -562,8 +562,8 @@ const parseMs = ms => {
|
|
|
562
562
|
};
|
|
563
563
|
};
|
|
564
564
|
|
|
565
|
-
const byteAsFileSize =
|
|
566
|
-
return formatBytes(
|
|
565
|
+
const byteAsFileSize = numberOfBytes => {
|
|
566
|
+
return formatBytes(numberOfBytes);
|
|
567
567
|
};
|
|
568
568
|
const byteAsMemoryUsage = metricValue => {
|
|
569
569
|
return formatBytes(metricValue, {
|
|
@@ -581,13 +581,14 @@ const formatBytes = (number, {
|
|
|
581
581
|
const exponent = Math.min(Math.floor(Math.log10(number) / 3), BYTE_UNITS.length - 1);
|
|
582
582
|
const unitNumber = number / Math.pow(1000, exponent);
|
|
583
583
|
const unitName = BYTE_UNITS[exponent];
|
|
584
|
-
const
|
|
584
|
+
const maxDecimals = unitNumber < 100 ? 1 : 0;
|
|
585
585
|
const unitNumberRounded = setRoundedPrecision(unitNumber, {
|
|
586
|
-
decimals
|
|
586
|
+
decimals: maxDecimals,
|
|
587
|
+
decimalsWhenSmall: 1
|
|
587
588
|
});
|
|
588
589
|
|
|
589
590
|
if (fixedDecimals) {
|
|
590
|
-
return `${unitNumberRounded.toFixed(
|
|
591
|
+
return `${unitNumberRounded.toFixed(maxDecimals)} ${unitName}`;
|
|
591
592
|
}
|
|
592
593
|
|
|
593
594
|
return `${unitNumberRounded} ${unitName}`;
|
|
@@ -8559,12 +8560,12 @@ const createReloadableWorker = (workerFileUrl, options = {}) => {
|
|
|
8559
8560
|
worker.once("error", error => {
|
|
8560
8561
|
console.error(error);
|
|
8561
8562
|
});
|
|
8562
|
-
await new Promise(resolve => {
|
|
8563
|
-
worker.once("online", resolve);
|
|
8564
|
-
});
|
|
8565
8563
|
worker.once("exit", () => {
|
|
8566
8564
|
worker = null;
|
|
8567
8565
|
});
|
|
8566
|
+
await new Promise(resolve => {
|
|
8567
|
+
worker.once("online", resolve);
|
|
8568
|
+
});
|
|
8568
8569
|
return worker;
|
|
8569
8570
|
};
|
|
8570
8571
|
|
|
@@ -8575,6 +8576,7 @@ const createReloadableWorker = (workerFileUrl, options = {}) => {
|
|
|
8575
8576
|
|
|
8576
8577
|
return {
|
|
8577
8578
|
isPrimary,
|
|
8579
|
+
isWorker: !isPrimary,
|
|
8578
8580
|
load,
|
|
8579
8581
|
reload,
|
|
8580
8582
|
terminate
|
|
@@ -13280,7 +13282,7 @@ const jsenvPluginAsJsClassicHtml = ({
|
|
|
13280
13282
|
appliesDuring: "*",
|
|
13281
13283
|
transformUrlContent: {
|
|
13282
13284
|
html: async (urlInfo, context) => {
|
|
13283
|
-
const shouldTransformScriptTypeModule = !context.isSupportedOnCurrentClients("script_type_module") || !context.isSupportedOnCurrentClients("import_dynamic");
|
|
13285
|
+
const shouldTransformScriptTypeModule = !context.isSupportedOnCurrentClients("script_type_module") || !context.isSupportedOnCurrentClients("import_dynamic") || !context.isSupportedOnCurrentClients("import_meta");
|
|
13284
13286
|
const htmlAst = parseHtmlString(urlInfo.content);
|
|
13285
13287
|
const preloadAsScriptNodes = [];
|
|
13286
13288
|
const modulePreloadNodes = [];
|
|
@@ -13887,14 +13889,16 @@ const featureCompats = {
|
|
|
13887
13889
|
android: "4.4",
|
|
13888
13890
|
samsung: "4"
|
|
13889
13891
|
},
|
|
13892
|
+
// https://caniuse.com/?search=import.meta
|
|
13890
13893
|
import_meta: {
|
|
13894
|
+
android: "9",
|
|
13891
13895
|
chrome: "64",
|
|
13892
13896
|
edge: "79",
|
|
13893
13897
|
firefox: "62",
|
|
13894
|
-
safari: "11.1",
|
|
13895
|
-
opera: "51",
|
|
13896
13898
|
ios: "12",
|
|
13897
|
-
|
|
13899
|
+
opera: "51",
|
|
13900
|
+
safari: "11.1",
|
|
13901
|
+
samsung: "9.2"
|
|
13898
13902
|
},
|
|
13899
13903
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#browser_compatibility
|
|
13900
13904
|
import_dynamic: {
|
|
@@ -16738,6 +16742,10 @@ const getCorePlugins = ({
|
|
|
16738
16742
|
nodeEsmResolution = {};
|
|
16739
16743
|
}
|
|
16740
16744
|
|
|
16745
|
+
if (clientAutoreload === true) {
|
|
16746
|
+
clientAutoreload = {};
|
|
16747
|
+
}
|
|
16748
|
+
|
|
16741
16749
|
return [jsenvPluginUrlAnalysis({
|
|
16742
16750
|
rootDirectoryUrl,
|
|
16743
16751
|
...urlAnalysis
|
|
@@ -16755,7 +16763,7 @@ const getCorePlugins = ({
|
|
|
16755
16763
|
...nodeEsmResolution
|
|
16756
16764
|
}), jsenvPluginUrlResolution(), jsenvPluginUrlVersion(), jsenvPluginCommonJsGlobals(), jsenvPluginImportMetaScenarios(), jsenvPluginNodeRuntime({
|
|
16757
16765
|
runtimeCompat
|
|
16758
|
-
}), jsenvPluginBundling(bundling), jsenvPluginMinification(minification), jsenvPluginImportMetaHot(), ...(clientAutoreload ? [jsenvPluginAutoreload({
|
|
16766
|
+
}), jsenvPluginBundling(bundling), jsenvPluginMinification(minification), jsenvPluginImportMetaHot(), ...(clientAutoreload ? [jsenvPluginAutoreload({ ...clientAutoreload,
|
|
16759
16767
|
rootDirectoryUrl,
|
|
16760
16768
|
urlGraph,
|
|
16761
16769
|
scenario,
|
|
@@ -19264,22 +19272,18 @@ const startDevServer = async ({
|
|
|
19264
19272
|
privateKey,
|
|
19265
19273
|
keepProcessAlive = true,
|
|
19266
19274
|
rootDirectoryUrl,
|
|
19275
|
+
clientFiles = {
|
|
19276
|
+
"./src/": true,
|
|
19277
|
+
"./tests/": true
|
|
19278
|
+
},
|
|
19267
19279
|
devServerFiles = {
|
|
19268
19280
|
"./package.json": true,
|
|
19269
19281
|
"./jsenv.config.mjs": true
|
|
19270
19282
|
},
|
|
19283
|
+
clientAutoreload = true,
|
|
19284
|
+
devServerAutoreload = false,
|
|
19271
19285
|
devServerMainFile = getCallerPosition().url,
|
|
19272
|
-
// force disable server autoreload when this code is executed:
|
|
19273
|
-
// - inside a forked child process
|
|
19274
|
-
// - debugged by vscode
|
|
19275
|
-
// otherwise we get net:ERR_CONNECTION_REFUSED
|
|
19276
|
-
devServerAutoreload = typeof process.send !== "function" && !process.env.VSCODE_INSPECTOR_OPTIONS,
|
|
19277
|
-
clientFiles = {
|
|
19278
|
-
"./src/": true,
|
|
19279
|
-
"./test/": true
|
|
19280
|
-
},
|
|
19281
19286
|
cooldownBetweenFileEvents,
|
|
19282
|
-
clientAutoreload = true,
|
|
19283
19287
|
sourcemaps = "inline",
|
|
19284
19288
|
// default runtimeCompat assume dev server will be request by recent browsers
|
|
19285
19289
|
// Used by "jsenv_plugin_node_runtime.js" to deactivate itself
|
|
@@ -19303,7 +19307,7 @@ const startDevServer = async ({
|
|
|
19303
19307
|
"./src/**/*.html": true
|
|
19304
19308
|
},
|
|
19305
19309
|
test: {
|
|
19306
|
-
"./
|
|
19310
|
+
"./tests/**/*.test.html": true
|
|
19307
19311
|
}
|
|
19308
19312
|
},
|
|
19309
19313
|
// toolbar = false,
|
|
@@ -19330,68 +19334,74 @@ const startDevServer = async ({
|
|
|
19330
19334
|
});
|
|
19331
19335
|
}
|
|
19332
19336
|
|
|
19333
|
-
|
|
19337
|
+
let reloadableWorker;
|
|
19334
19338
|
|
|
19335
|
-
if (devServerAutoreload
|
|
19336
|
-
|
|
19337
|
-
relativeUrl,
|
|
19338
|
-
event
|
|
19339
|
-
}) => {
|
|
19340
|
-
const url = new URL(relativeUrl, rootDirectoryUrl).href;
|
|
19341
|
-
logger.info(`file ${event} ${url} -> restarting server...`);
|
|
19342
|
-
reloadableWorker.reload();
|
|
19343
|
-
};
|
|
19339
|
+
if (devServerAutoreload) {
|
|
19340
|
+
reloadableWorker = createReloadableWorker(devServerMainFile);
|
|
19344
19341
|
|
|
19345
|
-
|
|
19346
|
-
|
|
19347
|
-
|
|
19348
|
-
|
|
19349
|
-
},
|
|
19350
|
-
cooldownBetweenFileEvents,
|
|
19351
|
-
keepProcessAlive: false,
|
|
19352
|
-
recursive: true,
|
|
19353
|
-
added: ({
|
|
19354
|
-
relativeUrl
|
|
19355
|
-
}) => {
|
|
19356
|
-
devServerFileChangeCallback({
|
|
19357
|
-
relativeUrl,
|
|
19358
|
-
event: "added"
|
|
19359
|
-
});
|
|
19360
|
-
},
|
|
19361
|
-
updated: ({
|
|
19362
|
-
relativeUrl
|
|
19363
|
-
}) => {
|
|
19364
|
-
devServerFileChangeCallback({
|
|
19365
|
-
relativeUrl,
|
|
19366
|
-
event: "modified"
|
|
19367
|
-
});
|
|
19368
|
-
},
|
|
19369
|
-
removed: ({
|
|
19370
|
-
relativeUrl
|
|
19342
|
+
if (reloadableWorker.isPrimary) {
|
|
19343
|
+
const devServerFileChangeCallback = ({
|
|
19344
|
+
relativeUrl,
|
|
19345
|
+
event
|
|
19371
19346
|
}) => {
|
|
19372
|
-
|
|
19373
|
-
|
|
19374
|
-
|
|
19375
|
-
|
|
19376
|
-
}
|
|
19377
|
-
});
|
|
19378
|
-
operation.addAbortCallback(() => {
|
|
19379
|
-
stopWatchingDevServerFiles();
|
|
19380
|
-
reloadableWorker.terminate();
|
|
19381
|
-
});
|
|
19382
|
-
const worker = await reloadableWorker.load();
|
|
19383
|
-
|
|
19384
|
-
if (!keepProcessAlive) {
|
|
19385
|
-
worker.unref();
|
|
19386
|
-
}
|
|
19347
|
+
const url = new URL(relativeUrl, rootDirectoryUrl).href;
|
|
19348
|
+
logger.info(`file ${event} ${url} -> restarting server...`);
|
|
19349
|
+
reloadableWorker.reload();
|
|
19350
|
+
};
|
|
19387
19351
|
|
|
19388
|
-
|
|
19389
|
-
|
|
19390
|
-
|
|
19352
|
+
const stopWatchingDevServerFiles = registerDirectoryLifecycle(rootDirectoryUrl, {
|
|
19353
|
+
watchPatterns: { ...devServerFiles.include,
|
|
19354
|
+
[devServerMainFile]: true,
|
|
19355
|
+
".jsenv/": false
|
|
19356
|
+
},
|
|
19357
|
+
cooldownBetweenFileEvents,
|
|
19358
|
+
keepProcessAlive: false,
|
|
19359
|
+
recursive: true,
|
|
19360
|
+
added: ({
|
|
19361
|
+
relativeUrl
|
|
19362
|
+
}) => {
|
|
19363
|
+
devServerFileChangeCallback({
|
|
19364
|
+
relativeUrl,
|
|
19365
|
+
event: "added"
|
|
19366
|
+
});
|
|
19367
|
+
},
|
|
19368
|
+
updated: ({
|
|
19369
|
+
relativeUrl
|
|
19370
|
+
}) => {
|
|
19371
|
+
devServerFileChangeCallback({
|
|
19372
|
+
relativeUrl,
|
|
19373
|
+
event: "modified"
|
|
19374
|
+
});
|
|
19375
|
+
},
|
|
19376
|
+
removed: ({
|
|
19377
|
+
relativeUrl
|
|
19378
|
+
}) => {
|
|
19379
|
+
devServerFileChangeCallback({
|
|
19380
|
+
relativeUrl,
|
|
19381
|
+
event: "removed"
|
|
19382
|
+
});
|
|
19383
|
+
}
|
|
19384
|
+
});
|
|
19385
|
+
operation.addAbortCallback(() => {
|
|
19391
19386
|
stopWatchingDevServerFiles();
|
|
19392
19387
|
reloadableWorker.terminate();
|
|
19393
|
-
}
|
|
19394
|
-
|
|
19388
|
+
});
|
|
19389
|
+
const worker = await reloadableWorker.load();
|
|
19390
|
+
const messagePromise = new Promise(resolve => {
|
|
19391
|
+
worker.once("message", resolve);
|
|
19392
|
+
});
|
|
19393
|
+
await messagePromise; // if (!keepProcessAlive) {
|
|
19394
|
+
// worker.unref()
|
|
19395
|
+
// }
|
|
19396
|
+
|
|
19397
|
+
return {
|
|
19398
|
+
origin: `${protocol}://127.0.0.1:${port}`,
|
|
19399
|
+
stop: () => {
|
|
19400
|
+
stopWatchingDevServerFiles();
|
|
19401
|
+
reloadableWorker.terminate();
|
|
19402
|
+
}
|
|
19403
|
+
};
|
|
19404
|
+
}
|
|
19395
19405
|
}
|
|
19396
19406
|
|
|
19397
19407
|
const startDevServerTask = createTaskLog("start dev server", {
|
|
@@ -19414,7 +19424,9 @@ const startDevServer = async ({
|
|
|
19414
19424
|
};
|
|
19415
19425
|
|
|
19416
19426
|
const stopWatchingClientFiles = registerDirectoryLifecycle(rootDirectoryUrl, {
|
|
19417
|
-
watchPatterns: clientFiles,
|
|
19427
|
+
watchPatterns: { ...clientFiles,
|
|
19428
|
+
".jsenv/": false
|
|
19429
|
+
},
|
|
19418
19430
|
cooldownBetweenFileEvents,
|
|
19419
19431
|
keepProcessAlive: false,
|
|
19420
19432
|
recursive: true,
|
|
@@ -19499,6 +19511,11 @@ const startDevServer = async ({
|
|
|
19499
19511
|
kitchen.pluginController.callHooks("destroy", {});
|
|
19500
19512
|
};
|
|
19501
19513
|
});
|
|
19514
|
+
|
|
19515
|
+
if (reloadableWorker && reloadableWorker.isWorker) {
|
|
19516
|
+
parentPort.postMessage(server.origin);
|
|
19517
|
+
}
|
|
19518
|
+
|
|
19502
19519
|
return {
|
|
19503
19520
|
origin: server.origin,
|
|
19504
19521
|
stop: () => {
|
|
@@ -20207,7 +20224,9 @@ const run = async ({
|
|
|
20207
20224
|
const runOperation = Abort.startOperation();
|
|
20208
20225
|
runOperation.addAbortSignal(signal);
|
|
20209
20226
|
|
|
20210
|
-
if (
|
|
20227
|
+
if ( // ideally we would rather log than the timeout is ignored
|
|
20228
|
+
// when keepRunning is true
|
|
20229
|
+
!keepRunning && typeof allocatedMs === "number" && allocatedMs !== Infinity) {
|
|
20211
20230
|
const timeoutAbortSource = runOperation.timeout(allocatedMs);
|
|
20212
20231
|
resultTransformer = composeTransformer$1(resultTransformer, result => {
|
|
20213
20232
|
if (result.status === "errored" && Abort.isAbortError(result.error) && timeoutAbortSource.signal.aborted) {
|
|
@@ -21224,15 +21243,6 @@ const executeInParallel = async ({
|
|
|
21224
21243
|
return executionResults;
|
|
21225
21244
|
};
|
|
21226
21245
|
|
|
21227
|
-
const defaultCoverageConfig = {
|
|
21228
|
-
"./index.js": true,
|
|
21229
|
-
"./main.js": true,
|
|
21230
|
-
"./src/**/*.js": true,
|
|
21231
|
-
"./**/*.test.*": false,
|
|
21232
|
-
// contains .test. -> nope
|
|
21233
|
-
"./**/test/": false // inside a test folder -> nope,
|
|
21234
|
-
|
|
21235
|
-
};
|
|
21236
21246
|
/**
|
|
21237
21247
|
* Execute a list of files and log how it goes
|
|
21238
21248
|
* @param {Object} testPlanParameters
|
|
@@ -21276,7 +21286,15 @@ const executeTestPlan = async ({
|
|
|
21276
21286
|
gcBetweenExecutions = logMemoryHeapUsage,
|
|
21277
21287
|
coverage = process.argv.includes("--cover") || process.argv.includes("--coverage"),
|
|
21278
21288
|
coverageTempDirectoryRelativeUrl = "./.coverage/tmp/",
|
|
21279
|
-
coverageConfig =
|
|
21289
|
+
coverageConfig = {
|
|
21290
|
+
"./src/**/*.js": true,
|
|
21291
|
+
"./**/*.test.*": false,
|
|
21292
|
+
// contains .test. -> no
|
|
21293
|
+
"./**/test/": false,
|
|
21294
|
+
// inside a test directory -> no
|
|
21295
|
+
"./**/tests/": false // inside a tests directory -> no
|
|
21296
|
+
|
|
21297
|
+
},
|
|
21280
21298
|
coverageIncludeMissing = true,
|
|
21281
21299
|
coverageAndExecutionAllowed = false,
|
|
21282
21300
|
coverageForceIstanbul = false,
|
|
@@ -21517,7 +21535,7 @@ const createRuntimeFromPlaywright = ({
|
|
|
21517
21535
|
keepRunning,
|
|
21518
21536
|
onConsole,
|
|
21519
21537
|
executablePath,
|
|
21520
|
-
headful =
|
|
21538
|
+
headful = keepRunning,
|
|
21521
21539
|
ignoreHTTPSErrors = true
|
|
21522
21540
|
}) => {
|
|
21523
21541
|
const cleanupCallbackList = createCallbackListNotifiedOnce();
|
|
@@ -23531,17 +23549,18 @@ const build = async ({
|
|
|
23531
23549
|
buildDirectoryUrl,
|
|
23532
23550
|
entryPoints = {},
|
|
23533
23551
|
baseUrl = "/",
|
|
23534
|
-
// default runtimeCompat corresponds to
|
|
23535
|
-
//
|
|
23552
|
+
// default runtimeCompat corresponds to
|
|
23553
|
+
// "we can keep <script type="module"> intact":
|
|
23554
|
+
// so script_type_module + dynamic_import + import_meta
|
|
23536
23555
|
runtimeCompat = {
|
|
23537
23556
|
// android: "8",
|
|
23538
|
-
chrome: "
|
|
23557
|
+
chrome: "64",
|
|
23539
23558
|
edge: "79",
|
|
23540
23559
|
firefox: "67",
|
|
23541
|
-
ios: "
|
|
23542
|
-
opera: "
|
|
23560
|
+
ios: "12",
|
|
23561
|
+
opera: "51",
|
|
23543
23562
|
safari: "11.3",
|
|
23544
|
-
samsung: "
|
|
23563
|
+
samsung: "9.2"
|
|
23545
23564
|
},
|
|
23546
23565
|
plugins = [],
|
|
23547
23566
|
sourcemaps = false,
|
|
@@ -24756,17 +24775,13 @@ const startBuildServer = async ({
|
|
|
24756
24775
|
keepProcessAlive = true,
|
|
24757
24776
|
rootDirectoryUrl,
|
|
24758
24777
|
buildDirectoryUrl,
|
|
24759
|
-
|
|
24778
|
+
buildIndexPath = "/index.html",
|
|
24760
24779
|
buildServerFiles = {
|
|
24761
24780
|
"./package.json": true,
|
|
24762
24781
|
"./jsenv.config.mjs": true
|
|
24763
24782
|
},
|
|
24783
|
+
buildServerAutoreload = false,
|
|
24764
24784
|
buildServerMainFile = getCallerPosition().url,
|
|
24765
|
-
// force disable server autoreload when this code is executed:
|
|
24766
|
-
// - inside a forked child process
|
|
24767
|
-
// - debugged by vscode
|
|
24768
|
-
// otherwise we get net:ERR_CONNECTION_REFUSED
|
|
24769
|
-
buildServerAutoreload = typeof process.send !== "function" && !process.env.VSCODE_INSPECTOR_OPTIONS,
|
|
24770
24785
|
cooldownBetweenFileEvents
|
|
24771
24786
|
}) => {
|
|
24772
24787
|
const logger = createLogger({
|
|
@@ -24774,6 +24789,23 @@ const startBuildServer = async ({
|
|
|
24774
24789
|
});
|
|
24775
24790
|
rootDirectoryUrl = assertAndNormalizeDirectoryUrl(rootDirectoryUrl);
|
|
24776
24791
|
buildDirectoryUrl = assertAndNormalizeDirectoryUrl(buildDirectoryUrl);
|
|
24792
|
+
|
|
24793
|
+
if (buildIndexPath) {
|
|
24794
|
+
if (typeof buildIndexPath !== "string") {
|
|
24795
|
+
throw new TypeError(`buildIndexPath must be a string, got ${buildIndexPath}`);
|
|
24796
|
+
}
|
|
24797
|
+
|
|
24798
|
+
if (buildIndexPath[0] !== "/") {
|
|
24799
|
+
const buildIndexUrl = new URL(buildIndexPath, buildDirectoryUrl).href;
|
|
24800
|
+
|
|
24801
|
+
if (!buildIndexUrl.startsWith(buildDirectoryUrl)) {
|
|
24802
|
+
throw new Error(`buildIndexPath must be relative, got ${buildIndexPath}`);
|
|
24803
|
+
}
|
|
24804
|
+
|
|
24805
|
+
buildIndexPath = buildIndexUrl.slice(buildDirectoryUrl.length);
|
|
24806
|
+
}
|
|
24807
|
+
}
|
|
24808
|
+
|
|
24777
24809
|
const operation = Abort.startOperation();
|
|
24778
24810
|
operation.addAbortSignal(signal);
|
|
24779
24811
|
|
|
@@ -24791,71 +24823,74 @@ const startBuildServer = async ({
|
|
|
24791
24823
|
});
|
|
24792
24824
|
}
|
|
24793
24825
|
|
|
24794
|
-
|
|
24826
|
+
let reloadableWorker;
|
|
24795
24827
|
|
|
24796
|
-
if (buildServerAutoreload
|
|
24797
|
-
|
|
24798
|
-
relativeUrl,
|
|
24799
|
-
event
|
|
24800
|
-
}) => {
|
|
24801
|
-
const url = new URL(relativeUrl, rootDirectoryUrl).href;
|
|
24828
|
+
if (buildServerAutoreload) {
|
|
24829
|
+
reloadableWorker = createReloadableWorker(buildServerMainFile);
|
|
24802
24830
|
|
|
24803
|
-
|
|
24831
|
+
if (reloadableWorker.isPrimary) {
|
|
24832
|
+
const buildServerFileChangeCallback = ({
|
|
24833
|
+
relativeUrl,
|
|
24834
|
+
event
|
|
24835
|
+
}) => {
|
|
24836
|
+
const url = new URL(relativeUrl, rootDirectoryUrl).href;
|
|
24804
24837
|
logger.info(`file ${event} ${url} -> restarting server...`);
|
|
24805
24838
|
reloadableWorker.reload();
|
|
24806
|
-
}
|
|
24807
|
-
};
|
|
24808
|
-
|
|
24809
|
-
const stopWatchingBuildServerFiles = registerDirectoryLifecycle(rootDirectoryUrl, {
|
|
24810
|
-
watchPatterns: {
|
|
24811
|
-
[buildServerMainFile]: true,
|
|
24812
|
-
...buildServerFiles
|
|
24813
|
-
},
|
|
24814
|
-
cooldownBetweenFileEvents,
|
|
24815
|
-
keepProcessAlive: false,
|
|
24816
|
-
recursive: true,
|
|
24817
|
-
added: ({
|
|
24818
|
-
relativeUrl
|
|
24819
|
-
}) => {
|
|
24820
|
-
buildServerFileChangeCallback({
|
|
24821
|
-
relativeUrl,
|
|
24822
|
-
event: "added"
|
|
24823
|
-
});
|
|
24824
|
-
},
|
|
24825
|
-
updated: ({
|
|
24826
|
-
relativeUrl
|
|
24827
|
-
}) => {
|
|
24828
|
-
buildServerFileChangeCallback({
|
|
24829
|
-
relativeUrl,
|
|
24830
|
-
event: "modified"
|
|
24831
|
-
});
|
|
24832
|
-
},
|
|
24833
|
-
removed: ({
|
|
24834
|
-
relativeUrl
|
|
24835
|
-
}) => {
|
|
24836
|
-
buildServerFileChangeCallback({
|
|
24837
|
-
relativeUrl,
|
|
24838
|
-
event: "removed"
|
|
24839
|
-
});
|
|
24840
|
-
}
|
|
24841
|
-
});
|
|
24842
|
-
operation.addAbortCallback(() => {
|
|
24843
|
-
stopWatchingBuildServerFiles();
|
|
24844
|
-
reloadableWorker.terminate();
|
|
24845
|
-
});
|
|
24846
|
-
const worker = await reloadableWorker.load();
|
|
24847
|
-
|
|
24848
|
-
if (!keepProcessAlive) {
|
|
24849
|
-
worker.unref();
|
|
24850
|
-
}
|
|
24839
|
+
};
|
|
24851
24840
|
|
|
24852
|
-
|
|
24853
|
-
|
|
24854
|
-
|
|
24841
|
+
const stopWatchingBuildServerFiles = registerDirectoryLifecycle(rootDirectoryUrl, {
|
|
24842
|
+
watchPatterns: { ...buildServerFiles,
|
|
24843
|
+
[buildServerMainFile]: true,
|
|
24844
|
+
".jsenv/": false
|
|
24845
|
+
},
|
|
24846
|
+
cooldownBetweenFileEvents,
|
|
24847
|
+
keepProcessAlive: false,
|
|
24848
|
+
recursive: true,
|
|
24849
|
+
added: ({
|
|
24850
|
+
relativeUrl
|
|
24851
|
+
}) => {
|
|
24852
|
+
buildServerFileChangeCallback({
|
|
24853
|
+
relativeUrl,
|
|
24854
|
+
event: "added"
|
|
24855
|
+
});
|
|
24856
|
+
},
|
|
24857
|
+
updated: ({
|
|
24858
|
+
relativeUrl
|
|
24859
|
+
}) => {
|
|
24860
|
+
buildServerFileChangeCallback({
|
|
24861
|
+
relativeUrl,
|
|
24862
|
+
event: "modified"
|
|
24863
|
+
});
|
|
24864
|
+
},
|
|
24865
|
+
removed: ({
|
|
24866
|
+
relativeUrl
|
|
24867
|
+
}) => {
|
|
24868
|
+
buildServerFileChangeCallback({
|
|
24869
|
+
relativeUrl,
|
|
24870
|
+
event: "removed"
|
|
24871
|
+
});
|
|
24872
|
+
}
|
|
24873
|
+
});
|
|
24874
|
+
operation.addAbortCallback(() => {
|
|
24855
24875
|
stopWatchingBuildServerFiles();
|
|
24856
24876
|
reloadableWorker.terminate();
|
|
24857
|
-
}
|
|
24858
|
-
|
|
24877
|
+
});
|
|
24878
|
+
const worker = await reloadableWorker.load();
|
|
24879
|
+
const messagePromise = new Promise(resolve => {
|
|
24880
|
+
worker.once("message", resolve);
|
|
24881
|
+
});
|
|
24882
|
+
await messagePromise; // if (!keepProcessAlive) {
|
|
24883
|
+
// worker.unref()
|
|
24884
|
+
// }
|
|
24885
|
+
|
|
24886
|
+
return {
|
|
24887
|
+
origin: `${protocol}://127.0.0.1:${port}`,
|
|
24888
|
+
stop: () => {
|
|
24889
|
+
stopWatchingBuildServerFiles();
|
|
24890
|
+
reloadableWorker.terminate();
|
|
24891
|
+
}
|
|
24892
|
+
};
|
|
24893
|
+
}
|
|
24859
24894
|
}
|
|
24860
24895
|
|
|
24861
24896
|
const startBuildServerTask = createTaskLog("start build server", {
|
|
@@ -24866,7 +24901,8 @@ const startBuildServer = async ({
|
|
|
24866
24901
|
stopOnExit: false,
|
|
24867
24902
|
stopOnSIGINT: false,
|
|
24868
24903
|
stopOnInternalError: false,
|
|
24869
|
-
|
|
24904
|
+
// the worker should be kept alive by the parent otherwise
|
|
24905
|
+
keepProcessAlive,
|
|
24870
24906
|
logLevel: serverLogLevel,
|
|
24871
24907
|
startLog: false,
|
|
24872
24908
|
protocol,
|
|
@@ -24892,7 +24928,7 @@ const startBuildServer = async ({
|
|
|
24892
24928
|
requestToResponse: composeServices({ ...services,
|
|
24893
24929
|
build_files_service: createBuildFilesService({
|
|
24894
24930
|
buildDirectoryUrl,
|
|
24895
|
-
|
|
24931
|
+
buildIndexPath
|
|
24896
24932
|
})
|
|
24897
24933
|
})
|
|
24898
24934
|
});
|
|
@@ -24902,6 +24938,11 @@ const startBuildServer = async ({
|
|
|
24902
24938
|
logger.info(`- ${server.origins[key]}`);
|
|
24903
24939
|
});
|
|
24904
24940
|
logger.info(``);
|
|
24941
|
+
|
|
24942
|
+
if (reloadableWorker && reloadableWorker.isWorker) {
|
|
24943
|
+
parentPort.postMessage(server.origin);
|
|
24944
|
+
}
|
|
24945
|
+
|
|
24905
24946
|
return {
|
|
24906
24947
|
origin: server.origin,
|
|
24907
24948
|
stop: () => {
|
|
@@ -24912,14 +24953,14 @@ const startBuildServer = async ({
|
|
|
24912
24953
|
|
|
24913
24954
|
const createBuildFilesService = ({
|
|
24914
24955
|
buildDirectoryUrl,
|
|
24915
|
-
|
|
24956
|
+
buildIndexPath
|
|
24916
24957
|
}) => {
|
|
24917
24958
|
return request => {
|
|
24918
24959
|
const urlIsVersioned = new URL(request.ressource, request.origin).searchParams.has("v");
|
|
24919
24960
|
|
|
24920
|
-
if (
|
|
24961
|
+
if (buildIndexPath && request.ressource === "/") {
|
|
24921
24962
|
request = { ...request,
|
|
24922
|
-
ressource:
|
|
24963
|
+
ressource: `/${buildIndexPath}`
|
|
24923
24964
|
};
|
|
24924
24965
|
}
|
|
24925
24966
|
|
|
@@ -25160,4 +25201,4 @@ const jsenvPluginInjectGlobals = urlAssociations => {
|
|
|
25160
25201
|
};
|
|
25161
25202
|
};
|
|
25162
25203
|
|
|
25163
|
-
export { build, chromium, chromiumIsolatedTab,
|
|
25204
|
+
export { build, chromium, chromiumIsolatedTab, execute, executeTestPlan, firefox, firefoxIsolatedTab, jsenvPluginInjectGlobals, nodeProcess, startBuildServer, startDevServer, webkit, webkitIsolatedTab };
|
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.95",
|
|
4
4
|
"description": "Tool to develop, test and build js projects",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
@@ -71,13 +71,13 @@
|
|
|
71
71
|
"@jsenv/importmap": "1.2.1",
|
|
72
72
|
"@jsenv/integrity": "0.0.1",
|
|
73
73
|
"@jsenv/node-esm-resolution": "0.1.0",
|
|
74
|
-
"@jsenv/server": "12.7.
|
|
74
|
+
"@jsenv/server": "12.7.3",
|
|
75
75
|
"@jsenv/uneval": "1.6.0",
|
|
76
76
|
"@jsenv/url-meta": "7.0.0",
|
|
77
77
|
"@jsenv/urls": "1.2.6",
|
|
78
78
|
"@jsenv/utils": "2.0.1",
|
|
79
79
|
"@jsenv/babel-plugins": "1.0.5",
|
|
80
|
-
"@jsenv/log": "2.0
|
|
80
|
+
"@jsenv/log": "2.1.0",
|
|
81
81
|
"@jsenv/sourcemap": "1.0.1",
|
|
82
82
|
"acorn-import-assertions": "1.8.0",
|
|
83
83
|
"cuid": "2.1.8",
|
|
@@ -97,17 +97,17 @@
|
|
|
97
97
|
"devDependencies": {
|
|
98
98
|
"@babel/eslint-parser": "7.18.2",
|
|
99
99
|
"@babel/plugin-syntax-import-assertions": "7.17.12",
|
|
100
|
-
"@jsenv/assert": "2.
|
|
100
|
+
"@jsenv/assert": "2.6.0",
|
|
101
101
|
"@jsenv/eslint-config": "16.0.9",
|
|
102
|
-
"@jsenv/file-size-impact": "
|
|
103
|
-
"@jsenv/https-local": "
|
|
104
|
-
"@jsenv/package-workspace": "0.
|
|
105
|
-
"@jsenv/performance-impact": "
|
|
102
|
+
"@jsenv/file-size-impact": "13.0.0",
|
|
103
|
+
"@jsenv/https-local": "2.1.0",
|
|
104
|
+
"@jsenv/package-workspace": "0.3.0",
|
|
105
|
+
"@jsenv/performance-impact": "3.0.0",
|
|
106
106
|
"eslint": "8.18.0",
|
|
107
107
|
"eslint-plugin-html": "6.2.0",
|
|
108
108
|
"eslint-plugin-import": "2.26.0",
|
|
109
|
-
"eslint-plugin-react": "7.30.
|
|
109
|
+
"eslint-plugin-react": "7.30.1",
|
|
110
110
|
"playwright": "1.22.2",
|
|
111
111
|
"prettier": "2.7.1"
|
|
112
112
|
}
|
|
113
|
-
}
|
|
113
|
+
}
|
package/src/build/build.js
CHANGED
|
@@ -85,17 +85,18 @@ export const build = async ({
|
|
|
85
85
|
entryPoints = {},
|
|
86
86
|
baseUrl = "/",
|
|
87
87
|
|
|
88
|
-
// default runtimeCompat corresponds to
|
|
89
|
-
//
|
|
88
|
+
// default runtimeCompat corresponds to
|
|
89
|
+
// "we can keep <script type="module"> intact":
|
|
90
|
+
// so script_type_module + dynamic_import + import_meta
|
|
90
91
|
runtimeCompat = {
|
|
91
92
|
// android: "8",
|
|
92
|
-
chrome: "
|
|
93
|
+
chrome: "64",
|
|
93
94
|
edge: "79",
|
|
94
95
|
firefox: "67",
|
|
95
|
-
ios: "
|
|
96
|
-
opera: "
|
|
96
|
+
ios: "12",
|
|
97
|
+
opera: "51",
|
|
97
98
|
safari: "11.3",
|
|
98
|
-
samsung: "
|
|
99
|
+
samsung: "9.2",
|
|
99
100
|
},
|
|
100
101
|
plugins = [],
|
|
101
102
|
sourcemaps = false,
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* we want to be in the user shoes and we should not alter build files.
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
+
import { parentPort } from "node:worker_threads"
|
|
16
17
|
import {
|
|
17
18
|
jsenvAccessControlAllowedHeaders,
|
|
18
19
|
startServer,
|
|
@@ -50,23 +51,34 @@ export const startBuildServer = async ({
|
|
|
50
51
|
|
|
51
52
|
rootDirectoryUrl,
|
|
52
53
|
buildDirectoryUrl,
|
|
53
|
-
|
|
54
|
+
buildIndexPath = "/index.html",
|
|
54
55
|
buildServerFiles = {
|
|
55
56
|
"./package.json": true,
|
|
56
57
|
"./jsenv.config.mjs": true,
|
|
57
58
|
},
|
|
59
|
+
buildServerAutoreload = false,
|
|
58
60
|
buildServerMainFile = getCallerPosition().url,
|
|
59
|
-
// force disable server autoreload when this code is executed:
|
|
60
|
-
// - inside a forked child process
|
|
61
|
-
// - debugged by vscode
|
|
62
|
-
// otherwise we get net:ERR_CONNECTION_REFUSED
|
|
63
|
-
buildServerAutoreload = typeof process.send !== "function" &&
|
|
64
|
-
!process.env.VSCODE_INSPECTOR_OPTIONS,
|
|
65
61
|
cooldownBetweenFileEvents,
|
|
66
62
|
}) => {
|
|
67
63
|
const logger = createLogger({ logLevel })
|
|
68
64
|
rootDirectoryUrl = assertAndNormalizeDirectoryUrl(rootDirectoryUrl)
|
|
69
65
|
buildDirectoryUrl = assertAndNormalizeDirectoryUrl(buildDirectoryUrl)
|
|
66
|
+
if (buildIndexPath) {
|
|
67
|
+
if (typeof buildIndexPath !== "string") {
|
|
68
|
+
throw new TypeError(
|
|
69
|
+
`buildIndexPath must be a string, got ${buildIndexPath}`,
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
if (buildIndexPath[0] !== "/") {
|
|
73
|
+
const buildIndexUrl = new URL(buildIndexPath, buildDirectoryUrl).href
|
|
74
|
+
if (!buildIndexUrl.startsWith(buildDirectoryUrl)) {
|
|
75
|
+
throw new Error(
|
|
76
|
+
`buildIndexPath must be relative, got ${buildIndexPath}`,
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
buildIndexPath = buildIndexUrl.slice(buildDirectoryUrl.length)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
70
82
|
|
|
71
83
|
const operation = Abort.startOperation()
|
|
72
84
|
operation.addAbortSignal(signal)
|
|
@@ -84,50 +96,56 @@ export const startBuildServer = async ({
|
|
|
84
96
|
port = await findFreePort(port, { signal: operation.signal })
|
|
85
97
|
}
|
|
86
98
|
|
|
87
|
-
|
|
88
|
-
if (buildServerAutoreload
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
99
|
+
let reloadableWorker
|
|
100
|
+
if (buildServerAutoreload) {
|
|
101
|
+
reloadableWorker = createReloadableWorker(buildServerMainFile)
|
|
102
|
+
if (reloadableWorker.isPrimary) {
|
|
103
|
+
const buildServerFileChangeCallback = ({ relativeUrl, event }) => {
|
|
104
|
+
const url = new URL(relativeUrl, rootDirectoryUrl).href
|
|
92
105
|
logger.info(`file ${event} ${url} -> restarting server...`)
|
|
93
106
|
reloadableWorker.reload()
|
|
94
107
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
108
|
+
const stopWatchingBuildServerFiles = registerDirectoryLifecycle(
|
|
109
|
+
rootDirectoryUrl,
|
|
110
|
+
{
|
|
111
|
+
watchPatterns: {
|
|
112
|
+
...buildServerFiles,
|
|
113
|
+
[buildServerMainFile]: true,
|
|
114
|
+
".jsenv/": false,
|
|
115
|
+
},
|
|
116
|
+
cooldownBetweenFileEvents,
|
|
117
|
+
keepProcessAlive: false,
|
|
118
|
+
recursive: true,
|
|
119
|
+
added: ({ relativeUrl }) => {
|
|
120
|
+
buildServerFileChangeCallback({ relativeUrl, event: "added" })
|
|
121
|
+
},
|
|
122
|
+
updated: ({ relativeUrl }) => {
|
|
123
|
+
buildServerFileChangeCallback({ relativeUrl, event: "modified" })
|
|
124
|
+
},
|
|
125
|
+
removed: ({ relativeUrl }) => {
|
|
126
|
+
buildServerFileChangeCallback({ relativeUrl, event: "removed" })
|
|
127
|
+
},
|
|
114
128
|
},
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
operation.addAbortCallback(() => {
|
|
118
|
-
stopWatchingBuildServerFiles()
|
|
119
|
-
reloadableWorker.terminate()
|
|
120
|
-
})
|
|
121
|
-
const worker = await reloadableWorker.load()
|
|
122
|
-
if (!keepProcessAlive) {
|
|
123
|
-
worker.unref()
|
|
124
|
-
}
|
|
125
|
-
return {
|
|
126
|
-
origin: `${protocol}://127.0.0.1:${port}`,
|
|
127
|
-
stop: () => {
|
|
129
|
+
)
|
|
130
|
+
operation.addAbortCallback(() => {
|
|
128
131
|
stopWatchingBuildServerFiles()
|
|
129
132
|
reloadableWorker.terminate()
|
|
130
|
-
}
|
|
133
|
+
})
|
|
134
|
+
const worker = await reloadableWorker.load()
|
|
135
|
+
const messagePromise = new Promise((resolve) => {
|
|
136
|
+
worker.once("message", resolve)
|
|
137
|
+
})
|
|
138
|
+
await messagePromise
|
|
139
|
+
// if (!keepProcessAlive) {
|
|
140
|
+
// worker.unref()
|
|
141
|
+
// }
|
|
142
|
+
return {
|
|
143
|
+
origin: `${protocol}://127.0.0.1:${port}`,
|
|
144
|
+
stop: () => {
|
|
145
|
+
stopWatchingBuildServerFiles()
|
|
146
|
+
reloadableWorker.terminate()
|
|
147
|
+
},
|
|
148
|
+
}
|
|
131
149
|
}
|
|
132
150
|
}
|
|
133
151
|
|
|
@@ -139,7 +157,8 @@ export const startBuildServer = async ({
|
|
|
139
157
|
stopOnExit: false,
|
|
140
158
|
stopOnSIGINT: false,
|
|
141
159
|
stopOnInternalError: false,
|
|
142
|
-
|
|
160
|
+
// the worker should be kept alive by the parent otherwise
|
|
161
|
+
keepProcessAlive,
|
|
143
162
|
logLevel: serverLogLevel,
|
|
144
163
|
startLog: false,
|
|
145
164
|
|
|
@@ -168,7 +187,7 @@ export const startBuildServer = async ({
|
|
|
168
187
|
...services,
|
|
169
188
|
build_files_service: createBuildFilesService({
|
|
170
189
|
buildDirectoryUrl,
|
|
171
|
-
|
|
190
|
+
buildIndexPath,
|
|
172
191
|
}),
|
|
173
192
|
}),
|
|
174
193
|
})
|
|
@@ -178,6 +197,9 @@ export const startBuildServer = async ({
|
|
|
178
197
|
logger.info(`- ${server.origins[key]}`)
|
|
179
198
|
})
|
|
180
199
|
logger.info(``)
|
|
200
|
+
if (reloadableWorker && reloadableWorker.isWorker) {
|
|
201
|
+
parentPort.postMessage(server.origin)
|
|
202
|
+
}
|
|
181
203
|
return {
|
|
182
204
|
origin: server.origin,
|
|
183
205
|
stop: () => {
|
|
@@ -186,16 +208,16 @@ export const startBuildServer = async ({
|
|
|
186
208
|
}
|
|
187
209
|
}
|
|
188
210
|
|
|
189
|
-
const createBuildFilesService = ({ buildDirectoryUrl,
|
|
211
|
+
const createBuildFilesService = ({ buildDirectoryUrl, buildIndexPath }) => {
|
|
190
212
|
return (request) => {
|
|
191
213
|
const urlIsVersioned = new URL(
|
|
192
214
|
request.ressource,
|
|
193
215
|
request.origin,
|
|
194
216
|
).searchParams.has("v")
|
|
195
|
-
if (
|
|
217
|
+
if (buildIndexPath && request.ressource === "/") {
|
|
196
218
|
request = {
|
|
197
219
|
...request,
|
|
198
|
-
ressource:
|
|
220
|
+
ressource: `/${buildIndexPath}`,
|
|
199
221
|
}
|
|
200
222
|
}
|
|
201
223
|
return fetchFileSystem(
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { parentPort } from "node:worker_threads"
|
|
1
2
|
import { findFreePort } from "@jsenv/server"
|
|
2
3
|
import {
|
|
3
4
|
assertAndNormalizeDirectoryUrl,
|
|
@@ -31,23 +32,18 @@ export const startDevServer = async ({
|
|
|
31
32
|
privateKey,
|
|
32
33
|
keepProcessAlive = true,
|
|
33
34
|
rootDirectoryUrl,
|
|
35
|
+
clientFiles = {
|
|
36
|
+
"./src/": true,
|
|
37
|
+
"./tests/": true,
|
|
38
|
+
},
|
|
34
39
|
devServerFiles = {
|
|
35
40
|
"./package.json": true,
|
|
36
41
|
"./jsenv.config.mjs": true,
|
|
37
42
|
},
|
|
43
|
+
clientAutoreload = true,
|
|
44
|
+
devServerAutoreload = false,
|
|
38
45
|
devServerMainFile = getCallerPosition().url,
|
|
39
|
-
// force disable server autoreload when this code is executed:
|
|
40
|
-
// - inside a forked child process
|
|
41
|
-
// - debugged by vscode
|
|
42
|
-
// otherwise we get net:ERR_CONNECTION_REFUSED
|
|
43
|
-
devServerAutoreload = typeof process.send !== "function" &&
|
|
44
|
-
!process.env.VSCODE_INSPECTOR_OPTIONS,
|
|
45
|
-
clientFiles = {
|
|
46
|
-
"./src/": true,
|
|
47
|
-
"./test/": true,
|
|
48
|
-
},
|
|
49
46
|
cooldownBetweenFileEvents,
|
|
50
|
-
clientAutoreload = true,
|
|
51
47
|
|
|
52
48
|
sourcemaps = "inline",
|
|
53
49
|
// default runtimeCompat assume dev server will be request by recent browsers
|
|
@@ -72,7 +68,7 @@ export const startDevServer = async ({
|
|
|
72
68
|
"./src/**/*.html": true,
|
|
73
69
|
},
|
|
74
70
|
test: {
|
|
75
|
-
"./
|
|
71
|
+
"./tests/**/*.test.html": true,
|
|
76
72
|
},
|
|
77
73
|
},
|
|
78
74
|
// toolbar = false,
|
|
@@ -96,49 +92,57 @@ export const startDevServer = async ({
|
|
|
96
92
|
port = await findFreePort(port, { signal: operation.signal })
|
|
97
93
|
}
|
|
98
94
|
|
|
99
|
-
|
|
100
|
-
if (devServerAutoreload
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
95
|
+
let reloadableWorker
|
|
96
|
+
if (devServerAutoreload) {
|
|
97
|
+
reloadableWorker = createReloadableWorker(devServerMainFile)
|
|
98
|
+
if (reloadableWorker.isPrimary) {
|
|
99
|
+
const devServerFileChangeCallback = ({ relativeUrl, event }) => {
|
|
100
|
+
const url = new URL(relativeUrl, rootDirectoryUrl).href
|
|
101
|
+
logger.info(`file ${event} ${url} -> restarting server...`)
|
|
102
|
+
reloadableWorker.reload()
|
|
103
|
+
}
|
|
104
|
+
const stopWatchingDevServerFiles = registerDirectoryLifecycle(
|
|
105
|
+
rootDirectoryUrl,
|
|
106
|
+
{
|
|
107
|
+
watchPatterns: {
|
|
108
|
+
...devServerFiles.include,
|
|
109
|
+
[devServerMainFile]: true,
|
|
110
|
+
".jsenv/": false,
|
|
111
|
+
},
|
|
112
|
+
cooldownBetweenFileEvents,
|
|
113
|
+
keepProcessAlive: false,
|
|
114
|
+
recursive: true,
|
|
115
|
+
added: ({ relativeUrl }) => {
|
|
116
|
+
devServerFileChangeCallback({ relativeUrl, event: "added" })
|
|
117
|
+
},
|
|
118
|
+
updated: ({ relativeUrl }) => {
|
|
119
|
+
devServerFileChangeCallback({ relativeUrl, event: "modified" })
|
|
120
|
+
},
|
|
121
|
+
removed: ({ relativeUrl }) => {
|
|
122
|
+
devServerFileChangeCallback({ relativeUrl, event: "removed" })
|
|
123
|
+
},
|
|
124
124
|
},
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
operation.addAbortCallback(() => {
|
|
128
|
-
stopWatchingDevServerFiles()
|
|
129
|
-
reloadableWorker.terminate()
|
|
130
|
-
})
|
|
131
|
-
|
|
132
|
-
const worker = await reloadableWorker.load()
|
|
133
|
-
if (!keepProcessAlive) {
|
|
134
|
-
worker.unref()
|
|
135
|
-
}
|
|
136
|
-
return {
|
|
137
|
-
origin: `${protocol}://127.0.0.1:${port}`,
|
|
138
|
-
stop: () => {
|
|
125
|
+
)
|
|
126
|
+
operation.addAbortCallback(() => {
|
|
139
127
|
stopWatchingDevServerFiles()
|
|
140
128
|
reloadableWorker.terminate()
|
|
141
|
-
}
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
const worker = await reloadableWorker.load()
|
|
132
|
+
const messagePromise = new Promise((resolve) => {
|
|
133
|
+
worker.once("message", resolve)
|
|
134
|
+
})
|
|
135
|
+
await messagePromise
|
|
136
|
+
// if (!keepProcessAlive) {
|
|
137
|
+
// worker.unref()
|
|
138
|
+
// }
|
|
139
|
+
return {
|
|
140
|
+
origin: `${protocol}://127.0.0.1:${port}`,
|
|
141
|
+
stop: () => {
|
|
142
|
+
stopWatchingDevServerFiles()
|
|
143
|
+
reloadableWorker.terminate()
|
|
144
|
+
},
|
|
145
|
+
}
|
|
142
146
|
}
|
|
143
147
|
}
|
|
144
148
|
|
|
@@ -155,7 +159,10 @@ export const startDevServer = async ({
|
|
|
155
159
|
})
|
|
156
160
|
}
|
|
157
161
|
const stopWatchingClientFiles = registerDirectoryLifecycle(rootDirectoryUrl, {
|
|
158
|
-
watchPatterns:
|
|
162
|
+
watchPatterns: {
|
|
163
|
+
...clientFiles,
|
|
164
|
+
".jsenv/": false,
|
|
165
|
+
},
|
|
159
166
|
cooldownBetweenFileEvents,
|
|
160
167
|
keepProcessAlive: false,
|
|
161
168
|
recursive: true,
|
|
@@ -230,6 +237,9 @@ export const startDevServer = async ({
|
|
|
230
237
|
kitchen.pluginController.callHooks("destroy", {})
|
|
231
238
|
}
|
|
232
239
|
})
|
|
240
|
+
if (reloadableWorker && reloadableWorker.isWorker) {
|
|
241
|
+
parentPort.postMessage(server.origin)
|
|
242
|
+
}
|
|
233
243
|
return {
|
|
234
244
|
origin: server.origin,
|
|
235
245
|
stop: () => {
|
package/src/execute/run.js
CHANGED
|
@@ -25,7 +25,13 @@ export const run = async ({
|
|
|
25
25
|
|
|
26
26
|
const runOperation = Abort.startOperation()
|
|
27
27
|
runOperation.addAbortSignal(signal)
|
|
28
|
-
if (
|
|
28
|
+
if (
|
|
29
|
+
// ideally we would rather log than the timeout is ignored
|
|
30
|
+
// when keepRunning is true
|
|
31
|
+
!keepRunning &&
|
|
32
|
+
typeof allocatedMs === "number" &&
|
|
33
|
+
allocatedMs !== Infinity
|
|
34
|
+
) {
|
|
29
35
|
const timeoutAbortSource = runOperation.timeout(allocatedMs)
|
|
30
36
|
resultTransformer = composeTransformer(resultTransformer, (result) => {
|
|
31
37
|
if (
|
|
@@ -30,16 +30,15 @@ export const createReloadableWorker = (workerFileUrl, options = {}) => {
|
|
|
30
30
|
workerFilePath,
|
|
31
31
|
},
|
|
32
32
|
})
|
|
33
|
-
|
|
34
33
|
worker.once("error", (error) => {
|
|
35
34
|
console.error(error)
|
|
36
35
|
})
|
|
37
|
-
await new Promise((resolve) => {
|
|
38
|
-
worker.once("online", resolve)
|
|
39
|
-
})
|
|
40
36
|
worker.once("exit", () => {
|
|
41
37
|
worker = null
|
|
42
38
|
})
|
|
39
|
+
await new Promise((resolve) => {
|
|
40
|
+
worker.once("online", resolve)
|
|
41
|
+
})
|
|
43
42
|
return worker
|
|
44
43
|
}
|
|
45
44
|
|
|
@@ -50,6 +49,7 @@ export const createReloadableWorker = (workerFileUrl, options = {}) => {
|
|
|
50
49
|
|
|
51
50
|
return {
|
|
52
51
|
isPrimary,
|
|
52
|
+
isWorker: !isPrimary,
|
|
53
53
|
load,
|
|
54
54
|
reload,
|
|
55
55
|
terminate,
|
package/src/main.js
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
// dev
|
|
2
2
|
export { startDevServer } from "./dev/start_dev_server.js"
|
|
3
3
|
// test
|
|
4
|
-
export {
|
|
5
|
-
executeTestPlan,
|
|
6
|
-
defaultCoverageConfig,
|
|
7
|
-
} from "./test/execute_test_plan.js"
|
|
4
|
+
export { executeTestPlan } from "./test/execute_test_plan.js"
|
|
8
5
|
export {
|
|
9
6
|
chromium,
|
|
10
7
|
chromiumIsolatedTab,
|
|
@@ -18,14 +18,16 @@ export const featureCompats = {
|
|
|
18
18
|
android: "4.4",
|
|
19
19
|
samsung: "4",
|
|
20
20
|
},
|
|
21
|
+
// https://caniuse.com/?search=import.meta
|
|
21
22
|
import_meta: {
|
|
23
|
+
android: "9",
|
|
22
24
|
chrome: "64",
|
|
23
25
|
edge: "79",
|
|
24
26
|
firefox: "62",
|
|
25
|
-
safari: "11.1",
|
|
26
|
-
opera: "51",
|
|
27
27
|
ios: "12",
|
|
28
|
-
|
|
28
|
+
opera: "51",
|
|
29
|
+
safari: "11.1",
|
|
30
|
+
samsung: "9.2",
|
|
29
31
|
},
|
|
30
32
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#browser_compatibility
|
|
31
33
|
import_dynamic: {
|
package/src/plugins/plugins.js
CHANGED
|
@@ -45,6 +45,9 @@ export const getCorePlugins = ({
|
|
|
45
45
|
if (nodeEsmResolution === true) {
|
|
46
46
|
nodeEsmResolution = {}
|
|
47
47
|
}
|
|
48
|
+
if (clientAutoreload === true) {
|
|
49
|
+
clientAutoreload = {}
|
|
50
|
+
}
|
|
48
51
|
return [
|
|
49
52
|
jsenvPluginUrlAnalysis({ rootDirectoryUrl, ...urlAnalysis }),
|
|
50
53
|
jsenvPluginTranspilation(transpilation),
|
|
@@ -78,6 +81,7 @@ export const getCorePlugins = ({
|
|
|
78
81
|
...(clientAutoreload
|
|
79
82
|
? [
|
|
80
83
|
jsenvPluginAutoreload({
|
|
84
|
+
...clientAutoreload,
|
|
81
85
|
rootDirectoryUrl,
|
|
82
86
|
urlGraph,
|
|
83
87
|
scenario,
|
|
@@ -27,7 +27,8 @@ export const jsenvPluginAsJsClassicHtml = ({
|
|
|
27
27
|
html: async (urlInfo, context) => {
|
|
28
28
|
const shouldTransformScriptTypeModule =
|
|
29
29
|
!context.isSupportedOnCurrentClients("script_type_module") ||
|
|
30
|
-
!context.isSupportedOnCurrentClients("import_dynamic")
|
|
30
|
+
!context.isSupportedOnCurrentClients("import_dynamic") ||
|
|
31
|
+
!context.isSupportedOnCurrentClients("import_meta")
|
|
31
32
|
const htmlAst = parseHtmlString(urlInfo.content)
|
|
32
33
|
const preloadAsScriptNodes = []
|
|
33
34
|
const modulePreloadNodes = []
|
|
@@ -11,14 +11,6 @@ import { generateCoverageHtmlDirectory } from "./coverage/coverage_reporter_html
|
|
|
11
11
|
import { generateCoverageTextLog } from "./coverage/coverage_reporter_text_log.js"
|
|
12
12
|
import { executePlan } from "./execute_plan.js"
|
|
13
13
|
|
|
14
|
-
export const defaultCoverageConfig = {
|
|
15
|
-
"./index.js": true,
|
|
16
|
-
"./main.js": true,
|
|
17
|
-
"./src/**/*.js": true,
|
|
18
|
-
"./**/*.test.*": false, // contains .test. -> nope
|
|
19
|
-
"./**/test/": false, // inside a test folder -> nope,
|
|
20
|
-
}
|
|
21
|
-
|
|
22
14
|
/**
|
|
23
15
|
* Execute a list of files and log how it goes
|
|
24
16
|
* @param {Object} testPlanParameters
|
|
@@ -64,7 +56,12 @@ export const executeTestPlan = async ({
|
|
|
64
56
|
coverage = process.argv.includes("--cover") ||
|
|
65
57
|
process.argv.includes("--coverage"),
|
|
66
58
|
coverageTempDirectoryRelativeUrl = "./.coverage/tmp/",
|
|
67
|
-
coverageConfig =
|
|
59
|
+
coverageConfig = {
|
|
60
|
+
"./src/**/*.js": true,
|
|
61
|
+
"./**/*.test.*": false, // contains .test. -> no
|
|
62
|
+
"./**/test/": false, // inside a test directory -> no
|
|
63
|
+
"./**/tests/": false, // inside a tests directory -> no
|
|
64
|
+
},
|
|
68
65
|
coverageIncludeMissing = true,
|
|
69
66
|
coverageAndExecutionAllowed = false,
|
|
70
67
|
coverageForceIstanbul = false,
|