@jsenv/core 40.2.0 → 40.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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, updateJsonFileSync$1 as updateJsonFileSync, isSpecifierForNodeBuiltin$1 as isSpecifierForNodeBuiltin, 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,216 @@ 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 sideEffectFileUrlSet = new Set();
8233
+ const packageJsonFileUrl = new URL("./package.json", packageDirectory.url)
8234
+ .href;
8235
+
8236
+ const normalizeSideEffectFileUrl = (url) => {
8237
+ const urlRelativeToPackage = urlToRelativeUrl(url, packageDirectory.url);
8238
+ return urlRelativeToPackage[0] === "."
8239
+ ? urlRelativeToPackage
8240
+ : `./${urlRelativeToPackage}`;
8241
+ };
8242
+
8243
+ const sideEffectBuildFileUrls = [];
8244
+
8245
+ const packageSideEffectsCacheMap = new Map();
8246
+ const readSideEffectInfoFromClosestPackage = (urlInfo) => {
8247
+ const closestPackageDirectoryUrl = urlInfo.packageDirectoryUrl;
8248
+ const closestPackageJSON = urlInfo.packageJSON;
8249
+ if (!closestPackageJSON) {
8250
+ return undefined;
8251
+ }
8252
+ const fromCache = packageSideEffectsCacheMap.get(
8253
+ closestPackageDirectoryUrl,
8254
+ );
8255
+ if (fromCache) {
8256
+ return fromCache.value;
8257
+ }
8258
+ try {
8259
+ return storePackageSideEffect(
8260
+ closestPackageDirectoryUrl,
8261
+ closestPackageJSON,
8262
+ );
8263
+ } catch {
8264
+ return storePackageSideEffect(closestPackageDirectoryUrl, null);
8265
+ }
8266
+ };
8267
+ const storePackageSideEffect = (packageDirectoryUrl, packageJSON) => {
8268
+ if (!packageJSON) {
8269
+ packageSideEffectsCacheMap.set(packageDirectoryUrl, { value: undefined });
8270
+ return undefined;
8271
+ }
8272
+ const value = packageJSON.sideEffects;
8273
+ if (Array.isArray(value)) {
8274
+ const noSideEffect = {
8275
+ has: false,
8276
+ reason: "not listed in package.json side effects",
8277
+ packageDirectoryUrl,
8278
+ };
8279
+ const hasSideEffect = {
8280
+ has: true,
8281
+ reason: "listed in package.json side effects",
8282
+ packageDirectoryUrl,
8283
+ };
8284
+ const sideEffectPatterns = {};
8285
+ for (const v of value) {
8286
+ sideEffectPatterns[v] = v;
8287
+ }
8288
+ const associations = URL_META.resolveAssociations(
8289
+ { sideEffects: sideEffectPatterns },
8290
+ packageDirectoryUrl,
8291
+ );
8292
+ const getSideEffectInfo = (urlInfo) => {
8293
+ const meta = URL_META.applyAssociations({
8294
+ url: urlInfo.url,
8295
+ associations,
8296
+ });
8297
+ const sideEffectKey = meta.sideEffects;
8298
+ if (sideEffectKey) {
8299
+ return {
8300
+ ...hasSideEffect,
8301
+ reason: `"${sideEffectKey}" listed in package.json side effects`,
8302
+ };
8303
+ }
8304
+ return noSideEffect;
8305
+ };
8306
+ packageSideEffectsCacheMap.set(packageDirectoryUrl, {
8307
+ value: getSideEffectInfo,
8308
+ });
8309
+ return getSideEffectInfo;
8310
+ }
8311
+ if (value === false) {
8312
+ const noSideEffect = {
8313
+ has: false,
8314
+ reason: "package.json side effects is false",
8315
+ packageDirectoryUrl,
8316
+ };
8317
+ packageSideEffectsCacheMap.set(packageDirectoryUrl, {
8318
+ value: noSideEffect,
8319
+ });
8320
+ return noSideEffect;
8321
+ }
8322
+ const hasSideEffect = {
8323
+ has: true,
8324
+ reason: "package.json side effects is true",
8325
+ packageDirectoryUrl,
8326
+ };
8327
+ packageSideEffectsCacheMap.set(packageDirectoryUrl, {
8328
+ value: hasSideEffect,
8329
+ });
8330
+ return hasSideEffect;
8331
+ };
8332
+ const getSideEffectInfoFromClosestPackage = (urlInfo) => {
8333
+ const sideEffectInfoFromClosestPackage =
8334
+ readSideEffectInfoFromClosestPackage(urlInfo);
8335
+ if (sideEffectInfoFromClosestPackage === undefined) {
8336
+ return null;
8337
+ }
8338
+ if (typeof sideEffectInfoFromClosestPackage === "function") {
8339
+ return sideEffectInfoFromClosestPackage(urlInfo);
8340
+ }
8341
+ return sideEffectInfoFromClosestPackage;
8342
+ };
8343
+
8344
+ return {
8345
+ name: "jsenv:package_side_effects",
8346
+ appliesDuring: "build",
8347
+ urlInfoCreated: (urlInfo) => {
8348
+ const url = urlInfo.url;
8349
+ if (isSpecifierForNodeBuiltin(url)) {
8350
+ urlInfo.contentSideEffects.push({
8351
+ sideEffect: "no",
8352
+ reason: "node builtin module",
8353
+ });
8354
+ return;
8355
+ }
8356
+ if (url.startsWith("file:")) {
8357
+ const sideEffectFromClosestPackage =
8358
+ getSideEffectInfoFromClosestPackage(urlInfo);
8359
+ if (sideEffectFromClosestPackage) {
8360
+ // if (sideEffectFromClosestPackage.has) {
8361
+ // console.log(`have side effect: ${url}`);
8362
+ // } else {
8363
+ // console.log(`no side effect: ${url}`);
8364
+ // }
8365
+ urlInfo.contentSideEffects.push(sideEffectFromClosestPackage);
8366
+ }
8367
+ return;
8368
+ }
8369
+ },
8370
+ refineBuildUrlContent: (buildUrlInfo, { buildUrl }) => {
8371
+ for (const sideEffect of buildUrlInfo.contentSideEffects) {
8372
+ if (sideEffect.has) {
8373
+ sideEffectBuildFileUrls.push(buildUrl);
8374
+ return;
8375
+ }
8376
+ }
8377
+ },
8378
+ refineBuild: () => {
8379
+ if (sideEffectBuildFileUrls.length === 0) {
8380
+ return;
8381
+ }
8382
+ let sideEffectsToAdd = [];
8383
+ if (sideEffects === false) {
8384
+ sideEffectsToAdd = sideEffectBuildFileUrls;
8385
+ } else if (Array.isArray(sideEffects)) {
8386
+ for (const sideEffectFileRelativeUrl of sideEffects) {
8387
+ const sideEffectFileUrl = new URL(
8388
+ sideEffectFileRelativeUrl,
8389
+ packageDirectory.url,
8390
+ ).href;
8391
+ sideEffectFileUrlSet.add(sideEffectFileUrl);
8392
+ }
8393
+ for (const url of sideEffectBuildFileUrls) {
8394
+ if (sideEffectFileUrlSet.has(url)) {
8395
+ continue;
8396
+ }
8397
+ sideEffectsToAdd.push(url);
8398
+ }
8399
+ }
8400
+ if (sideEffectsToAdd.length === 0) {
8401
+ return;
8402
+ }
8403
+
8404
+ const finalSideEffects = Array.isArray(sideEffects) ? sideEffects : [];
8405
+ for (const sideEffectBuildUrl of sideEffectBuildFileUrls) {
8406
+ finalSideEffects.push(normalizeSideEffectFileUrl(sideEffectBuildUrl));
8407
+ }
8408
+ updateJsonFileSync(packageJsonFileUrl, {
8409
+ sideEffects: finalSideEffects,
8410
+ });
8411
+ },
8412
+ };
8413
+ };
8414
+
8173
8415
  // tslint:disable:ordered-imports
