@jsenv/core 29.9.1 → 30.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.js CHANGED
@@ -15,10 +15,11 @@ import { performance as performance$1 } from "node:perf_hooks";
15
15
  import { Readable, Stream, Writable } from "node:stream";
16
16
  import { Http2ServerResponse } from "node:http2";
17
17
  import { lookup } from "node:dns";
18
- import { SOURCEMAP, generateSourcemapFileUrl, composeTwoSourcemaps, generateSourcemapDataUrl, createMagicSource, sourcemapConverter, getOriginalPosition } from "@jsenv/sourcemap";
19
- import { parseHtmlString, stringifyHtmlAst, getHtmlNodeAttribute, visitHtmlNodes, analyzeScriptNode, setHtmlNodeAttributes, parseSrcSet, getHtmlNodePosition, getHtmlNodeAttributePosition, applyPostCss, postCssPluginUrlVisitor, parseJsUrls, getHtmlNodeText, setHtmlNodeText, applyBabelPlugins, injectScriptNodeAsEarlyAsPossible, createHtmlNode, findHtmlNode, removeHtmlNode, removeHtmlNodeText, transpileWithParcel, injectJsImport, minifyWithParcel, analyzeLinkNode, injectHtmlNode, insertHtmlNodeAfter } from "@jsenv/ast";
18
+ import { SOURCEMAP, generateSourcemapFileUrl, composeTwoSourcemaps, generateSourcemapDataUrl, createMagicSource, getOriginalPosition } from "@jsenv/sourcemap";
19
+ import { parseHtmlString, stringifyHtmlAst, getHtmlNodeAttribute, visitHtmlNodes, analyzeScriptNode, setHtmlNodeAttributes, parseSrcSet, getHtmlNodePosition, getHtmlNodeAttributePosition, applyPostCss, postCssPluginUrlVisitor, parseJsUrls, getHtmlNodeText, setHtmlNodeText, applyBabelPlugins, injectScriptNodeAsEarlyAsPossible, createHtmlNode, findHtmlNode, removeHtmlNode, removeHtmlNodeText, transpileWithParcel, injectJsImport, analyzeLinkNode, injectHtmlNode, insertHtmlNodeAfter } from "@jsenv/ast";
20
20
  import { createRequire } from "node:module";
21
21
  import babelParser from "@babel/parser";
22
+ import { bundleJsModules } from "@jsenv/plugin-bundling";
22
23
  import v8, { takeCoverage } from "node:v8";
23
24
  import wrapAnsi from "wrap-ansi";
24
25
  import stripAnsi from "strip-ansi";
@@ -2367,7 +2368,7 @@ const error = (...args) => console.error(...args);
2367
2368
  const errorDisabled = () => {};
2368
2369
 
2369
2370
  // From: https://github.com/sindresorhus/has-flag/blob/main/index.js
