@jsenv/core 40.2.1 → 40.3.2

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.
@@ -1,7 +1,7 @@
1
1
  import { parseHtml, injectHtmlNodeAsEarlyAsPossible, createHtmlNode, stringifyHtmlAst, applyBabelPlugins, generateUrlForInlineContent, parseJsWithAcorn, visitHtmlNodes, analyzeScriptNode, getHtmlNodeText, getHtmlNodeAttribute, getHtmlNodePosition, getUrlForContentInsideHtml, setHtmlNodeAttributes, setHtmlNodeText, parseCssUrls, getHtmlNodeAttributePosition, parseSrcSet, removeHtmlNodeText, parseJsUrls, getUrlForContentInsideJs, analyzeLinkNode, injectJsenvScript, findHtmlNode, removeHtmlNode, insertHtmlNodeAfter } from "@jsenv/ast";
2
2
  import { memoryUsage } from "node:process";
3
3
  import { readFileSync, existsSync, readdirSync, lstatSync, realpathSync } from "node:fs";
4
- import { lookupPackageDirectory$1 as lookupPackageDirectory, registerDirectoryLifecycle$1 as registerDirectoryLifecycle, urlToRelativeUrl$1 as urlToRelativeUrl, createDetailedMessage$1 as createDetailedMessage, stringifyUrlSite$1 as stringifyUrlSite, generateContentFrame$1 as generateContentFrame, validateResponseIntegrity$1 as validateResponseIntegrity, urlIsInsideOf$1 as urlIsInsideOf, ensureWindowsDriveLetter$1 as ensureWindowsDriveLetter, setUrlFilename$1 as setUrlFilename, moveUrl$1 as moveUrl, getCallerPosition$1 as getCallerPosition, urlToBasename$1 as urlToBasename, urlToExtension$1 as urlToExtension, asSpecifierWithoutSearch$1 as asSpecifierWithoutSearch, asUrlWithoutSearch$1 as asUrlWithoutSearch, injectQueryParamsIntoSpecifier$1 as injectQueryParamsIntoSpecifier, bufferToEtag$1 as bufferToEtag, isFileSystemPath$1 as isFileSystemPath, urlToPathname$1 as urlToPathname, setUrlBasename$1 as setUrlBasename, urlToFileSystemPath$1 as urlToFileSystemPath, writeFileSync$1 as writeFileSync, createLogger$1 as createLogger, URL_META$1 as URL_META, applyNodeEsmResolution$1 as applyNodeEsmResolution, RUNTIME_COMPAT$1 as RUNTIME_COMPAT, normalizeUrl$1 as normalizeUrl, ANSI$1 as ANSI, CONTENT_TYPE$1 as CONTENT_TYPE, urlToFilename$1 as urlToFilename, DATA_URL$1 as DATA_URL, normalizeImportMap$1 as normalizeImportMap, composeTwoImportMaps$1 as composeTwoImportMaps, resolveImport$1 as resolveImport, JS_QUOTES$1 as JS_QUOTES, defaultLookupPackageScope$1 as defaultLookupPackageScope, defaultReadPackageJson$1 as defaultReadPackageJson, readCustomConditionsFromProcessArgs$1 as readCustomConditionsFromProcessArgs, readEntryStatSync$1 as readEntryStatSync, ensurePathnameTrailingSlash$1 as ensurePathnameTrailingSlash, compareFileUrls$1 as compareFileUrls, applyFileSystemMagicResolution$1 as applyFileSystemMagicResolution, getExtensionsToTry$1 as getExtensionsToTry, setUrlExtension$1 as setUrlExtension, jsenvPluginTranspilation$1 as jsenvPluginTranspilation, renderDetails, humanizeDuration, humanizeFileSize, renderTable, renderBigSection, distributePercentages, humanizeMemory, comparePathnames, UNICODE, escapeRegexpSpecialChars, injectQueryParamIntoSpecifierWithoutEncoding, renderUrlOrRelativeUrlFilename, assertAndNormalizeDirectoryUrl$1 as assertAndNormalizeDirectoryUrl, Abort, raceProcessTeardownEvents, startMonitoringCpuUsage, startMonitoringMemoryUsage, readPackageAtOrNull, inferRuntimeCompatFromClosestPackage, browserDefaultRuntimeCompat, nodeDefaultRuntimeCompat, clearDirectorySync, createTaskLog$1 as createTaskLog, jsenvPluginBundling, jsenvPluginMinification, ensureEmptyDirectory, jsenvPluginJsModuleFallback, createDynamicLog } from "../jsenv_core_packages.js";
4
+ import { lookupPackageDirectory$1 as lookupPackageDirectory, registerDirectoryLifecycle$1 as registerDirectoryLifecycle, urlToRelativeUrl$1 as urlToRelativeUrl, createDetailedMessage$1 as createDetailedMessage, stringifyUrlSite$1 as stringifyUrlSite, generateContentFrame$1 as generateContentFrame, validateResponseIntegrity$1 as validateResponseIntegrity, urlIsInsideOf$1 as urlIsInsideOf, ensureWindowsDriveLetter$1 as ensureWindowsDriveLetter, setUrlFilename$1 as setUrlFilename, moveUrl$1 as moveUrl, getCallerPosition$1 as getCallerPosition, urlToBasename$1 as urlToBasename, urlToExtension$1 as urlToExtension, asSpecifierWithoutSearch$1 as asSpecifierWithoutSearch, asUrlWithoutSearch$1 as asUrlWithoutSearch, injectQueryParamsIntoSpecifier$1 as injectQueryParamsIntoSpecifier, bufferToEtag$1 as bufferToEtag, isFileSystemPath$1 as isFileSystemPath, urlToPathname$1 as urlToPathname, setUrlBasename$1 as setUrlBasename, urlToFileSystemPath$1 as urlToFileSystemPath, writeFileSync$1 as writeFileSync, createLogger$1 as createLogger, URL_META$1 as URL_META, applyNodeEsmResolution$1 as applyNodeEsmResolution, RUNTIME_COMPAT$1 as RUNTIME_COMPAT, normalizeUrl$1 as normalizeUrl, ANSI$1 as ANSI, CONTENT_TYPE$1 as CONTENT_TYPE, urlToFilename$1 as urlToFilename, DATA_URL$1 as DATA_URL, errorToHTML$1 as errorToHTML, normalizeImportMap$1 as normalizeImportMap, composeTwoImportMaps$1 as composeTwoImportMaps, resolveImport$1 as resolveImport, JS_QUOTES$1 as JS_QUOTES, defaultLookupPackageScope$1 as defaultLookupPackageScope, defaultReadPackageJson$1 as defaultReadPackageJson, readCustomConditionsFromProcessArgs$1 as readCustomConditionsFromProcessArgs, readEntryStatSync$1 as readEntryStatSync, ensurePathnameTrailingSlash$1 as ensurePathnameTrailingSlash, compareFileUrls$1 as compareFileUrls, applyFileSystemMagicResolution$1 as applyFileSystemMagicResolution, getExtensionsToTry$1 as getExtensionsToTry, setUrlExtension$1 as setUrlExtension, isSpecifierForNodeBuiltin$1 as isSpecifierForNodeBuiltin, updateJsonFileSync$1 as updateJsonFileSync, jsenvPluginTranspilation$1 as jsenvPluginTranspilation, renderDetails, humanizeDuration, humanizeFileSize, renderTable, renderBigSection, distributePercentages, humanizeMemory, comparePathnames, UNICODE, escapeRegexpSpecialChars, injectQueryParamIntoSpecifierWithoutEncoding, renderUrlOrRelativeUrlFilename, assertAndNormalizeDirectoryUrl$1 as assertAndNormalizeDirectoryUrl, Abort, raceProcessTeardownEvents, startMonitoringCpuUsage, startMonitoringMemoryUsage, createLookupPackageDirectory, readPackageAtOrNull$1 as readPackageAtOrNull, inferRuntimeCompatFromClosestPackage, browserDefaultRuntimeCompat, nodeDefaultRuntimeCompat, clearDirectorySync, createTaskLog$1 as createTaskLog, jsenvPluginBundling, jsenvPluginMinification, ensureEmptyDirectory, jsenvPluginJsModuleFallback, createDynamicLog } from "../jsenv_core_packages.js";
5
5
  import { pathToFileURL } from "node:url";
