@jsenv/core 38.2.2 → 38.2.4

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 CHANGED
@@ -1,9 +1,43 @@
1
1
  # @jsenv/core [![npm package](https://img.shields.io/npm/v/@jsenv/core.svg?logo=npm&label=package)](https://www.npmjs.com/package/@jsenv/core)
2
2
 
3
- Jsenv is a tool to develop test and build projects using JavaScript.
4
- Jsenv is simple, easy to understand and well documented.
3
+ Jsenv is a tool to develop test and build projects using JavaScript. Jsenv is simple, easy to understand and well [documented](<https://github.com/jsenv/core/wiki/A)-directory-structure>).
5
4
 
6
- [Documentation](<https://github.com/jsenv/core/wiki/A)-Introduction>)
5
+ Jsenv cares a lot about the developper experience, especially when it comes to tests.
6
+
7
+ The pillars of jsenv are:
8
+
9
+ 1. A dev server serving source files with autoreload
10
+ 2. A build generating an optimized version of source files into a directory
11
+ 3. A build server serving build files
12
+ 4. A test runner executing test files in web browser(s)
13
+
14
+ # The best parts
15
+
16
+ ## Reduce cognitive load inside test files
17
+
18
+ When coding, we spend most of our time working on source files. At some point we switch from source files to test files. Suddenly things are different:
19
+
20
+ - code does not execute as it would in source files
21
+ - some tools are used differently in test files, some cannot be used at all
22
+ - you are forced to code in a certain way that is completely different from the one in source files
23
+
24
+ This huge gap between source files and test files creates a context switching costing a lot of cognitive energy.
25
+ Jsenv makes a special effort to [provide a solution](<https://github.com/jsenv/core/wiki/D)-Test>) where switching from source files to test files is easy.
26
+
27
+ ## Others
28
+
29
+ - A [large browser support during dev](<https://github.com/jsenv/core/wiki/B)-Dev#21-browser-support>). Because some people might be happy to use an other browser than the latest chrome during dev. Moreover it is useful to reproduce bug specific to certain browsers.
30
+ - A [large browser support after build](<https://github.com/jsenv/core/wiki/C)-Build#211-maximal-browser-support>). Because some product still needs to support old versions of Firefox, Chrome and Safari.
31
+ - A [single set of files during build](<https://github.com/jsenv/core/wiki/C)-Build#212-same-build-for-all-browsers>). Because a single one is simpler to properly support in every aspects.
32
+ - Versioning during build is robust and <a href="https://bundlers.tooling.report/hashing/avoid-cascade/" target="_blank">avoids cascading hash changes</a><sup>↗</sup>
33
+ - Ability to [execute tests in multiple browsers](<https://github.com/jsenv/core/wiki/D)-Test#32-executing-on-more-browsers>): Chrome, Safari, Firefox
34
+ - An advanced support of top level await, allowing to use it everywhere
35
+ - An advanced support of web workers including worker type module
36
+ - Unlock js module features on a regular `<script>` when needed. If you need the behaviour of `<script>` which is to block other `<script>` tag in the page, you'll be happy to still have the power of js modules, like imports, at your disposal.
37
+
38
+ # Demos
39
+
40
+ [H) Demos](<https://github.com/jsenv/core/wiki/H)-Demos>).
7
41
 
8
42
  <!-- # Installation
9
43
 
@@ -11,5 +45,5 @@ Jsenv is simple, easy to understand and well documented.
11
45
  npm install --save-dev @jsenv/core
12
46
  ```
13
47
 
14
- _@jsenv/core_ is tested on Mac, Windows, Linux with Node.js 18.
48
+ _@jsenv/core_ is tested on Mac, Windows, Linux with Node.js 20.
15
49
  Other operating systems and Node.js versions are not tested. -->
@@ -2509,7 +2509,9 @@ const createWatcher = (sourcePath, options) => {
2509
2509
  if (e.code === "ENOENT") {
2510
2510
  return;
2511
2511
  }
2512
- console.error(`error while fixing windows eperm: ${e.stack}`);
2512
+ console.error(
2513
+ `error while trying to get rid of windows EPERM: ${e.stack}`,
2514
+ );
2513
2515
  throw error;
2514
2516
  }
2515
2517
  } else {
@@ -2543,9 +2545,7 @@ callback: ${callback}`);
2543
2545
  return { registerCleanupCallback, cleanup };
2544
2546
  };
2545
2547
 
2546
- const isLinux = process.platform === "linux";
2547
- // linux does not support recursive option
2548
- const fsWatchSupportsRecursive = !isLinux;
2548
+ const fsWatchSupportsRecursive = process.platform !== "linux";
2549
2549
 
2550
2550
  const registerDirectoryLifecycle = (
2551
2551
  source,
@@ -2628,8 +2628,8 @@ const registerDirectoryLifecycle = (
2628
2628
  try {
2629
2629
  const relativeUrl = urlToRelativeUrl(url, source);
2630
2630
  const previousInfo = infoMap.get(relativeUrl);
2631
- const stats = statSync(new URL(url));
2632
- const type = statsToType(stats);
2631
+ const stat = statSync(new URL(url));
2632
+ const type = statsToType(stat);
2633
2633
  const patternValue = previousInfo
2634
2634
  ? previousInfo.patternValue
2635
2635
  : getWatchPatternValue({ url, type });
@@ -2638,13 +2638,15 @@ const registerDirectoryLifecycle = (
2638
2638
  url,
2639
2639
  relativeUrl,
2640
2640
  type,
2641
- atimeMs: stats.atimeMs,
2642
- mtimeMs: stats.mtimeMs,
2641
+ stat,
2643
2642
  patternValue,
2644
2643
  };
2645
2644
  } catch (e) {
2646
2645
  if (e.code === "ENOENT") {
2647
- return null;
2646
+ return {
2647
+ type: null,
2648
+ stat: null,
2649
+ };
2648
2650
  }
2649
2651
  throw e;
2650
2652
  }
@@ -2717,7 +2719,7 @@ const registerDirectoryLifecycle = (
2717
2719
  const handleChange = (relativeUrl) => {
2718
2720
  const entryUrl = new URL(relativeUrl, sourceUrl).href;
2719
2721
  const entryInfo = readEntryInfo(entryUrl);
2720
- if (!entryInfo) {
2722
+ if (entryInfo.type === null) {
2721
2723
  const previousEntryInfo = infoMap.get(relativeUrl);
2722
2724
  if (!previousEntryInfo) {
2723
2725
  // on MacOS it's possible to receive a "rename" event for
@@ -2777,7 +2779,7 @@ const registerDirectoryLifecycle = (
2777
2779
  readdirSync(new URL(directoryUrl)).forEach((entryName) => {
2778
2780
  const childEntryUrl = new URL(entryName, directoryUrl).href;
2779
2781
  const childEntryInfo = readEntryInfo(childEntryUrl);
2780
- if (childEntryInfo && childEntryInfo.patternValue) {
2782
+ if (childEntryInfo.type !== null && childEntryInfo.patternValue) {
2781
2783
  handleEntryFound(childEntryInfo, { notify });
2782
2784
  }
2783
2785
  });
@@ -2806,7 +2808,7 @@ const registerDirectoryLifecycle = (
2806
2808
  relativeUrl: entryInfo.relativeUrl,
2807
2809
  type: entryInfo.type,
2808
2810
  patternValue: entryInfo.patternValue,
2809
- mtime: entryInfo.mtimeMs,
2811
+ mtime: entryInfo.stat.mtimeMs,
2810
2812
  });
2811
2813
  }
2812
2814
  };
@@ -2817,19 +2819,19 @@ const registerDirectoryLifecycle = (
2817
2819
  relativeUrl: entryInfo.relativeUrl,
2818
2820
  type: entryInfo.type,
2819
2821
  patternValue: entryInfo.patternValue,
2820
- mtime: entryInfo.mtimeMs,
2822
+ mtime: entryInfo.stat.mtimeMs,
2821
2823
  });
2822
2824
  }
2823
2825
  };
2824
2826
  const handleEntryUpdated = (entryInfo) => {
2825
2827
  infoMap.set(entryInfo.relativeUrl, entryInfo);
2826
- if (updated && entryInfo.patternValue) {
2828
+ if (updated && entryInfo.patternValue && shouldCallUpdated(entryInfo)) {
2827
2829
  updated({
2828
2830
  relativeUrl: entryInfo.relativeUrl,
2829
2831
  type: entryInfo.type,
2830
2832
  patternValue: entryInfo.patternValue,
2831
- mtime: entryInfo.mtimeMs,
2832
- previousMtime: entryInfo.previousInfo.mtimeMs,
2833
+ mtime: entryInfo.stat.mtimeMs,
2834
+ previousMtime: entryInfo.previousInfo.stat.mtimeMs,
2833
2835
  });
2834
2836
  }
2835
2837
  };
@@ -2837,7 +2839,7 @@ const registerDirectoryLifecycle = (
2837
2839
  readdirSync(new URL(sourceUrl)).forEach((entry) => {
2838
2840
  const entryUrl = new URL(entry, sourceUrl).href;
2839
2841
  const entryInfo = readEntryInfo(entryUrl);
2840
- if (entryInfo && entryInfo.patternValue) {
2842
+ if (entryInfo.type !== null && entryInfo.patternValue) {
2841
2843
  handleEntryFound(entryInfo, {
2842
2844
  notify: notifyExistent,
2843
2845
  });
@@ -2871,6 +2873,20 @@ ${relativeUrls.join("\n")}`,
2871
2873
  return tracker.cleanup;
2872
2874
  };
2873
2875
 
2876
+ const shouldCallUpdated = (entryInfo) => {
2877
+ const { stat, previousInfo } = entryInfo;
2878
+ if (!stat.atimeMs) {
2879
+ return true;
2880
+ }
2881
+ if (stat.atimeMs < stat.mtimeMs) {
2882
+ return true;
2883
+ }
2884
+ if (stat.mtimeMs > previousInfo.stat.mtimeMs) {
2885
+ return true;
2886
+ }
2887
+ return false;
2888
+ };
2889
+
2874
2890
  const undefinedOrFunction = (value) => {
2875
2891
  return typeof value === "undefined" || typeof value === "function";
2876
2892
  };
@@ -13235,6 +13251,7 @@ const createUrlInfoTransformer = ({
13235
13251
  generatedUrlObject.searchParams.delete("as_json_module");
13236
13252
  generatedUrlObject.searchParams.delete("as_text_module");
13237
13253
  generatedUrlObject.searchParams.delete("dynamic_import");
13254
+ generatedUrlObject.searchParams.delete("cjs_as_js_module");
13238
13255
  const urlForSourcemap = generatedUrlObject.href;
13239
13256
  urlInfo.sourcemapGeneratedUrl = generateSourcemapFileUrl(urlForSourcemap);
13240
13257
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/core",
3
- "version": "38.2.2",
3
+ "version": "38.2.4",
4
4
  "description": "Tool to develop, test and build js projects",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -13,7 +13,7 @@
13
13
  "url": "https://github.com/jsenv/core"
14
14
  },
15
15
  "engines": {
16
- "node": ">=18.5.0"
16
+ "node": ">=20.8.0"
17
17
  },
18
18
  "publishConfig": {
19
19
  "access": "public"
@@ -62,7 +62,7 @@
62
62
  "@financial-times/polyfill-useragent-normaliser": "1.10.2",
63
63
  "@jsenv/abort": "4.2.4",
64
64
  "@jsenv/ast": "5.1.4",
65
- "@jsenv/filesystem": "4.2.6",
65
+ "@jsenv/filesystem": "4.3.1",
66
66
  "@jsenv/importmap": "1.2.1",
67
67
  "@jsenv/integrity": "0.0.1",
68
68
  "@jsenv/log": "3.4.0",
@@ -149,6 +149,7 @@ export const createUrlInfoTransformer = ({
149
149
  generatedUrlObject.searchParams.delete("as_json_module");
150
150
  generatedUrlObject.searchParams.delete("as_text_module");
151
151
  generatedUrlObject.searchParams.delete("dynamic_import");
152
+ generatedUrlObject.searchParams.delete("cjs_as_js_module");
152
153
  const urlForSourcemap = generatedUrlObject.href;
153
154
  urlInfo.sourcemapGeneratedUrl = generateSourcemapFileUrl(urlForSourcemap);
154
155