2370
- function hasFlag(flag, argv = process$1.argv) {
2371
+ function hasFlag(flag, argv = globalThis.Deno?.args ?? process$1.argv) {
2371
2372
  const prefix = flag.startsWith('-') ? '' : flag.length === 1 ? '-' : '--';
2372
2373
  const position = argv.indexOf(prefix + flag);
2373
2374
  const terminatorPosition = argv.indexOf('--');
@@ -2424,6 +2425,12 @@ function _supportsColor(haveStream, {
2424
2425
  return 2;
2425
2426
  }
2426
2427
  }
2428
+
2429
+ // Check for Azure DevOps pipelines.
2430
+ // Has to be above the `!streamIsTTY` check.
2431
+ if ('TF_BUILD' in env && 'AGENT_NAME' in env) {
2432
+ return 1;
2433
+ }
2427
2434
  if (haveStream && !streamIsTTY && forceColor === undefined) {
2428
2435
  return 0;
2429
2436
  }
@@ -2441,7 +2448,10 @@ function _supportsColor(haveStream, {
2441
2448
  return 1;
2442
2449
  }
2443
2450
  if ('CI' in env) {
2444
- if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI', 'GITHUB_ACTIONS', 'BUILDKITE', 'DRONE'].some(sign => sign in env) || env.CI_NAME === 'codeship') {
2451
+ if ('GITHUB_ACTIONS' in env) {
2452
+ return 3;
2453
+ }
2454
+ if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI', 'BUILDKITE', 'DRONE'].some(sign => sign in env) || env.CI_NAME === 'codeship') {
2445
2455
  return 1;
2446
2456
  }
2447
2457
  return min;
@@ -2449,14 +2459,12 @@ function _supportsColor(haveStream, {
2449
2459
  if ('TEAMCITY_VERSION' in env) {
2450
2460
  return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
2451
2461
  }
2452
-
2453
- // Check for Azure DevOps pipelines
2454
- if ('TF_BUILD' in env && 'AGENT_NAME' in env) {
2455
- return 1;
2456
- }
2457
2462
  if (env.COLORTERM === 'truecolor') {
2458
2463
  return 3;
2459
2464
  }
2465
+ if (env.TERM === 'xterm-kitty') {
2466
+ return 3;
2467
+ }
2460
2468
  if ('TERM_PROGRAM' in env) {
2461
2469
  const version = Number.parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10);
2462
2470
  switch (env.TERM_PROGRAM) {
@@ -14818,432 +14826,6 @@ const jsenvPluginAsJsClassicWorkers = () => {
14818
14826
  };
14819
14827
  };
14820
14828
 
14821
- /*
14822
- * Generated helpers
14823
- * - https://github.com/babel/babel/commits/main/packages/babel-helpers/src/helpers.ts
14824
- * File helpers
14825
- * - https://github.com/babel/babel/tree/main/packages/babel-helpers/src/helpers
14826
- *
14827
- */
14828
- const babelHelperClientDirectoryUrl = new URL("./babel_helpers/", import.meta.url).href;
14829
-
14830
- // we cannot use "@jsenv/core/src/*" because babel helper might be injected
14831
- // into node_modules not depending on "@jsenv/core"
14832
- const getBabelHelperFileUrl = babelHelperName => {
14833
- const babelHelperFileUrl = new URL(`./${babelHelperName}/${babelHelperName}.js`, babelHelperClientDirectoryUrl).href;
14834
- return babelHelperFileUrl;
14835
- };
14836
- const babelHelperNameFromUrl = url => {
14837
- if (!url.startsWith(babelHelperClientDirectoryUrl)) {
14838
- return null;
14839
- }
14840
- const afterBabelHelperDirectory = url.slice(babelHelperClientDirectoryUrl.length);
14841
- const babelHelperName = afterBabelHelperDirectory.slice(0, afterBabelHelperDirectory.indexOf("/"));
14842
- return babelHelperName;
14843
- };
14844
-
14845
- const fileUrlConverter = {
14846
- asFilePath: fileUrl => {
14847
- const filePath = urlToFileSystemPath(fileUrl);
14848
- const urlObject = new URL(fileUrl);
14849
- const {
14850
- searchParams
14851
- } = urlObject;
14852
- return `${filePath}${stringifyQuery(searchParams)}`;
14853
- },
14854
- asFileUrl: filePath => {
14855
- return decodeURIComponent(fileSystemPathToUrl$1(filePath)).replace(/[=](?=&|$)/g, "");
14856
- }
14857
- };
14858
- const stringifyQuery = searchParams => {
14859
- const search = searchParams.toString();
14860
- return search ? `?${search}` : "";
14861
- };
14862
-
14863
- const globalThisClientFileUrl = new URL("./js/global_this.js", import.meta.url).href;
14864
- const newStylesheetClientFileUrl = new URL("./js/new_stylesheet.js", import.meta.url).href;
14865
- const regeneratorRuntimeClientFileUrl = new URL("./js/regenerator_runtime.js", import.meta.url).href;
14866
- const bundleJsModules = async ({
14867
- jsModuleUrlInfos,
14868
- context,
14869
- options
14870
- }) => {
14871
- const {
14872
- signal,
14873
- logger,
14874
- rootDirectoryUrl,
14875
- buildDirectoryUrl,
14876
- assetsDirectory,
14877
- urlGraph,
14878
- runtimeCompat,
14879
- sourcemaps
14880
- } = context;
14881
- const {
14882
- babelHelpersChunk = true,
14883
- include,
14884
- preserveDynamicImport = false,
14885
- strictExports = false
14886
- } = options;
14887
- const {
14888
- jsModuleBundleUrlInfos
14889
- } = await buildWithRollup({
14890
- signal,
14891
- logger,
14892
- rootDirectoryUrl,
14893
- buildDirectoryUrl,
14894
- assetsDirectory,
14895
- urlGraph,
14896
- jsModuleUrlInfos,
14897
- runtimeCompat,
14898
- sourcemaps,
14899
- include,
14900
- babelHelpersChunk,
14901
- preserveDynamicImport,
14902
- strictExports
14903
- });
14904
- return jsModuleBundleUrlInfos;
14905
- };
14906
- const rollupPluginJsenv = ({
14907
- // logger,
14908
- rootDirectoryUrl,
14909
- buildDirectoryUrl,
14910
- assetsDirectory,
14911
- urlGraph,
14912
- jsModuleUrlInfos,
14913
- sourcemaps,
14914
- include,
14915
- babelHelpersChunk,
14916
- preserveDynamicImport,
14917
- strictExports,
14918
- resultRef
14919
- }) => {
14920
- let _rollupEmitFile = () => {
14921
- throw new Error("not implemented");
14922
- };
14923
- const format = jsModuleUrlInfos.some(jsModuleUrlInfo => jsModuleUrlInfo.filename.endsWith(".cjs")) ? "cjs" : "esm";
14924
- const emitChunk = chunk => {
14925
- return _rollupEmitFile({
14926
- type: "chunk",
14927
- ...chunk
14928
- });
14929
- };
14930
- let importCanBeBundled = () => true;
14931
- if (include) {
14932
- const associations = URL_META.resolveAssociations({
14933
- bundle: include
14934
- }, rootDirectoryUrl);
14935
- importCanBeBundled = url => {
14936
- return URL_META.applyAssociations({
14937
- url,
14938
- associations
14939
- }).bundle;
14940
- };
14941
- }
14942
- const urlImporters = {};
14943
- return {
14944
- name: "jsenv",
14945
- async buildStart() {
14946
- _rollupEmitFile = (...args) => this.emitFile(...args);
14947
- let previousNonEntryPointModuleId;
14948
- jsModuleUrlInfos.forEach(jsModuleUrlInfo => {
14949
- const id = jsModuleUrlInfo.url;
14950
- if (jsModuleUrlInfo.isEntryPoint) {
14951
- emitChunk({
14952
- id
14953
- });
14954
- return;
14955
- }
14956
- emitChunk({
14957
- id,
14958
- implicitlyLoadedAfterOneOf: previousNonEntryPointModuleId ? [previousNonEntryPointModuleId] : null,
14959
- preserveSignature: strictExports ? "strict" : jsModuleUrlInfo.dependents.size < 2 ? "allow-extension" : "strict"
14960
- });
14961
- previousNonEntryPointModuleId = id;
14962
- });
14963
- },
14964
- async generateBundle(outputOptions, rollupResult) {
14965
- _rollupEmitFile = (...args) => this.emitFile(...args);
14966
- const jsModuleBundleUrlInfos = {};
14967
- Object.keys(rollupResult).forEach(fileName => {
14968
- const rollupFileInfo = rollupResult[fileName];
14969
- // there is 3 types of file: "placeholder", "asset", "chunk"
14970
- if (rollupFileInfo.type === "chunk") {
14971
- const sourceUrls = Object.keys(rollupFileInfo.modules).map(id => fileUrlConverter.asFileUrl(id));
14972
- let url;
14973
- let originalUrl;
14974
- if (rollupFileInfo.facadeModuleId) {
14975
- url = fileUrlConverter.asFileUrl(rollupFileInfo.facadeModuleId);
14976
- originalUrl = url;
14977
- } else {
14978
- url = new URL(rollupFileInfo.fileName, buildDirectoryUrl).href;
14979
- if (rollupFileInfo.isDynamicEntry) {
14980
- originalUrl = sourceUrls[sourceUrls.length - 1];
14981
- } else {
14982
- originalUrl = url;
14983
- }
14984
- }
14985
- const jsModuleBundleUrlInfo = {
14986
- url,
14987
- originalUrl,
14988
- type: format === "esm" ? "js_module" : "common_js",
14989
- data: {
14990
- bundlerName: "rollup",
14991
- bundleRelativeUrl: rollupFileInfo.fileName,
14992
- usesImport: rollupFileInfo.imports.length > 0 || rollupFileInfo.dynamicImports.length > 0,
14993
- isDynamicEntry: rollupFileInfo.isDynamicEntry
14994
- },
14995
- sourceUrls,
14996
- contentType: "text/javascript",
14997
- content: rollupFileInfo.code,
14998
- sourcemap: rollupFileInfo.map
14999
- };
15000
- jsModuleBundleUrlInfos[url] = jsModuleBundleUrlInfo;
15001
- }
15002
- });
15003
- resultRef.current = {
15004
- jsModuleBundleUrlInfos
15005
- };
15006
- },
15007
- outputOptions: outputOptions => {
15008
- // const sourcemapFile = buildDirectoryUrl
15009
- Object.assign(outputOptions, {
15010
- format,
15011
- dir: fileUrlConverter.asFilePath(buildDirectoryUrl),
15012
- sourcemap: sourcemaps === "file" || sourcemaps === "inline",
15013
- // sourcemapFile,
15014
- sourcemapPathTransform: relativePath => {
15015
- return new URL(relativePath, buildDirectoryUrl).href;
15016
- },
15017
- entryFileNames: () => {
15018
- return `[name].js`;
15019
- },
15020
- chunkFileNames: chunkInfo => {
15021
- const insideJs = willBeInsideJsDirectory({
15022
- chunkInfo,
15023
- fileUrlConverter,
15024
- jsModuleUrlInfos
15025
- });
15026
- let nameFromUrlInfo;
15027
- if (chunkInfo.facadeModuleId) {
15028
- const url = fileUrlConverter.asFileUrl(chunkInfo.facadeModuleId);
15029
- const urlInfo = jsModuleUrlInfos.find(jsModuleUrlInfo => jsModuleUrlInfo.url === url);
15030
- if (urlInfo) {
15031
- nameFromUrlInfo = urlInfo.filename;
15032
- }
15033
- }
15034
- const name = nameFromUrlInfo || `${chunkInfo.name}.js`;
15035
- return insideJs ? `${assetsDirectory}js/${name}` : `${name}`;
15036
- },
15037
- manualChunks: id => {
15038
- if (babelHelpersChunk) {
15039
- const fileUrl = fileUrlConverter.asFileUrl(id);
15040
- if (fileUrl.endsWith("babel-plugin-transform-async-to-promises/helpers.mjs")) {
15041
- return "babel_helpers";
15042
- }
15043
- if (babelHelperNameFromUrl(fileUrl)) {
15044
- return "babel_helpers";
15045
- }
15046
- if (fileUrl === globalThisClientFileUrl) {
15047
- return "babel_helpers";
15048
- }
15049
- if (fileUrl === newStylesheetClientFileUrl) {
15050
- return "babel_helpers";
15051
- }
15052
- if (fileUrl === regeneratorRuntimeClientFileUrl) {
15053
- return "babel_helpers";
15054
- }
15055
- }
15056
- return null;
15057
- }
15058
- // https://rollupjs.org/guide/en/#outputpaths
15059
- // paths: (id) => {
15060
- // return id
15061
- // },
15062
- });
15063
- },
15064
-
15065
- // https://rollupjs.org/guide/en/#resolvedynamicimport
15066
- resolveDynamicImport: (specifier, importer) => {
15067
- if (preserveDynamicImport) {
15068
- let urlObject;
15069
- if (specifier[0] === "/") {
15070
- urlObject = new URL(specifier.slice(1), rootDirectoryUrl);
15071
- } else {
15072
- if (isFileSystemPath$1(importer)) {
15073
- importer = fileUrlConverter.asFileUrl(importer);
15074
- }
15075
- urlObject = new URL(specifier, importer);
15076
- }
15077
- urlObject.searchParams.set("as_js_classic_library", "");
15078
- return {
15079
- external: true,
15080
- id: urlObject.href
15081
- };
15082
- }
15083
- return null;
15084
- },
15085
- resolveId: (specifier, importer = rootDirectoryUrl) => {
15086
- if (isFileSystemPath$1(importer)) {
15087
- importer = fileUrlConverter.asFileUrl(importer);
15088
- }
15089
- let url;
15090
- if (specifier[0] === "/") {
15091
- url = new URL(specifier.slice(1), rootDirectoryUrl).href;
15092
- } else {
15093
- url = new URL(specifier, importer).href;
15094
- }
15095
- const existingImporter = urlImporters[url];
15096
- if (!existingImporter) {
15097
- urlImporters[url] = importer;
15098
- }
15099
- if (!url.startsWith("file:")) {
15100
- return {
15101
- id: url,
15102
- external: true
15103
- };
15104
- }
15105
- if (!importCanBeBundled(url)) {
15106
- return {
15107
- id: url,
15108
- external: true
15109
- };
15110
- }
15111
- const urlInfo = urlGraph.getUrlInfo(url);
15112
- if (!urlInfo) {
15113
- // happen when excluded by urlAnalysis.include
15114
- return {
15115
- id: url,
15116
- external: true
15117
- };
15118
- }
15119
- if (!urlInfo.shouldHandle) {
15120
- return {
15121
- id: url,
15122
- external: true
15123
- };
15124
- }
15125
- const filePath = fileUrlConverter.asFilePath(url);
15126
- return filePath;
15127
- },
15128
- async load(rollupId) {
15129
- const fileUrl = fileUrlConverter.asFileUrl(rollupId);
15130
- const urlInfo = urlGraph.getUrlInfo(fileUrl);
15131
- return {
15132
- code: urlInfo.content,
15133
- map: (sourcemaps === "file" || sourcemaps === "inline") && urlInfo.sourcemap ? sourcemapConverter.toFilePaths(urlInfo.sourcemap) : null
15134
- };
15135
- }
15136
- };
15137
- };
15138
- const buildWithRollup = async ({
15139
- signal,
15140
- logger,
15141
- rootDirectoryUrl,
15142
- buildDirectoryUrl,
15143
- assetsDirectory,
15144
- urlGraph,
15145
- jsModuleUrlInfos,
15146
- runtimeCompat,
15147
- sourcemaps,
15148
- include,
15149
- babelHelpersChunk,
15150
- preserveDynamicImport
15151
- }) => {
15152
- const resultRef = {
15153
- current: null
15154
- };
15155
- try {
15156
- await applyRollupPlugins({
15157
- rollupPlugins: [rollupPluginJsenv({
15158
- signal,
15159
- logger,
15160
- rootDirectoryUrl,
15161
- buildDirectoryUrl,
15162
- assetsDirectory,
15163
- urlGraph,
15164
- jsModuleUrlInfos,
15165
- runtimeCompat,
15166
- sourcemaps,
15167
- include,
15168
- babelHelpersChunk,
15169
- preserveDynamicImport,
15170
- resultRef
15171
- })],
15172
- inputOptions: {
15173
- input: [],
15174
- onwarn: warning => {
15175
- if (warning.code === "CIRCULAR_DEPENDENCY") {
15176
- return;
15177
- }
15178
- if (warning.code === "THIS_IS_UNDEFINED" && pathToFileURL(warning.id).href === globalThisClientFileUrl) {
15179
- return;
15180
- }
15181
- if (warning.code === "EVAL") {
15182
- // ideally we should disable only for jsenv files
15183
- return;
15184
- }
15185
- logger.warn(String(warning));
15186
- }
15187
- }
15188
- });
15189
- return resultRef.current;
15190
- } catch (e) {
15191
- if (e.code === "MISSING_EXPORT") {
15192
- const detailedMessage = createDetailedMessage$1(e.message, {
15193
- frame: e.frame
15194
- });
15195
- throw new Error(detailedMessage, {
15196
- cause: e
15197
- });
15198
- }
15199
- throw e;
15200
- }
15201
- };
15202
- const applyRollupPlugins = async ({
15203
- rollupPlugins,
15204
- inputOptions = {},
15205
- outputOptions = {}
15206
- }) => {
15207
- const {
15208
- rollup
15209
- } = await import("rollup");
15210
- const {
15211
- importAssertions
15212
- } = await import("acorn-import-assertions");
15213
- const rollupReturnValue = await rollup({
15214
- ...inputOptions,
15215
- plugins: rollupPlugins,
15216
- acornInjectPlugins: [importAssertions, ...(inputOptions.acornInjectPlugins || [])]
15217
- });
15218
- const rollupOutputArray = await rollupReturnValue.generate(outputOptions);
15219
- return rollupOutputArray;
15220
- };
15221
- const willBeInsideJsDirectory = ({
15222
- chunkInfo,
15223
- fileUrlConverter,
15224
- jsModuleUrlInfos
15225
- }) => {
15226
- // if the chunk is generated dynamically by rollup
15227
- // for an entry point jsenv will put that file inside js/ directory
15228
- // if it's generated dynamically for a file already in js/ directory
15229
- // both will be inside the js/ directory
15230
- if (!chunkInfo.facadeModuleId) {
15231
- // generated by rollup
15232
- return true;
15233
- }
15234
- const url = fileUrlConverter.asFileUrl(chunkInfo.facadeModuleId);
15235
- const jsModuleUrlInfo = jsModuleUrlInfos.find(jsModuleUrlInfo => jsModuleUrlInfo.url === url);
15236
- if (!jsModuleUrlInfo) {
15237
- // generated by rollup
15238
- return true;
15239
- }
15240
- if (!jsModuleUrlInfo.isEntryPoint) {
15241
- // not an entry point, jsenv will put it inside js/ directory
15242
- return true;
15243
- }
15244
- return false;
15245
- };
15246
-
15247
14829
  const jsenvPluginAsJsClassicLibrary = ({
15248
14830
  systemJsInjection,
15249
14831
  systemJsClientFileUrl,
@@ -18566,6 +18148,30 @@ const babelPluginInstrument = (api, {
18566
18148
  };
18567
18149
  };
18568
18150
 
18151
+ /*
18152
+ * Generated helpers
18153
+ * - https://github.com/babel/babel/commits/main/packages/babel-helpers/src/helpers.ts
18154
+ * File helpers
18155
+ * - https://github.com/babel/babel/tree/main/packages/babel-helpers/src/helpers
18156
+ *
18157
+ */
18158
+ const babelHelperClientDirectoryUrl = new URL("./babel_helpers/", import.meta.url).href;
18159
+
18160
+ // we cannot use "@jsenv/core/src/*" because babel helper might be injected
18161
+ // into node_modules not depending on "@jsenv/core"
18162
+ const getBabelHelperFileUrl = babelHelperName => {
18163
+ const babelHelperFileUrl = new URL(`./${babelHelperName}/${babelHelperName}.js`, babelHelperClientDirectoryUrl).href;
18164
+ return babelHelperFileUrl;
18165
+ };
18166
+ const babelHelperNameFromUrl = url => {
18167
+ if (!url.startsWith(babelHelperClientDirectoryUrl)) {
18168
+ return null;
18169
+ }
18170
+ const afterBabelHelperDirectory = url.slice(babelHelperClientDirectoryUrl.length);
18171
+ const babelHelperName = afterBabelHelperDirectory.slice(0, afterBabelHelperDirectory.indexOf("/"));
18172
+ return babelHelperName;
18173
+ };
18174
+
18569
18175
  /* eslint-disable camelcase */
18570
18176
  // copied from
18571
18177
  // https://github.com/babel/babel/blob/e498bee10f0123bb208baa228ce6417542a2c3c4/packages/babel-compat-data/data/plugins.json#L1
@@ -19157,10 +18763,10 @@ const babelPluginBabelHelpersAsJsenvImports = (babel, {
19157
18763
  };
19158
18764
  };
19159
18765
 
18766
+ const newStylesheetClientFileUrl = new URL("./js/new_stylesheet.js", import.meta.url).href;
19160
18767
  const babelPluginNewStylesheetAsJsenvImport = (babel, {
19161
18768
  getImportSpecifier
19162
18769
  }) => {
19163
- const newStylesheetClientFileUrl = new URL("./js/new_stylesheet.js", import.meta.url).href;
19164
18770
  return {
19165
18771
  name: "new-stylesheet-as-jsenv-import",
19166
18772
  visitor: {
@@ -19269,10 +18875,10 @@ const getImportAssertionsDescriptor = importAssertions => {
19269
18875
  return importAssertionsDescriptor;
19270
18876
  };
19271
18877
 
18878
+ const globalThisClientFileUrl = new URL("./js/global_this.js", import.meta.url).href;
19272
18879
  const babelPluginGlobalThisAsJsenvImport = (babel, {
19273
18880
  getImportSpecifier
19274
18881
  }) => {
19275
- const globalThisClientFileUrl = new URL("./js/global_this.js", import.meta.url).href;
19276
18882
  return {
19277
18883
  name: "global-this-as-jsenv-import",
19278
18884
  visitor: {
@@ -19300,10 +18906,10 @@ const babelPluginGlobalThisAsJsenvImport = (babel, {
19300
18906
  };
19301
18907
  };
19302
18908
 
18909
+ const regeneratorRuntimeClientFileUrl = new URL("./js/regenerator_runtime.js", import.meta.url).href;
19303
18910
  const babelPluginRegeneratorRuntimeAsJsenvImport = (babel, {
19304
18911
  getImportSpecifier
19305
18912
  }) => {
19306
- const regeneratorRuntimeClientFileUrl = new URL("./js/regenerator_runtime.js", import.meta.url).href;
19307
18913
  return {
19308
18914
  name: "regenerator-runtime-as-jsenv-import",
19309
18915
  visitor: {
@@ -19410,6 +19016,17 @@ const jsenvPluginBabel = ({
19410
19016
  return {
19411
19017
  name: "jsenv:babel",
19412
19018
  appliesDuring: "*",
19019
+ transformUrlContent: urlInfo => {
19020
+ if (urlInfo.url === regeneratorRuntimeClientFileUrl) {
19021
+ urlInfo.data.isBabelClientFile = true;
19022
+ }
19023
+ if (urlInfo.url === globalThisClientFileUrl) {
19024
+ urlInfo.data.isBabelClientFile = true;
19025
+ }
19026
+ if (urlInfo.url === newStylesheetClientFileUrl) {
19027
+ urlInfo.data.isBabelClientFile = true;
19028
+ }
19029
+ },
19413
19030
  finalizeUrlContent: {
19414
19031
  js_classic: transformWithBabel,
19415
19032
  js_module: transformWithBabel
@@ -19602,368 +19219,6 @@ const jsenvPluginNodeRuntime = ({
19602
19219
  };
19603
19220
  };
19604
19221
 
19605
- const sortByDependencies = nodes => {
19606
- const visited = [];
19607
- const sorted = [];
19608
- const circular = [];
19609
- const visit = url => {
19610
- const isSorted = sorted.includes(url);
19611
- if (isSorted) {
19612
- return;
19613
- }
19614
- const isVisited = visited.includes(url);
19615
- if (isVisited) {
19616
- if (!circular.includes(url)) {
19617
- circular.push(url);
19618
- }
19619
- } else {
19620
- visited.push(url);
19621
- nodes[url].dependencies.forEach(dependencyUrl => {
19622
- visit(dependencyUrl);
19623
- });
19624
- sorted.push(url);
19625
- }
19626
- };
19627
- Object.keys(nodes).forEach(url => {
19628
- visit(url);
19629
- });
19630
- sorted.circular = circular;
19631
- return sorted;
19632
- };
19633
-
19634
- /*
19635
- * Each @import found in css is replaced by the file content
19636
- * - There is no need to worry about urls (such as background-image: url())
19637
- * because they are absolute (file://*) and will be made relative again by jsenv build
19638
- * - The sourcemap are not generated but ideally they should be
19639
- * It can be quite challenging, see "bundle_sourcemap.js"
19640
- */
19641
-
19642
- // Do not use until https://github.com/parcel-bundler/parcel-css/issues/181
19643
- const bundleCss = async ({
19644
- cssUrlInfos,
19645
- context
19646
- }) => {
19647
- const bundledCssUrlInfos = {};
19648
- const cssBundleInfos = await performCssBundling({
19649
- cssEntryUrlInfos: cssUrlInfos,
19650
- context
19651
- });
19652
- cssUrlInfos.forEach(cssUrlInfo => {
19653
- bundledCssUrlInfos[cssUrlInfo.url] = {
19654
- data: {
19655
- bundlerName: "parcel"
19656
- },
19657
- contentType: "text/css",
19658
- content: cssBundleInfos[cssUrlInfo.url].bundleContent
19659
- };
19660
- });
19661
- return bundledCssUrlInfos;
19662
- };
19663
- const performCssBundling = async ({
19664
- cssEntryUrlInfos,
19665
- context
19666
- }) => {
19667
- const cssBundleInfos = await loadCssUrls({
19668
- cssEntryUrlInfos,
19669
- context
19670
- });
19671
- const cssUrlsSorted = sortByDependencies(cssBundleInfos);
19672
- cssUrlsSorted.forEach(cssUrl => {
19673
- const cssBundleInfo = cssBundleInfos[cssUrl];
19674
- const magicSource = createMagicSource(cssBundleInfo.content);
19675
- cssBundleInfo.cssUrls.forEach(cssUrl => {
19676
- if (cssUrl.type === "@import") {
19677
- magicSource.replace({
19678
- start: cssUrl.atRuleStart,
19679
- end: cssUrl.atRuleEnd,
19680
- replacement: cssBundleInfos[cssUrl.url].bundleContent
19681
- });
19682
- }
19683
- });
19684
- const {
19685
- content
19686
- } = magicSource.toContentAndSourcemap();
19687
- cssBundleInfo.bundleContent = content.trim();
19688
- });
19689
- return cssBundleInfos;
19690
- };
19691
- const parseCssUrls = async ({
19692
- css,
19693
- url
19694
- }) => {
19695
- const cssUrls = [];
19696
- await applyPostCss({
19697
- sourcemaps: false,
19698
- plugins: [postCssPluginUrlVisitor({
19699
- urlVisitor: ({
19700
- type,
19701
- specifier,
19702
- specifierStart,
19703
- specifierEnd,
19704
- atRuleStart,
19705
- atRuleEnd
19706
- }) => {
19707
- cssUrls.push({
19708
- type,
19709
- url: new URL(specifier, url).href,
19710
- specifierStart,
19711
- specifierEnd,
19712
- atRuleStart,
19713
- atRuleEnd
19714
- });
19715
- }
19716
- })],
19717
- url,
19718
- content: css
19719
- });
19720
- return cssUrls;
19721
- };
19722
- const loadCssUrls = async ({
19723
- cssEntryUrlInfos,
19724
- context
19725
- }) => {
19726
- const cssBundleInfos = {};
19727
- const promises = [];
19728
- const promiseMap = new Map();
19729
- const load = cssUrlInfo => {
19730
- const promiseFromData = promiseMap.get(cssUrlInfo.url);
19731
- if (promiseFromData) return promiseFromData;
19732
- const promise = _load(cssUrlInfo);
19733
- promises.push(promise);
19734
- promiseMap.set(cssUrlInfo.url, promise);
19735
- return promise;
19736
- };
19737
- const _load = async cssUrlInfo => {
19738
- const cssUrls = await parseCssUrls({
19739
- css: cssUrlInfo.content,
19740
- url: cssUrlInfo.url
19741
- });
19742
- const cssBundleInfo = {
19743
- content: cssUrlInfo.content,
19744
- cssUrls,
19745
- dependencies: []
19746
- };
19747
- cssBundleInfos[cssUrlInfo.url] = cssBundleInfo;
19748
- cssUrls.forEach(cssUrl => {
19749
- if (cssUrl.type === "@import") {
19750
- cssBundleInfo.dependencies.push(cssUrl.url);
19751
- const importedCssUrlInfo = context.urlGraph.getUrlInfo(cssUrl.url);
19752
- load(importedCssUrlInfo);
19753
- }
19754
- });
19755
- };
19756
- cssEntryUrlInfos.forEach(cssEntryUrlInfo => {
19757
- load(cssEntryUrlInfo);
19758
- });
19759
- const waitAll = async () => {
19760
- if (promises.length === 0) {
19761
- return;
19762
- }
19763
- const promisesToWait = promises.slice();
19764
- promises.length = 0;
19765
- await Promise.all(promisesToWait);
19766
- await waitAll();
19767
- };
19768
- await waitAll();
19769
- promiseMap.clear();
19770
- return cssBundleInfos;
19771
- };
19772
-
19773
- /*
19774
- * TODO:
19775
- * for each js_classic where subtype is a worker
19776
- * take the url info and find importScripts calls
19777
- * and replace them with the corresponding url info file content
19778
- * we'll ikely need to save the importScripts node location to be able to do that
19779
- */
19780
-
19781
- // import { createMagicSource } from "@jsenv/utils/sourcemap/magic_source.js"
19782
-
19783
- const bundleJsClassicWorkers = () => {
19784
- return {};
19785
- };
19786
-
19787
- const jsenvPluginBundling = bundling => {
19788
- if (typeof bundling === "boolean") {
19789
- bundling = {
19790
- css: bundling,
19791
- js_classic_workers: bundling,
19792
- js_module: bundling
19793
- };
19794
- } else if (typeof bundling !== "object") {
19795
- throw new Error(`bundling must be a boolean or an object, got ${bundling}`);
19796
- }
19797
- Object.keys(bundling).forEach(key => {
19798
- if (bundling[key] === true) bundling[key] = {};
19799
- });
19800
- return {
19801
- name: "jsenv:bundling",
19802
- appliesDuring: "build",
19803
- bundle: {
19804
- css: bundling.css ? (cssUrlInfos, context) => {
19805
- return bundleCss({
19806
- cssUrlInfos,
19807
- context,
19808
- options: bundling.css
19809
- });
19810
- } : undefined,
19811
- js_classic: bundling.js_classic ? (jsClassicUrlInfos, context) => {
19812
- return bundleJsClassicWorkers({
19813
- jsClassicUrlInfos,
19814
- context,
19815
- options: bundling.js_classic_workers
19816
- });
19817
- } : undefined,
19818
- js_module: bundling.js_module ? (jsModuleUrlInfos, context) => {
19819
- return bundleJsModules({
19820
- jsModuleUrlInfos,
19821
- context,
19822
- options: bundling.js_module
19823
- });
19824
- } : undefined
19825
- }
19826
- };
19827
- };
19828
-
19829
- // https://github.com/kangax/html-minifier#options-quick-reference
19830
- const minifyHtml = ({
19831
- htmlUrlInfo,
19832
- options
19833
- } = {}) => {
19834
- const {
19835
- collapseWhitespace = true,
19836
- removeComments = true
19837
- } = options;
19838
- const {
19839
- minify
19840
- } = requireFromJsenv("html-minifier");
19841
- const htmlMinified = minify(htmlUrlInfo.content, {
19842
- collapseWhitespace,
19843
- removeComments
19844
- });
19845
- return htmlMinified;
19846
- };
19847
-
19848
- const minifyCss = ({
19849
- cssUrlInfo,
19850
- context
19851
- }) => {
19852
- const {
19853
- code,
19854
- map
19855
- } = minifyWithParcel(cssUrlInfo, context);
19856
- return {
19857
- content: String(code),
19858
- sourcemap: map
19859
- };
19860
- };
19861
-
19862
- // https://github.com/terser-js/terser#minify-options
19863
-
19864
- const minifyJs = async ({
19865
- jsUrlInfo,
19866
- options
19867
- }) => {
19868
- const url = jsUrlInfo.url;
19869
- const content = jsUrlInfo.content;
19870
- const sourcemap = jsUrlInfo.sourcemap;
19871
- const isJsModule = jsUrlInfo.type === "js_module";
19872
- const {
19873
- minify
19874
- } = await import("terser");
19875
- const terserResult = await minify({
19876
- [url]: content
19877
- }, {
19878
- sourceMap: {
19879
- ...(sourcemap ? {
19880
- content: JSON.stringify(sourcemap)
19881
- } : {}),
19882
- asObject: true,
19883
- includeSources: true
19884
- },
19885
- module: isJsModule,
19886
- // We need to preserve "new InlineContent()" calls to be able to recognize them
19887
- // after minification in order to version urls inside inline content text
19888
- keep_fnames: /InlineContent/,
19889
- ...options
19890
- });
19891
- return {
19892
- content: terserResult.code,
19893
- sourcemap: terserResult.map
19894
- };
19895
- };
19896
-
19897
- const minifyJson = ({
19898
- jsonUrlInfo
19899
- }) => {
19900
- const {
19901
- content
19902
- } = jsonUrlInfo;
19903
- if (content.startsWith("{\n")) {
19904
- const jsonWithoutWhitespaces = JSON.stringify(JSON.parse(content));
19905
- return jsonWithoutWhitespaces;
19906
- }
19907
- return null;
19908
- };
19909
-
19910
- const jsenvPluginMinification = minification => {
19911
- if (typeof minification === "boolean") {
19912
- minification = {
19913
- html: minification,
19914
- css: minification,
19915
- js_classic: minification,
19916
- js_module: minification,
19917
- json: minification,
19918
- svg: minification
19919
- };
19920
- } else if (typeof minification !== "object") {
19921
- throw new Error(`minification must be a boolean or an object, got ${minification}`);
19922
- }
19923
- Object.keys(minification).forEach(key => {
19924
- if (minification[key] === true) minification[key] = {};
19925
- });
19926
- const htmlOptimizer = minification.html ? (urlInfo, context) => minifyHtml({
19927
- htmlUrlInfo: urlInfo,
19928
- context,
19929
- options: minification.html
19930
- }) : null;
19931
- const jsonOptimizer = minification.json ? (urlInfo, context) => minifyJson({
19932
- jsonUrlInfo: urlInfo,
19933
- context,
19934
- options: minification.json
19935
- }) : null;
19936
- const cssOptimizer = minification.css ? (urlInfo, context) => minifyCss({
19937
- cssUrlInfo: urlInfo,
19938
- context,
19939
- options: minification.css
19940
- }) : null;
19941
- const jsClassicOptimizer = minification.js_classic ? (urlInfo, context) => minifyJs({
19942
- jsUrlInfo: urlInfo,
19943
- context,
19944
- options: minification.js_classic
19945
- }) : null;
19946
- const jsModuleOptimizer = minification.js_module ? (urlInfo, context) => minifyJs({
19947
- jsUrlInfo: urlInfo,
19948
- context,
19949
- options: minification.js_module
19950
- }) : null;
19951
- return {
19952
- name: "jsenv:minification",
19953
- appliesDuring: "build",
19954
- optimizeUrlContent: {
19955
- html: htmlOptimizer,
19956
- svg: htmlOptimizer,
19957
- css: cssOptimizer,
19958
- js_classic: jsClassicOptimizer,
19959
- js_module: jsModuleOptimizer,
19960
- json: jsonOptimizer,
19961
- importmap: jsonOptimizer,
19962
- webmanifest: jsonOptimizer
19963
- }
19964
- };
19965
- };
19966
-
19967
19222
  // Some "smart" default applied to decide what should hot reload / fullreload:
19968
19223
  // By default:
19969
19224
  // - hot reload on <img src="./image.png" />
@@ -20747,8 +20002,6 @@ const getCorePlugins = ({
20747
20002
  directoryReferenceAllowed,
20748
20003
  supervisor,
20749
20004
  transpilation = true,
20750
- minification = false,
20751
- bundling = false,
20752
20005
  clientMainFileUrl,
20753
20006
  clientAutoreload = false,
20754
20007
  clientFileChangeCallbackList,
@@ -20795,7 +20048,7 @@ const getCorePlugins = ({
20795
20048
  urlResolution
20796
20049
  }), jsenvPluginUrlVersion(), jsenvPluginCommonJsGlobals(), jsenvPluginImportMetaScenarios(), jsenvPluginNodeRuntime({
20797
20050
  runtimeCompat
20798
- }), jsenvPluginBundling(bundling), jsenvPluginMinification(minification), jsenvPluginImportMetaHot(), ...(clientAutoreload ? [jsenvPluginAutoreload({
20051
+ }), jsenvPluginImportMetaHot(), ...(clientAutoreload ? [jsenvPluginAutoreload({
20799
20052
  ...clientAutoreload,
20800
20053
  clientFileChangeCallbackList,
20801
20054
  clientFilesPruneCallbackList
@@ -21158,8 +20411,6 @@ const defaultRuntimeCompat = {
21158
20411
  * Directory where asset files will be written
21159
20412
  * @param {string|url} [buildParameters.base=""]
21160
20413
  * Urls in build file contents will be prefixed with this string
21161
- * @param {boolean|object} [buildParameters.minification=true]
21162
- * Minify build file contents
21163
20414
  * @param {boolean} [buildParameters.versioning=true]
21164
20415
  * Controls if url in build file contents are versioned
21165
20416
  * @param {('search_param'|'filename')} [buildParameters.versioningMethod="search_param"]
@@ -21192,8 +20443,6 @@ const build = async ({
21192
20443
  fileSystemMagicRedirection,
21193
20444
  directoryReferenceAllowed,
21194
20445
  transpilation = {},
21195
- bundling = true,
21196
- minification = !runtimeCompat.node,
21197
20446
  versioning = !runtimeCompat.node,
21198
20447
  versioningMethod = "search_param",
21199
20448
  // "filename", "search_param"
@@ -21305,9 +20554,7 @@ build ${entryPointKeys.length} entry points`);
21305
20554
  ...transpilation,
21306
20555
  babelHelpersAsImport: !useExplicitJsClassicConversion,
21307
20556
  jsClassicFallback: false
21308
- },
21309
- minification,
21310
- bundling
20557
+ }
21311
20558
  })],
21312
20559
  sourcemaps,
21313
20560
  sourcemapsSourcesContent,
@@ -22079,7 +21326,7 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
22079
21326
  urlInfo,
22080
21327
  kitchen: finalGraphKitchen,
22081
21328
  versionMappings: versionMappingsNeeded,
22082
- minification
21329
+ minification: plugins.some(plugin => plugin.name === "jsenv:minification")
22083
21330
  });
22084
21331
  });
22085
21332
  }
@@ -22285,8 +21532,15 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
22285
21532
  }
22286
21533
  }
22287
21534
  const buildManifest = {};
22288
- const buildFileContents = {};
22289
- const buildInlineContents = {};
21535
+ const buildContents = {};
21536
+ const buildInlineRelativeUrls = [];
21537
+ const getBuildRelativeUrl = url => {
21538
+ const urlObject = new URL(url);
21539
+ urlObject.searchParams.delete("as_js_classic");
21540
+ url = urlObject.href;
21541
+ const buildRelativeUrl = urlToRelativeUrl(url, buildDirectoryUrl);
21542
+ return buildRelativeUrl;
21543
+ };
22290
21544
  GRAPH.forEach(finalGraph, urlInfo => {
22291
21545
  if (!urlInfo.shouldHandle) {
22292
21546
  return;
@@ -22298,21 +21552,35 @@ ${ANSI.color(buildUrl, ANSI.MAGENTA)}
22298
21552
  return;
22299
21553
  }
22300
21554
  if (urlInfo.isInline) {
22301
- const buildRelativeUrl = urlToRelativeUrl(urlInfo.url, buildDirectoryUrl);
22302
- buildInlineContents[buildRelativeUrl] = urlInfo.content;
21555
+ const buildRelativeUrl = getBuildRelativeUrl(urlInfo.url);
21556
+ buildContents[buildRelativeUrl] = urlInfo.content;
21557
+ buildInlineRelativeUrls.push(buildRelativeUrl);
22303
21558
  } else {
22304
21559
  const versionedUrl = versionedUrlMap.get(urlInfo.url);
22305
21560
  if (versionedUrl && canUseVersionedUrl(urlInfo)) {
22306
- const buildRelativeUrl = urlToRelativeUrl(urlInfo.url, buildDirectoryUrl);
22307
- const versionedBuildRelativeUrl = urlToRelativeUrl(versionedUrl, buildDirectoryUrl);
22308
- buildFileContents[versionedBuildRelativeUrl] = urlInfo.content;
21561
+ const buildRelativeUrl = getBuildRelativeUrl(urlInfo.url);
21562
+ const versionedBuildRelativeUrl = getBuildRelativeUrl(versionedUrl);
21563
+ if (versioningMethod === "search_param") {
21564
+ buildContents[buildRelativeUrl] = urlInfo.content;
21565
+ } else {
21566
+ buildContents[versionedBuildRelativeUrl] = urlInfo.content;
21567
+ }
22309
21568
  buildManifest[buildRelativeUrl] = versionedBuildRelativeUrl;
22310
21569
  } else {
22311
- const buildRelativeUrl = urlToRelativeUrl(urlInfo.url, buildDirectoryUrl);
22312
- buildFileContents[buildRelativeUrl] = urlInfo.content;
21570
+ const buildRelativeUrl = getBuildRelativeUrl(urlInfo.url);
21571
+ buildContents[buildRelativeUrl] = urlInfo.content;
22313
21572
  }
22314
21573
  }
22315
21574
  });
21575
+ const buildFileContents = {};
21576
+ const buildInlineContents = {};
21577
+ Object.keys(buildContents).sort((a, b) => comparePathnames(a, b)).forEach(buildRelativeUrl => {
21578
+ if (buildInlineRelativeUrls.includes(buildRelativeUrl)) {
21579
+ buildInlineContents[buildRelativeUrl] = buildContents[buildRelativeUrl];
21580
+ } else {
21581
+ buildFileContents[buildRelativeUrl] = buildContents[buildRelativeUrl];
21582
+ }
21583
+ });
22316
21584
  if (writeOnFileSystem) {
22317
21585
  if (directoryToClean) {
22318
21586
  await ensureEmptyDirectory(directoryToClean);