8174
8416
 
8175
8417
 
@@ -8177,6 +8419,7 @@ const getCorePlugins = ({
8177
8419
  rootDirectoryUrl,
8178
8420
  mainFilePath,
8179
8421
  runtimeCompat,
8422
+ packageDirectory,
8180
8423
  sourceFilesConfig,
8181
8424
 
8182
8425
  referenceAnalysis = {},
@@ -8197,6 +8440,7 @@ const getCorePlugins = ({
8197
8440
  cacheControl,
8198
8441
  scenarioPlaceholders = true,
8199
8442
  ribbon = true,
8443
+ packageSideEffects = false,
8200
8444
  } = {}) => {
8201
8445
  if (cacheControl === true) {
8202
8446
  cacheControl = {};
@@ -8237,6 +8481,7 @@ const getCorePlugins = ({
8237
8481
  directoryListing,
8238
8482
  rootDirectoryUrl,
8239
8483
  mainFilePath,
8484
+ packageDirectory,
8240
8485
  sourceFilesConfig,
8241
8486
  }),
8242
8487
  {
@@ -8280,6 +8525,9 @@ const getCorePlugins = ({
8280
8525
  ...(ribbon ? [jsenvPluginRibbon({ rootDirectoryUrl, ...ribbon })] : []),
8281
8526
  jsenvPluginCleanHTML(),
8282
8527
  jsenvPluginChromeDevtoolsJson(),
8528
+ ...(packageSideEffects
8529
+ ? [jsenvPluginPackageSideEffects({ packageDirectory })]
8530
+ : []),
8283
8531
  ];
8284
8532
  };
8285
8533
 
@@ -8706,7 +8954,6 @@ const createBuildSpecifierManager = ({
8706
8954
  versioningMethod,
8707
8955
  versionLength,
8708
8956
  canUseImportmap,
8709
- onSourceFileBuild,
8710
8957
  }) => {
8711
8958
  const placeholderAPI = createPlaceholderAPI({
8712
8959
  length,
@@ -8773,31 +9020,6 @@ const createBuildSpecifierManager = ({
8773
9020
  buildSpecifier,
8774
9021
  reference,
8775
9022
  );
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
9023
  return buildGeneratedSpecifier;
8802
9024
  };
8803
9025
  const internalRedirections = new Map();
@@ -8814,14 +9036,17 @@ const createBuildSpecifierManager = ({
8814
9036
  );
8815
9037
  for (const url of Object.keys(urlInfosBundled)) {
8816
9038
  const urlInfoBundled = urlInfosBundled[url];
9039
+ const contentSideEffects = [];
8817
9040
  if (urlInfoBundled.sourceUrls) {
8818
9041
  for (const sourceUrl of urlInfoBundled.sourceUrls) {
8819
- const sourceRawUrlInfo = rawKitchen.graph.getUrlInfo(sourceUrl);
8820
- if (sourceRawUrlInfo) {
8821
- sourceRawUrlInfo.data.bundled = true;
9042
+ const rawUrlInfo = rawKitchen.graph.getUrlInfo(sourceUrl);
9043
+ if (rawUrlInfo) {
9044
+ rawUrlInfo.data.bundled = true;
9045
+ contentSideEffects.push(...rawUrlInfo.contentSideEffects);
8822
9046
  }
8823
9047
  }
8824
9048
  }
9049
+ urlInfoBundled.contentSideEffects = contentSideEffects;
8825
9050
  bundleInfoMap.set(url, urlInfoBundled);
8826
9051
  }
8827
9052
  };
@@ -8983,6 +9208,7 @@ const createBuildSpecifierManager = ({
8983
9208
  contentType: bundleInfo.contentType,
8984
9209
  sourcemap: bundleInfo.sourcemap,
8985
9210
  data: bundleInfo.data,
9211
+ contentSideEffects: bundleInfo.contentSideEffects,
8986
9212
  };
8987
9213
  }
8988
9214
  const rawUrlInfo = rawKitchen.graph.getUrlInfo(rawUrl);
@@ -9031,6 +9257,7 @@ const createBuildSpecifierManager = ({
9031
9257
  originalContent: rawUrlInfo.originalContent,
9032
9258
  originalUrl: rawUrlInfo.originalUrl,
9033
9259
  sourcemap: rawUrlInfo.sourcemap,
9260
+ contentSideEffects: rawUrlInfo.contentSideEffects,
9034
9261
  };
9035
9262
  }
9036
9263
  if (firstReference.isInline) {
@@ -9741,6 +9968,8 @@ const createBuildSpecifierManager = ({
9741
9968
  };
9742
9969
  },
9743
9970
 
9971
+ getBuildUrl: (urlInfo) => urlInfoToBuildUrlMap.get(urlInfo),
9972
+
9744
9973
  getBuildInfo: () => {
9745
9974
  const buildManifest = {};
9746
9975
  const buildContents = {};
@@ -10737,92 +10966,45 @@ const build = async ({
10737
10966
  return compareFileUrls(a.sourceUrl, b.sourceUrl);
10738
10967
  });
10739
10968
 
10740
- const packageDirectoryUrl = lookupPackageDirectory(sourceDirectoryUrl);
10969
+ const lookupPackageDirectoryUrl = createLookupPackageDirectory();
10970
+ const packageDirectoryCache = new Map();
10971
+ const readPackageDirectory = (url) => {
10972
+ const fromCache = packageDirectoryCache.get(url);
10973
+ if (fromCache !== undefined) {
10974
+ return fromCache;
10975
+ }
10976
+ return readPackageAtOrNull(url);
10977
+ };
10978
+ const packageDirectory = {
10979
+ url: lookupPackageDirectory(sourceDirectoryUrl),
10980
+ find: lookupPackageDirectoryUrl,
10981
+ read: readPackageDirectory,
10982
+ };
10983
+
10741
10984
  if (outDirectoryUrl === undefined) {
10742
10985
  if (
10743
10986
  process.env.CAPTURING_SIDE_EFFECTS ||
10744
10987
  (false)
10745
10988
  ) {
10746
10989
  outDirectoryUrl = new URL("../.jsenv_b/", sourceDirectoryUrl).href;
10747
- } else if (packageDirectoryUrl) {
10748
- outDirectoryUrl = `${packageDirectoryUrl}.jsenv/`;
10990
+ } else if (packageDirectory.url) {
10991
+ outDirectoryUrl = `${packageDirectory.url}.jsenv/`;
10749
10992
  }
10750
10993
  }
10751
- let rootPackageDirectoryUrl = packageDirectoryUrl;
10752
- if (packageDirectoryUrl) {
10753
- const parentPackageDirectoryUrl = lookupPackageDirectory(
10754
- new URL("../", packageDirectoryUrl),
10994
+ let rootPackageDirectoryUrl;
10995
+ if (packageDirectory.url) {
10996
+ const parentPackageDirectoryUrl = packageDirectory.find(
10997
+ new URL("../", packageDirectory.url),
10755
10998
  );
10756
- if (parentPackageDirectoryUrl) {
10757
- rootPackageDirectoryUrl = parentPackageDirectoryUrl;
10758
- }
10999
+ rootPackageDirectoryUrl = parentPackageDirectoryUrl || packageDirectory.url;
11000
+ } else {
11001
+ rootPackageDirectoryUrl = packageDirectory.url;
10759
11002
  }
10760
11003
 
10761
11004
  const runBuild = async ({ signal }) => {
10762
11005
  const startDate = Date.now();
10763
11006
  const { onBuildEnd, onEntryPointBuildStart } = startBuildLogs();
10764
11007
 
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 = ({ sourceFileUrl, buildFileUrl }) => {
10777
- const buildCallbackSet = sourceFileBuildCallbackMap.get(sourceFileUrl);
10778
- if (buildCallbackSet) {
10779
- for (const buildCallback of buildCallbackSet) {
10780
- buildCallback({ buildFileUrl });
10781
- }
10782
- }
10783
- };
10784
- sync_package_side_effects: {
10785
- if (!packageDirectoryUrl) {
10786
- break sync_package_side_effects;
10787
- }
10788
- const packageJson = readPackageAtOrNull(packageDirectoryUrl);
10789
- if (!packageJson) {
10790
- break sync_package_side_effects;
10791
- }
10792
- const { sideEffects } = packageJson;
10793
- if (!sideEffects || !Array.isArray(sideEffects)) {
10794
- break sync_package_side_effects;
10795
- }
10796
- const sideEffectFileUrlSet = new Set();
10797
- const packageJsonFileUrl = new URL("./package.json", packageDirectoryUrl)
10798
- .href;
10799
- for (const sideEffectFileRelativeUrl of sideEffects) {
10800
- const sideEffectFileUrl = new URL(
10801
- sideEffectFileRelativeUrl,
10802
- packageDirectoryUrl,
10803
- ).href;
10804
- sideEffectFileUrlSet.add(sideEffectFileUrl);
10805
- registerSourceFileBuildEffect(sideEffectFileUrl, ({ buildFileUrl }) => {
10806
- const urlRelativeToPackage = urlToRelativeUrl(
10807
- buildFileUrl,
10808
- packageDirectoryUrl,
10809
- );
10810
- if (sideEffectFileUrlSet.has(buildFileUrl)) {
10811
- return;
10812
- }
10813
- sideEffects.push(
10814
- urlRelativeToPackage[0] === "."
10815
- ? urlRelativeToPackage
10816
- : `./${urlRelativeToPackage}`,
10817
- );
10818
- writeFileSync(
10819
- packageJsonFileUrl,
10820
- JSON.stringify(packageJson, null, " "),
10821
- );
10822
- });
10823
- }
10824
- }
10825
-
10826
11008
  const buildUrlsGenerator = createBuildUrlsGenerator({
10827
11009
  sourceDirectoryUrl,
10828
11010
  buildDirectoryUrl,
@@ -10873,9 +11055,9 @@ const build = async ({
10873
11055
  buildDirectoryUrl,
10874
11056
  outDirectoryUrl: entryOutDirectoryUrl,
10875
11057
  sourceRelativeUrl: entryPoint.sourceRelativeUrl,
11058
+ packageDirectory,
10876
11059
  buildUrlsGenerator,
10877
11060
  someEntryPointUseNode,
10878
- onSourceFileBuild,
10879
11061
  },
10880
11062
  entryPoint.params,
10881
11063
  );
@@ -11087,6 +11269,7 @@ const entryPointDefaultParams = {
11087
11269
  sourcemapsSourcesContent: undefined,
11088
11270
  assetManifest: false,
11089
11271
  assetManifestFileRelativeUrl: "asset-manifest.json",
11272
+ packageSideEffects: true,
11090
11273
  };
11091
11274
 
11092
11275
  const prepareEntryPointBuild = async (
@@ -11094,11 +11277,11 @@ const prepareEntryPointBuild = async (
11094
11277
  signal,
11095
11278
  sourceDirectoryUrl,
11096
11279
  buildDirectoryUrl,
11097
- sourceRelativeUrl,
11098
11280
  outDirectoryUrl,
11281
+ sourceRelativeUrl,
11282
+ packageDirectory,
11099
11283
  buildUrlsGenerator,
11100
11284
  someEntryPointUseNode,
11101
- onSourceFileBuild,
11102
11285
  },
11103
11286
  entryPointParams,
11104
11287
  ) => {
@@ -11136,6 +11319,7 @@ const prepareEntryPointBuild = async (
11136
11319
  sourcemapsSourcesContent,
11137
11320
  assetManifest,
11138
11321
  assetManifestFileRelativeUrl,
11322
+ packageSideEffects,
11139
11323
  } = {
11140
11324
  ...entryPointDefaultParams,
11141
11325
  ...entryPointParams,
@@ -11228,6 +11412,7 @@ const prepareEntryPointBuild = async (
11228
11412
  outDirectoryUrl: outDirectoryUrl
11229
11413
  ? new URL("craft/", outDirectoryUrl)
11230
11414
  : undefined,
11415
+ packageDirectory,
11231
11416
  });
11232
11417
 
11233
11418
  let _getOtherEntryBuildInfo;
@@ -11255,6 +11440,7 @@ const prepareEntryPointBuild = async (
11255
11440
  ...(bundling ? [jsenvPluginBundling(bundling)] : []),
11256
11441
  ...(minification ? [jsenvPluginMinification(minification)] : []),
11257
11442
  ...getCorePlugins({
11443
+ packageDirectory,
11258
11444
  rootDirectoryUrl: sourceDirectoryUrl,
11259
11445
  runtimeCompat,
11260
11446
  referenceAnalysis,
@@ -11272,6 +11458,7 @@ const prepareEntryPointBuild = async (
11272
11458
  inlining: false,
11273
11459
  http,
11274
11460
  scenarioPlaceholders,
11461
+ packageSideEffects,
11275
11462
  }),
11276
11463
  ]);
11277
11464
  const rawPluginController = createPluginController(
@@ -11324,6 +11511,7 @@ const prepareEntryPointBuild = async (
11324
11511
  outDirectoryUrl: outDirectoryUrl
11325
11512
  ? new URL("shape/", outDirectoryUrl)
11326
11513
  : undefined,
11514
+ packageDirectory,
11327
11515
  });
11328
11516
  const buildSpecifierManager = createBuildSpecifierManager({
11329
11517
  rawKitchen,
@@ -11342,7 +11530,6 @@ const prepareEntryPointBuild = async (
11342
11530
  versioningViaImportmap &&
11343
11531
  rawKitchen.graph.getUrlInfo(entryReference.url).type === "html" &&
11344
11532
  rawKitchen.context.isSupportedOnCurrentClients("importmap"),
11345
- onSourceFileBuild,
11346
11533
  });
11347
11534
  const finalPluginStore = createPluginStore([
11348
11535
  jsenvPluginReferenceAnalysis({
@@ -11367,7 +11554,7 @@ const prepareEntryPointBuild = async (
11367
11554
  appliesDuring: "build",
11368
11555
  transformUrlContent: async (urlInfo) => {
11369
11556
  await rawKitchen.pluginController.callAsyncHooks(
11370
- "optimizeUrlContent",
11557
+ "optimizeBuildUrlContent",
11371
11558
  urlInfo,
11372
11559
  (optimizeReturnValue) => {
11373
11560
  urlInfo.mutateContent(optimizeReturnValue);
@@ -11593,6 +11780,41 @@ const prepareEntryPointBuild = async (
11593
11780
  buildOperation.throwIfAborted();
11594
11781
  }
11595
11782
  }
11783
+
11784
+ {
11785
+ const refineBuildUrlContentCallbackSet = new Set();
11786
+ const refineBuildCallbackSet = new Set();
11787
+ for (const plugin of rawKitchen.pluginController.activePlugins) {
11788
+ const refineBuildUrlContent = plugin.refineBuildUrlContent;
11789
+ if (refineBuildUrlContent) {
11790
+ refineBuildUrlContentCallbackSet.add(refineBuildUrlContent);
11791
+ }
11792
+ const refineBuild = plugin.refineBuild;
11793
+ if (refineBuild) {
11794
+ refineBuildCallbackSet.add(refineBuild);
11795
+ }
11796
+ }
11797
+ if (refineBuildUrlContentCallbackSet.size) {
11798
+ GRAPH_VISITOR.forEachUrlInfoStronglyReferenced(
11799
+ finalKitchen.graph.rootUrlInfo,
11800
+ (buildUrlInfo) => {
11801
+ if (!buildUrlInfo.url.startsWith("file:")) {
11802
+ return;
11803
+ }
11804
+ for (const refineBuildUrlContentCallback of refineBuildUrlContentCallbackSet) {
11805
+ refineBuildUrlContentCallback(buildUrlInfo, {
11806
+ buildUrl: buildSpecifierManager.getBuildUrl(buildUrlInfo),
11807
+ });
11808
+ }
11809
+ },
11810
+ );
11811
+ }
11812
+ if (refineBuildCallbackSet.size) {
11813
+ for (const refineBuildCallback of refineBuildCallbackSet) {
11814
+ refineBuildCallback(finalKitchen.graph);
11815
+ }
11816
+ }
11817
+ }
11596
11818
  }
11597
11819
  const {
11598
11820
  buildFileContents,