6
6
  import { generateSourcemapFileUrl, createMagicSource, composeTwoSourcemaps, generateSourcemapDataUrl, SOURCEMAP } from "@jsenv/sourcemap";
7
7
  import { performance } from "node:perf_hooks";
@@ -699,7 +699,14 @@ const createDependencies = (ownerUrlInfo) => {
699
699
  ...props,
700
700
  });
701
701
  const reference = originalReference.resolve();
702
- reference.finalize();
702
+ if (reference.urlInfo) {
703
+ return reference;
704
+ }
705
+ const kitchen = ownerUrlInfo.kitchen;
706
+ const urlInfo = kitchen.graph.reuseOrCreateUrlInfo(reference);
707
+ reference.urlInfo = urlInfo;
708
+ addDependency(reference);
709
+ ownerUrlInfo.context.finalizeReference(reference);
703
710
  return reference;
704
711
  };
705
712
 
@@ -1015,6 +1022,7 @@ const createReference = ({
1015
1022
  implicitReferenceSet: new Set(),
1016
1023
  isWeak,
1017
1024
  hasVersioningEffect,
1025
+ urlInfoEffectSet: new Set(),
1018
1026
  version,
1019
1027
  injected,
1020
1028
  timing: {},
@@ -1048,17 +1056,6 @@ const createReference = ({
1048
1056
  return referenceRedirected;
1049
1057
  };
1050
1058
 
1051
- reference.finalize = () => {
1052
- if (reference.urlInfo) {
1053
- return;
1054
- }
1055
- const kitchen = ownerUrlInfo.kitchen;
1056
- const urlInfo = kitchen.graph.reuseOrCreateUrlInfo(reference);
1057
- reference.urlInfo = urlInfo;
1058
- addDependency(reference);
1059
- ownerUrlInfo.context.finalizeReference(reference);
1060
- };
1061
-
1062
1059
  // "formatReference" can be async BUT this is an exception
1063
1060
  // for most cases it will be sync. We want to favor the sync signature to keep things simpler
1064
1061
  // The only case where it needs to be async is when
@@ -1421,6 +1418,10 @@ const applyReferenceEffectsOnUrlInfo = (reference) => {
1421
1418
  referencedUrlInfo.entryUrlInfo = reference.isEntryPoint
1422
1419
  ? referencedUrlInfo
1423
1420
  : reference.ownerUrlInfo.entryUrlInfo;
1421
+
1422
+ for (const urlInfoEffect of reference.urlInfoEffectSet) {
1423
+ urlInfoEffect(referencedUrlInfo);
1424
+ }
1424
1425
  };
1425
1426
 
1426
1427
  const GRAPH_VISITOR = {};
@@ -1832,6 +1833,7 @@ const createUrlInfo = (url, context) => {
1832
1833
  contentAst: undefined,
1833
1834
  contentLength: undefined,
1834
1835
  contentFinalized: false,
1836
+ contentSideEffects: [],
1835
1837
 
1836
1838
  sourcemap: null,
1837
1839
  sourcemapIsWrong: false,
@@ -1861,6 +1863,26 @@ const createUrlInfo = (url, context) => {
1861
1863
  urlInfo.pathname = new URL(url).pathname;
1862
1864
  urlInfo.searchParams = new URL(url).searchParams;
1863
1865
 
1866
+ Object.defineProperty(urlInfo, "packageDirectoryUrl", {
1867
+ enumerable: true,
1868
+ configurable: true,
1869
+ get: () => context.packageDirectory.find(url),
1870
+ });
1871
+ Object.defineProperty(urlInfo, "packageJSON", {
1872
+ enumerable: true,
1873
+ configurable: true,
1874
+ get: () => {
1875
+ const packageDirectoryUrl = context.packageDirectory.find(url);
1876
+ return packageDirectoryUrl
1877
+ ? context.packageDirectory.read(packageDirectoryUrl)
1878
+ : null;
1879
+ },
1880
+ });
1881
+ Object.defineProperty(urlInfo, "packageName", {
1882
+ enumerable: true,
1883
+ configurable: true,
1884
+ get: () => urlInfo.packageJSON?.name,
1885
+ });
1864
1886
  urlInfo.dependencies = createDependencies(urlInfo);
1865
1887
  urlInfo.isUsed = () => {
1866
1888
  if (urlInfo.isRoot) {
@@ -2653,6 +2675,7 @@ const createKitchen = ({
2653
2675
  sourcemapsSourcesContent,
2654
2676
  outDirectoryUrl,
2655
2677
  initialContext = {},
2678
+ packageDirectory,
2656
2679
  }) => {
2657
2680
  const logger = createLogger({ logLevel });
2658
2681
 
@@ -2667,6 +2690,7 @@ const createKitchen = ({
2667
2690
  logger,
2668
2691
  rootDirectoryUrl,
2669
2692
  mainFilePath,
2693
+ packageDirectory,
2670
2694
  dev,
2671
2695
  build,
2672
2696
  runtimeCompat,
@@ -2683,6 +2707,8 @@ const createKitchen = ({
2683
2707
  conditions: packageConditions,
2684
2708
  parentUrl: importer,
2685
2709
  specifier,
2710
+ lookupPackageScope: packageDirectory.find,
2711
+ readPackageJson: packageDirectory.read,
2686
2712
  });
2687
2713
  return { url, packageDirectoryUrl, packageJson };
2688
2714
  },
@@ -2703,6 +2729,9 @@ const createKitchen = ({
2703
2729
  rootDirectoryUrl,
2704
2730
  kitchen,
2705
2731
  });
2732
+ graph.urlInfoCreatedEventEmitter.on((urlInfoCreated) => {
2733
+ pluginController.callHooks("urlInfoCreated", urlInfoCreated, () => {});
2734
+ });
2706
2735
  kitchen.graph = graph;
2707
2736
 
2708
2737
  const urlInfoTransformer = createUrlInfoTransformer({
@@ -2955,6 +2984,7 @@ ${ANSI.color(normalizedReturnValue, ANSI.YELLOW)}
2955
2984
  isEntryPoint,
2956
2985
  isDynamicEntryPoint,
2957
2986
  filenameHint,
2987
+ contentSideEffects,
2958
2988
  } = fetchUrlContentReturnValue;
2959
2989
  if (content === undefined) {
2960
2990
  content = body;
@@ -2987,6 +3017,9 @@ ${ANSI.color(normalizedReturnValue, ANSI.YELLOW)}
2987
3017
  if (typeof isDynamicEntryPoint === "boolean") {
2988
3018
  urlInfo.isDynamicEntryPoint = isDynamicEntryPoint;
2989
3019
  }
3020
+ if (contentSideEffects) {
3021
+ urlInfo.contentSideEffects = contentSideEffects;
3022
+ }
2990
3023
  assertFetchedContentCompliance({
2991
3024
  urlInfo,
2992
3025
  content,
@@ -3738,19 +3771,11 @@ const generateHtmlForSyntaxError = (
3738
3771
  urlWithLineAndColumn,
3739
3772
  )}')`,
3740
3773
  errorLinkText: `${htmlRelativeUrl}:${line}:${column}`,
3741
- syntaxError: escapeHtml(htmlErrorContentFrame),
3774
+ syntaxErrorHTML: errorToHTML(htmlErrorContentFrame),
3742
3775
  };
3743
3776
  const html = replacePlaceholders$1(htmlForSyntaxError, replacers);
3744
3777
  return html;
3745
3778
  };
3746
- const escapeHtml = (string) => {
3747
- return string
3748
- .replace(/&/g, "&")
3749
- .replace(/</g, "&lt;")
3750
- .replace(/>/g, "&gt;")
3751
- .replace(/"/g, "&quot;")
3752
- .replace(/'/g, "&#039;");
3753
- };
3754
3779
  const replacePlaceholders$1 = (html, replacers) => {
3755
3780
  return html.replace(/\$\{(\w+)\}/g, (match, name) => {
3756
3781
  const replacer = replacers[name];
@@ -4052,15 +4077,18 @@ const HOOK_NAMES = [
4052
4077
  "redirectReference",
4053
4078
  "transformReferenceSearchParams",
4054
4079
  "formatReference",
4080
+ "urlInfoCreated",
4055
4081
  "fetchUrlContent",
4056
4082
  "transformUrlContent",
4057
4083
  "finalizeUrlContent",
4058
4084
  "bundle", // is called only during build
4059
- "optimizeUrlContent", // is called only during build
4085
+ "optimizeBuildUrlContent", // is called only during build
4060
4086
  "cooked",
4061
4087
  "augmentResponse", // is called only during dev/tests
4062
4088
  "destroy",
4063
4089
  "effect",
4090
+ "refineBuildUrlContent", // called only during build
4091
+ "refineBuild", // called only during build
4064
4092
  ];
4065
4093
 
4066
4094
  const testAppliesDuring = (plugin, kitchen) => {
@@ -4171,7 +4199,7 @@ const returnValueAssertions = [
4171
4199
  "fetchUrlContent",
4172
4200
  "transformUrlContent",
4173
4201
  "finalizeUrlContent",
4174
- "optimizeUrlContent",
4202
+ "optimizeBuildUrlContent",
4175
4203
  ],
4176
4204
  assertion: (valueReturned, urlInfo, { hook }) => {
4177
4205
  if (typeof valueReturned === "string" || Buffer.isBuffer(valueReturned)) {
@@ -6035,6 +6063,7 @@ const jsenvPluginDirectoryListing = ({
6035
6063
  urlMocks = false,
6036
6064
  autoreload = true,
6037
6065
  directoryContentMagicName,
6066
+ packageDirectory,
6038
6067
  rootDirectoryUrl,
6039
6068
  mainFilePath,
6040
6069
  sourceFilesConfig,
@@ -6120,6 +6149,7 @@ const jsenvPluginDirectoryListing = ({
6120
6149
  directoryContentMagicName,
6121
6150
  rootDirectoryUrl,
6122
6151
  mainFilePath,
6152
+ packageDirectory,
6123
6153
  enoent,
6124
6154
  }),
6125
6155
  },
@@ -6206,6 +6236,7 @@ const generateDirectoryListingInjection = (
6206
6236
  {
6207
6237
  rootDirectoryUrl,
6208
6238
  mainFilePath,
6239
+ packageDirectory,
6209
6240
  request,
6210
6241
  urlMocks,
6211
6242
  directoryContentMagicName,
@@ -6224,14 +6255,13 @@ const generateDirectoryListingInjection = (
6224
6255
  firstExistingDirectoryUrl,
6225
6256
  });
6226
6257
  package_workspaces: {
6227
- const packageDirectoryUrl = lookupPackageDirectory(serverRootDirectoryUrl);
6228
- if (!packageDirectoryUrl) {
6258
+ if (!packageDirectory.url) {
6229
6259
  break package_workspaces;
6230
6260
  }
6231
- if (String(packageDirectoryUrl) === String(serverRootDirectoryUrl)) {
6261
+ if (String(packageDirectory.url) === String(serverRootDirectoryUrl)) {
6232
6262
  break package_workspaces;
6233
6263
  }
6234
- rootDirectoryUrl = packageDirectoryUrl;
6264
+ rootDirectoryUrl = packageDirectory.url;
6235
6265
  // if (String(firstExistingDirectoryUrl) === String(serverRootDirectoryUrl)) {
6236
6266
  // let packageContent;
6237
6267
  // try {
@@ -6562,6 +6592,7 @@ const jsenvPluginProtocolFile = ({
6562
6592
  directoryListing,
6563
6593
  rootDirectoryUrl,
6564
6594
  mainFilePath,
6595
+ packageDirectory,
6565
6596
  sourceFilesConfig,
6566
6597
  }) => {
6567
6598
  return [
@@ -6625,6 +6656,7 @@ const jsenvPluginProtocolFile = ({
6625
6656
  directoryContentMagicName,
6626
6657
  rootDirectoryUrl,
6627
6658
  mainFilePath,
6659
+ packageDirectory,
6628
6660
  sourceFilesConfig,
6629
6661
  }),
6630
6662
  ]
@@ -8170,6 +8202,230 @@ const jsenvPluginAutoreloadOnServerRestart = () => {
8170
8202
  };
8171
8203
  };
8172
8204
 
8205
+ /**
8206
+ * Lorsqu'on bundle un package ayant pas le field sideEffects
8207
+ * alors on fini potentiellement par dire
8208
+ * sideEffect: false
8209
+ * sur le package racine alors qu'on en sait rien
8210
+ * on pourrait mettre un package.json dans dist dans ce cas
8211
+ * qui ne déclare pas le field side effect afin
8212
+ * d'override le package.json du project qui lui dit qu'il ny en a pas
8213
+ *
8214
+ * On part du principe pour le moment que c'est la respo du package racine de déclarer cela
8215
+ *
8216
+ */
8217
+
8218
+
8219
+ const jsenvPluginPackageSideEffects = ({ packageDirectory }) => {
8220
+ if (!packageDirectory.url) {
8221
+ return [];
8222
+ }
8223
+ const packageJson = packageDirectory.read(packageDirectory.url);
8224
+ if (!packageJson) {
8225
+ return [];
8226
+ }
8227
+ const { sideEffects } = packageJson;
8228
+ if (sideEffects !== false && !Array.isArray(sideEffects)) {
8229
+ return [];
8230
+ }
8231
+
8232
+ const normalizeSideEffectFileUrl = (url) => {
8233
+ const urlRelativeToPackage = urlToRelativeUrl(url, packageDirectory.url);
8234
+ return urlRelativeToPackage[0] === "."
8235
+ ? urlRelativeToPackage
8236
+ : `./${urlRelativeToPackage}`;
8237
+ };
8238
+
8239
+ const updatePackageSideEffects = (sideEffectBuildFileUrls) => {
8240
+ const packageJsonFileUrl = new URL("./package.json", packageDirectory.url)
8241
+ .href;
8242
+ const sideEffectRelativeUrlArray = [];
8243
+ for (const sideEffectBuildUrl of sideEffectBuildFileUrls) {
8244
+ sideEffectRelativeUrlArray.push(
8245
+ normalizeSideEffectFileUrl(sideEffectBuildUrl),
8246
+ );
8247
+ }
8248
+ updateJsonFileSync(packageJsonFileUrl, {
8249
+ sideEffects: sideEffectRelativeUrlArray,
8250
+ });
8251
+ };
8252
+
8253
+ const sideEffectBuildFileUrls = [];
8254
+
8255
+ const packageSideEffectsCacheMap = new Map();
8256
+ const readSideEffectInfoFromClosestPackage = (urlInfo) => {
8257
+ const closestPackageDirectoryUrl = urlInfo.packageDirectoryUrl;
8258
+ const closestPackageJSON = urlInfo.packageJSON;
8259
+ if (!closestPackageJSON) {
8260
+ return undefined;
8261
+ }
8262
+ const fromCache = packageSideEffectsCacheMap.get(
8263
+ closestPackageDirectoryUrl,
8264
+ );
8265
+ if (fromCache) {
8266
+ return fromCache.value;
8267
+ }
8268
+ try {
8269
+ return storePackageSideEffect(
8270
+ closestPackageDirectoryUrl,
8271
+ closestPackageJSON,
8272
+ );
8273
+ } catch {
8274
+ return storePackageSideEffect(closestPackageDirectoryUrl, null);
8275
+ }
8276
+ };
8277
+ const storePackageSideEffect = (packageDirectoryUrl, packageJSON) => {
8278
+ if (!packageJSON) {
8279
+ packageSideEffectsCacheMap.set(packageDirectoryUrl, { value: undefined });
8280
+ return undefined;
8281
+ }
8282
+ const value = packageJSON.sideEffects;
8283
+ if (Array.isArray(value)) {
8284
+ const noSideEffect = {
8285
+ has: false,
8286
+ reason: "not listed in package.json side effects",
8287
+ packageDirectoryUrl,
8288
+ };
8289
+ const hasSideEffect = {
8290
+ has: true,
8291
+ reason: "listed in package.json side effects",
8292
+ packageDirectoryUrl,
8293
+ };
8294
+ const sideEffectPatterns = {};
8295
+ for (const v of value) {
8296
+ sideEffectPatterns[v] = v;
8297
+ }
8298
+ const associations = URL_META.resolveAssociations(
8299
+ { sideEffects: sideEffectPatterns },
8300
+ packageDirectoryUrl,
8301
+ );
8302
+ const getSideEffectInfo = (urlInfo) => {
8303
+ const meta = URL_META.applyAssociations({
8304
+ url: urlInfo.url,
8305
+ associations,
8306
+ });
8307
+ const sideEffectKey = meta.sideEffects;
8308
+ if (sideEffectKey) {
8309
+ return {
8310
+ ...hasSideEffect,
8311
+ reason: `"${sideEffectKey}" listed in package.json side effects`,
8312
+ };
8313
+ }
8314
+ return noSideEffect;
8315
+ };
8316
+ packageSideEffectsCacheMap.set(packageDirectoryUrl, {
8317
+ value: getSideEffectInfo,
8318
+ });
8319
+ return getSideEffectInfo;
8320
+ }
8321
+ if (value === false) {
8322
+ const noSideEffect = {
8323
+ has: false,
8324
+ reason: "package.json side effects is false",
8325
+ packageDirectoryUrl,
8326
+ };
8327
+ packageSideEffectsCacheMap.set(packageDirectoryUrl, {
8328
+ value: noSideEffect,
8329
+ });
8330
+ return noSideEffect;
8331
+ }
8332
+ const hasSideEffect = {
8333
+ has: true,
8334
+ reason: "package.json side effects is true",
8335
+ packageDirectoryUrl,
8336
+ };
8337
+ packageSideEffectsCacheMap.set(packageDirectoryUrl, {
8338
+ value: hasSideEffect,
8339
+ });
8340
+ return hasSideEffect;
8341
+ };
8342
+ const getSideEffectInfoFromClosestPackage = (urlInfo) => {
8343
+ const sideEffectInfoFromClosestPackage =
8344
+ readSideEffectInfoFromClosestPackage(urlInfo);
8345
+ if (sideEffectInfoFromClosestPackage === undefined) {
8346
+ return null;
8347
+ }
8348
+ if (typeof sideEffectInfoFromClosestPackage === "function") {
8349
+ return sideEffectInfoFromClosestPackage(urlInfo);
8350
+ }
8351
+ return sideEffectInfoFromClosestPackage;
8352
+ };
8353
+
8354
+ return {
8355
+ name: "jsenv:package_side_effects",
8356
+ appliesDuring: "build",
8357
+ urlInfoCreated: (urlInfo) => {
8358
+ const url = urlInfo.url;
8359
+ if (isSpecifierForNodeBuiltin(url)) {
8360
+ urlInfo.contentSideEffects.push({
8361
+ sideEffect: "no",
8362
+ reason: "node builtin module",
8363
+ });
8364
+ return;
8365
+ }
8366
+ if (url.startsWith("file:")) {
8367
+ const sideEffectFromClosestPackage =
8368
+ getSideEffectInfoFromClosestPackage(urlInfo);
8369
+ if (sideEffectFromClosestPackage) {
8370
+ // if (sideEffectFromClosestPackage.has) {
8371
+ // console.log(`have side effect: ${url}`);
8372
+ // } else {
8373
+ // console.log(`no side effect: ${url}`);
8374
+ // }
8375
+ urlInfo.contentSideEffects.push(sideEffectFromClosestPackage);
8376
+ }
8377
+ return;
8378
+ }
8379
+ },
8380
+ refineBuildUrlContent: (buildUrlInfo, { buildUrl }) => {
8381
+ for (const sideEffect of buildUrlInfo.contentSideEffects) {
8382
+ if (sideEffect.has) {
8383
+ sideEffectBuildFileUrls.push(buildUrl);
8384
+ return;
8385
+ }
8386
+ }
8387
+ },
8388
+ refineBuild: (kitchen) => {
8389
+ if (sideEffectBuildFileUrls.length === 0) {
8390
+ return;
8391
+ }
8392
+ if (sideEffects === false) {
8393
+ updatePackageSideEffects(sideEffectBuildFileUrls);
8394
+ return;
8395
+ }
8396
+ const { buildDirectoryUrl } = kitchen.context;
8397
+ const sideEffectFileUrlSet = new Set();
8398
+ if (Array.isArray(sideEffects)) {
8399
+ let packageNeedsUpdate = false;
8400
+ for (const sideEffectFileRelativeUrl of sideEffects) {
8401
+ const sideEffectFileUrl = new URL(
8402
+ sideEffectFileRelativeUrl,
8403
+ packageDirectory.url,
8404
+ ).href;
8405
+ if (
8406
+ urlIsInsideOf(sideEffectFileUrl, buildDirectoryUrl) &&
8407
+ !sideEffectBuildFileUrls.includes(sideEffectFileUrl)
8408
+ ) {
8409
+ packageNeedsUpdate = true;
8410
+ } else {
8411
+ sideEffectFileUrlSet.add(sideEffectFileUrl);
8412
+ }
8413
+ }
8414
+ for (const sideEffectBuildUrl of sideEffectBuildFileUrls) {
8415
+ if (sideEffectFileUrlSet.has(sideEffectBuildUrl)) {
8416
+ continue;
8417
+ }
8418
+ packageNeedsUpdate = true;
8419
+ sideEffectFileUrlSet.add(sideEffectBuildUrl);
8420
+ }
8421
+ if (packageNeedsUpdate) {
8422
+ updatePackageSideEffects(sideEffectFileUrlSet);
8423
+ }
8424
+ }
8425
+ },
8426
+ };
8427
+ };
8428
+
8173
8429
  // tslint:disable:ordered-imports
8174
8430
 
8175
8431
 
@@ -8177,6 +8433,7 @@ const getCorePlugins = ({
8177
8433
  rootDirectoryUrl,
8178
8434
  mainFilePath,
8179
8435
  runtimeCompat,
8436
+ packageDirectory,
8180
8437
  sourceFilesConfig,
8181
8438
 
8182
8439
  referenceAnalysis = {},
@@ -8197,6 +8454,7 @@ const getCorePlugins = ({
8197
8454
  cacheControl,
8198
8455
  scenarioPlaceholders = true,
8199
8456
  ribbon = true,
8457
+ packageSideEffects = false,
8200
8458
  } = {}) => {
8201
8459
  if (cacheControl === true) {
8202
8460
  cacheControl = {};
@@ -8237,6 +8495,7 @@ const getCorePlugins = ({
8237
8495
  directoryListing,
8238
8496
  rootDirectoryUrl,
8239
8497
  mainFilePath,
8498
+ packageDirectory,
8240
8499
  sourceFilesConfig,
8241
8500
  }),
8242
8501
  {
@@ -8280,6 +8539,9 @@ const getCorePlugins = ({
8280
8539
  ...(ribbon ? [jsenvPluginRibbon({ rootDirectoryUrl, ...ribbon })] : []),
8281
8540
  jsenvPluginCleanHTML(),
8282
8541
  jsenvPluginChromeDevtoolsJson(),
8542
+ ...(packageSideEffects
8543
+ ? [jsenvPluginPackageSideEffects({ packageDirectory })]
8544
+ : []),
8283
8545
  ];
8284
8546
  };
8285
8547
 
@@ -8706,7 +8968,6 @@ const createBuildSpecifierManager = ({
8706
8968
  versioningMethod,
8707
8969
  versionLength,
8708
8970
  canUseImportmap,
8709
- onSourceFileBuild,
8710
8971
  }) => {
8711
8972
  const placeholderAPI = createPlaceholderAPI({
8712
8973
  length,
@@ -8773,31 +9034,6 @@ const createBuildSpecifierManager = ({
8773
9034
  buildSpecifier,
8774
9035
  reference,
8775
9036
  );
8776
-
8777
- if (buildUrlInfo.sourceUrls) {
8778
- for (const sourceUrl of buildUrlInfo.sourceUrls) {
8779
- const rawUrlInfo = rawKitchen.graph.getUrlInfo(sourceUrl);
8780
- if (rawUrlInfo) {
8781
- onSourceFileBuild({
8782
- sourceUrlInfo: rawUrlInfo,
8783
- buildUrlInfo,
8784
- sourceFileUrl: rawUrlInfo.url,
8785
- buildFileUrl: buildUrl,
8786
- });
8787
- }
8788
- }
8789
- } else if (buildUrlInfo.originalUrl) {
8790
- const rawUrlInfo = rawKitchen.graph.getUrlInfo(buildUrlInfo.originalUrl);
8791
- if (rawUrlInfo) {
8792
- onSourceFileBuild({
8793
- sourceUrlInfo: rawUrlInfo,
8794
- buildUrlInfo,
8795
- sourceFileUrl: rawUrlInfo.url,
8796
- buildFileUrl: buildUrl,
8797
- });
8798
- }
8799
- }
8800
-
8801
9037
  return buildGeneratedSpecifier;
8802
9038
  };
8803
9039
  const internalRedirections = new Map();
@@ -8814,14 +9050,17 @@ const createBuildSpecifierManager = ({
8814
9050
  );
8815
9051
  for (const url of Object.keys(urlInfosBundled)) {
8816
9052
  const urlInfoBundled = urlInfosBundled[url];
9053
+ const contentSideEffects = [];
8817
9054
  if (urlInfoBundled.sourceUrls) {
8818
9055
  for (const sourceUrl of urlInfoBundled.sourceUrls) {
8819
- const sourceRawUrlInfo = rawKitchen.graph.getUrlInfo(sourceUrl);
8820
- if (sourceRawUrlInfo) {
8821
- sourceRawUrlInfo.data.bundled = true;
9056
+ const rawUrlInfo = rawKitchen.graph.getUrlInfo(sourceUrl);
9057
+ if (rawUrlInfo) {
9058
+ rawUrlInfo.data.bundled = true;
9059
+ contentSideEffects.push(...rawUrlInfo.contentSideEffects);
8822
9060
  }
8823
9061
  }
8824
9062
  }
9063
+ urlInfoBundled.contentSideEffects = contentSideEffects;
8825
9064
  bundleInfoMap.set(url, urlInfoBundled);
8826
9065
  }
8827
9066
  };
@@ -8983,6 +9222,7 @@ const createBuildSpecifierManager = ({
8983
9222
  contentType: bundleInfo.contentType,
8984
9223
  sourcemap: bundleInfo.sourcemap,
8985
9224
  data: bundleInfo.data,
9225
+ contentSideEffects: bundleInfo.contentSideEffects,
8986
9226
  };
8987
9227
  }
8988
9228
  const rawUrlInfo = rawKitchen.graph.getUrlInfo(rawUrl);
@@ -9031,6 +9271,7 @@ const createBuildSpecifierManager = ({
9031
9271
  originalContent: rawUrlInfo.originalContent,
9032
9272
  originalUrl: rawUrlInfo.originalUrl,
9033
9273
  sourcemap: rawUrlInfo.sourcemap,
9274
+ contentSideEffects: rawUrlInfo.contentSideEffects,
9034
9275
  };
9035
9276
  }
9036
9277
  if (firstReference.isInline) {
@@ -9741,6 +9982,8 @@ const createBuildSpecifierManager = ({
9741
9982
  };
9742
9983
  },
9743
9984
 
9985
+ getBuildUrl: (urlInfo) => urlInfoToBuildUrlMap.get(urlInfo),
9986
+
9744
9987
  getBuildInfo: () => {
9745
9988
  const buildManifest = {};
9746
9989
  const buildContents = {};
@@ -10737,108 +10980,45 @@ const build = async ({
10737
10980
  return compareFileUrls(a.sourceUrl, b.sourceUrl);
10738
10981
  });
10739
10982
 
10740
- const packageDirectoryUrl = lookupPackageDirectory(sourceDirectoryUrl);
10983
+ const lookupPackageDirectoryUrl = createLookupPackageDirectory();
10984
+ const packageDirectoryCache = new Map();
10985
+ const readPackageDirectory = (url) => {
10986
+ const fromCache = packageDirectoryCache.get(url);
10987
+ if (fromCache !== undefined) {
10988
+ return fromCache;
10989
+ }
10990
+ return readPackageAtOrNull(url);
10991
+ };
10992
+ const packageDirectory = {
10993
+ url: lookupPackageDirectory(sourceDirectoryUrl),
10994
+ find: lookupPackageDirectoryUrl,
10995
+ read: readPackageDirectory,
10996
+ };
10997
+
10741
10998
  if (outDirectoryUrl === undefined) {
10742
10999
  if (
10743
11000
  process.env.CAPTURING_SIDE_EFFECTS ||
10744
11001
  (false)
10745
11002
  ) {
10746
11003
  outDirectoryUrl = new URL("../.jsenv_b/", sourceDirectoryUrl).href;
10747
- } else if (packageDirectoryUrl) {
10748
- outDirectoryUrl = `${packageDirectoryUrl}.jsenv/`;
11004
+ } else if (packageDirectory.url) {
11005
+ outDirectoryUrl = `${packageDirectory.url}.jsenv/`;
10749
11006
  }
10750
11007
  }
10751
- let rootPackageDirectoryUrl = packageDirectoryUrl;
10752
- if (packageDirectoryUrl) {
10753
- const parentPackageDirectoryUrl = lookupPackageDirectory(
10754
- new URL("../", packageDirectoryUrl),
11008
+ let rootPackageDirectoryUrl;
11009
+ if (packageDirectory.url) {
11010
+ const parentPackageDirectoryUrl = packageDirectory.find(
11011
+ new URL("../", packageDirectory.url),
10755
11012
  );
10756
- if (parentPackageDirectoryUrl) {
10757
- rootPackageDirectoryUrl = parentPackageDirectoryUrl;
10758
- }
11013
+ rootPackageDirectoryUrl = parentPackageDirectoryUrl || packageDirectory.url;
11014
+ } else {
11015
+ rootPackageDirectoryUrl = packageDirectory.url;
10759
11016
  }
10760
11017
 
10761
11018
  const runBuild = async ({ signal }) => {
10762
11019
  const startDate = Date.now();
10763
11020
  const { onBuildEnd, onEntryPointBuildStart } = startBuildLogs();
10764
11021
 
10765
- const sourceFileBuildCallbackMap = new Map();
10766
- const registerSourceFileBuildEffect = (url, callback) => {
10767
- const buildCallbackSet = sourceFileBuildCallbackMap.get(url);
10768
- if (buildCallbackSet) {
10769
- buildCallbackSet.add(callback);
10770
- } else {
10771
- const set = new Set();
10772
- set.add(callback);
10773
- sourceFileBuildCallbackMap.set(url, set);
10774
- }
10775
- };
10776
- const onSourceFileBuild = ({
10777
- sourceUrlInfo,
10778
- sourceFileUrl,
10779
- buildFileUrl,
10780
- }) => {
10781
- const buildCallbackSet = sourceFileBuildCallbackMap.get(sourceFileUrl);
10782
- if (buildCallbackSet) {
10783
- for (const buildCallback of buildCallbackSet) {
10784
- buildCallback({ sourceUrlInfo, buildFileUrl });
10785
- }
10786
- }
10787
- };
10788
- sync_package_side_effects: {
10789
- if (!packageDirectoryUrl) {
10790
- break sync_package_side_effects;
10791
- }
10792
- if (
10793
- urlIsInsideOf(packageDirectoryUrl, jsenvCoreDirectoryUrl) ||
10794
- packageDirectoryUrl === String(jsenvCoreDirectoryUrl)
10795
- ) {
10796
- break sync_package_side_effects;
10797
- }
10798
- const packageJson = readPackageAtOrNull(packageDirectoryUrl);
10799
- if (!packageJson) {
10800
- break sync_package_side_effects;
10801
- }
10802
- const { sideEffects } = packageJson;
10803
- if (!sideEffects || !Array.isArray(sideEffects)) {
10804
- break sync_package_side_effects;
10805
- }
10806
- const sideEffectFileUrlSet = new Set();
10807
- const packageJsonFileUrl = new URL("./package.json", packageDirectoryUrl)
10808
- .href;
10809
- for (const sideEffectFileRelativeUrl of sideEffects) {
10810
- const sideEffectFileUrl = new URL(
10811
- sideEffectFileRelativeUrl,
10812
- packageDirectoryUrl,
10813
- ).href;
10814
- sideEffectFileUrlSet.add(sideEffectFileUrl);
10815
- registerSourceFileBuildEffect(
10816
- sideEffectFileUrl,
10817
- ({ sourceUrlInfo, buildFileUrl }) => {
10818
- if (sourceUrlInfo.isInline) {
10819
- return;
10820
- }
10821
- const urlRelativeToPackage = urlToRelativeUrl(
10822
- buildFileUrl,
10823
- packageDirectoryUrl,
10824
- );
10825
- if (sideEffectFileUrlSet.has(buildFileUrl)) {
10826
- return;
10827
- }
10828
- sideEffects.push(
10829
- urlRelativeToPackage[0] === "."
10830
- ? urlRelativeToPackage
10831
- : `./${urlRelativeToPackage}`,
10832
- );
10833
- writeFileSync(
10834
- packageJsonFileUrl,
10835
- JSON.stringify(packageJson, null, " "),
10836
- );
10837
- },
10838
- );
10839
- }
10840
- }
10841
-
10842
11022
  const buildUrlsGenerator = createBuildUrlsGenerator({
10843
11023
  sourceDirectoryUrl,
10844
11024
  buildDirectoryUrl,
@@ -10889,9 +11069,9 @@ const build = async ({
10889
11069
  buildDirectoryUrl,
10890
11070
  outDirectoryUrl: entryOutDirectoryUrl,
10891
11071
  sourceRelativeUrl: entryPoint.sourceRelativeUrl,
11072
+ packageDirectory,
10892
11073
  buildUrlsGenerator,
10893
11074
  someEntryPointUseNode,
10894
- onSourceFileBuild,
10895
11075
  },
10896
11076
  entryPoint.params,
10897
11077
  );
@@ -11103,6 +11283,7 @@ const entryPointDefaultParams = {
11103
11283
  sourcemapsSourcesContent: undefined,
11104
11284
  assetManifest: false,
11105
11285
  assetManifestFileRelativeUrl: "asset-manifest.json",
11286
+ packageSideEffects: true,
11106
11287
  };
11107
11288
 
11108
11289
  const prepareEntryPointBuild = async (
@@ -11110,11 +11291,11 @@ const prepareEntryPointBuild = async (
11110
11291
  signal,
11111
11292
  sourceDirectoryUrl,
11112
11293
  buildDirectoryUrl,
11113
- sourceRelativeUrl,
11114
11294
  outDirectoryUrl,
11295
+ sourceRelativeUrl,
11296
+ packageDirectory,
11115
11297
  buildUrlsGenerator,
11116
11298
  someEntryPointUseNode,
11117
- onSourceFileBuild,
11118
11299
  },
11119
11300
  entryPointParams,
11120
11301
  ) => {
@@ -11152,6 +11333,7 @@ const prepareEntryPointBuild = async (
11152
11333
  sourcemapsSourcesContent,
11153
11334
  assetManifest,
11154
11335
  assetManifestFileRelativeUrl,
11336
+ packageSideEffects,
11155
11337
  } = {
11156
11338
  ...entryPointDefaultParams,
11157
11339
  ...entryPointParams,
@@ -11244,6 +11426,7 @@ const prepareEntryPointBuild = async (
11244
11426
  outDirectoryUrl: outDirectoryUrl
11245
11427
  ? new URL("craft/", outDirectoryUrl)
11246
11428
  : undefined,
11429
+ packageDirectory,
11247
11430
  });
11248
11431
 
11249
11432
  let _getOtherEntryBuildInfo;
@@ -11271,6 +11454,7 @@ const prepareEntryPointBuild = async (
11271
11454
  ...(bundling ? [jsenvPluginBundling(bundling)] : []),
11272
11455
  ...(minification ? [jsenvPluginMinification(minification)] : []),
11273
11456
  ...getCorePlugins({
11457
+ packageDirectory,
11274
11458
  rootDirectoryUrl: sourceDirectoryUrl,
11275
11459
  runtimeCompat,
11276
11460
  referenceAnalysis,
@@ -11288,6 +11472,7 @@ const prepareEntryPointBuild = async (
11288
11472
  inlining: false,
11289
11473
  http,
11290
11474
  scenarioPlaceholders,
11475
+ packageSideEffects,
11291
11476
  }),
11292
11477
  ]);
11293
11478
  const rawPluginController = createPluginController(
@@ -11340,6 +11525,7 @@ const prepareEntryPointBuild = async (
11340
11525
  outDirectoryUrl: outDirectoryUrl
11341
11526
  ? new URL("shape/", outDirectoryUrl)
11342
11527
  : undefined,
11528
+ packageDirectory,
11343
11529
  });
11344
11530
  const buildSpecifierManager = createBuildSpecifierManager({
11345
11531
  rawKitchen,
@@ -11358,7 +11544,6 @@ const prepareEntryPointBuild = async (
11358
11544
  versioningViaImportmap &&
11359
11545
  rawKitchen.graph.getUrlInfo(entryReference.url).type === "html" &&
11360
11546
  rawKitchen.context.isSupportedOnCurrentClients("importmap"),
11361
- onSourceFileBuild,
11362
11547
  });
11363
11548
  const finalPluginStore = createPluginStore([
11364
11549
  jsenvPluginReferenceAnalysis({
@@ -11383,7 +11568,7 @@ const prepareEntryPointBuild = async (
11383
11568
  appliesDuring: "build",
11384
11569
  transformUrlContent: async (urlInfo) => {
11385
11570
  await rawKitchen.pluginController.callAsyncHooks(
11386
- "optimizeUrlContent",
11571
+ "optimizeBuildUrlContent",
11387
11572
  urlInfo,
11388
11573
  (optimizeReturnValue) => {
11389
11574
  urlInfo.mutateContent(optimizeReturnValue);
@@ -11609,6 +11794,41 @@ const prepareEntryPointBuild = async (
11609
11794
  buildOperation.throwIfAborted();
11610
11795
  }
11611
11796
  }
11797
+
11798
+ {
11799
+ const refineBuildUrlContentCallbackSet = new Set();
11800
+ const refineBuildCallbackSet = new Set();
11801
+ for (const plugin of rawKitchen.pluginController.activePlugins) {
11802
+ const refineBuildUrlContent = plugin.refineBuildUrlContent;
11803
+ if (refineBuildUrlContent) {
11804
+ refineBuildUrlContentCallbackSet.add(refineBuildUrlContent);
11805
+ }
11806
+ const refineBuild = plugin.refineBuild;
11807
+ if (refineBuild) {
11808
+ refineBuildCallbackSet.add(refineBuild);
11809
+ }
11810
+ }
11811
+ if (refineBuildUrlContentCallbackSet.size) {
11812
+ GRAPH_VISITOR.forEachUrlInfoStronglyReferenced(
11813
+ finalKitchen.graph.rootUrlInfo,
11814
+ (buildUrlInfo) => {
11815
+ if (!buildUrlInfo.url.startsWith("file:")) {
11816
+ return;
11817
+ }
11818
+ for (const refineBuildUrlContentCallback of refineBuildUrlContentCallbackSet) {
11819
+ refineBuildUrlContentCallback(buildUrlInfo, {
11820
+ buildUrl: buildSpecifierManager.getBuildUrl(buildUrlInfo),
11821
+ });
11822
+ }
11823
+ },
11824
+ );
11825
+ }
11826
+ if (refineBuildCallbackSet.size) {
11827
+ for (const refineBuildCallback of refineBuildCallbackSet) {
11828
+ refineBuildCallback(finalKitchen);
11829
+ }
11830
+ }
11831
+ }
11612
11832
  }
11613
11833
  const {
11614
11834
  buildFileContents,