@rsbuild/core 1.6.12 → 1.6.14

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/131.js CHANGED
@@ -10,14 +10,14 @@ import * as __rspack_external_path from "path";
10
10
  import * as __rspack_external_url from "url";
11
11
  import { __webpack_require__ } from "./rslib-runtime.js";
12
12
  import { EventEmitter } from "events";
13
+ import { promisify as external_node_util_promisify, stripVTControlCharacters } from "node:util";
13
14
  import node_fs, { existsSync } from "node:fs";
14
15
  import node_os, { constants as external_node_os_constants } from "node:os";
15
16
  import node_process from "node:process";
16
17
  import { isPromise, isRegExp } from "node:util/types";
17
- import { promisify as external_node_util_promisify } from "node:util";
18
18
  import node_zlib from "node:zlib";
19
19
  __webpack_require__.add({
20
- "../../node_modules/.pnpm/deepmerge@4.3.1/node_modules/deepmerge/dist/cjs.js": function(module) {
20
+ "../../node_modules/.pnpm/deepmerge@4.3.1/node_modules/deepmerge/dist/cjs.js" (module) {
21
21
  var isMergeableObject = function isMergeableObject(value) {
22
22
  return isNonNullObject(value) && !isSpecial(value);
23
23
  };
@@ -86,7 +86,7 @@ __webpack_require__.add({
86
86
  }, {});
87
87
  }, module.exports = deepmerge;
88
88
  },
89
- "../../node_modules/.pnpm/dotenv-expand@12.0.3/node_modules/dotenv-expand/lib/main.js": function(module) {
89
+ "../../node_modules/.pnpm/dotenv-expand@12.0.3/node_modules/dotenv-expand/lib/main.js" (module) {
90
90
  function _resolveEscapeSequences(value) {
91
91
  return value.replace(/\\\$/g, '$');
92
92
  }
@@ -118,7 +118,7 @@ __webpack_require__.add({
118
118
  }
119
119
  module.exports.expand = expand;
120
120
  },
121
- "../../node_modules/.pnpm/ee-first@1.1.1/node_modules/ee-first/index.js": function(module) {
121
+ "../../node_modules/.pnpm/ee-first@1.1.1/node_modules/ee-first/index.js" (module) {
122
122
  function listener(event, done) {
123
123
  return function onevent(arg1) {
124
124
  for(var args = Array(arguments.length), i = 0; i < args.length; i++)args[i] = arguments[i];
@@ -151,7 +151,7 @@ __webpack_require__.add({
151
151
  return thunk.cancel = cleanup, thunk;
152
152
  };
153
153
  },
154
- "../../node_modules/.pnpm/javascript-stringify@2.1.0/node_modules/javascript-stringify/dist/array.js": function(__unused_webpack_module, exports) {
154
+ "../../node_modules/.pnpm/javascript-stringify@2.1.0/node_modules/javascript-stringify/dist/array.js" (__unused_webpack_module, exports) {
155
155
  Object.defineProperty(exports, "__esModule", {
156
156
  value: !0
157
157
  }), exports.arrayToString = void 0, exports.arrayToString = (array, space, next)=>{
@@ -162,7 +162,7 @@ __webpack_require__.add({
162
162
  return `[${eol}${values}${eol}]`;
163
163
  };
164
164
  },
165
- "../../node_modules/.pnpm/javascript-stringify@2.1.0/node_modules/javascript-stringify/dist/function.js": function(__unused_webpack_module, exports, __webpack_require__) {
165
+ "../../node_modules/.pnpm/javascript-stringify@2.1.0/node_modules/javascript-stringify/dist/function.js" (__unused_webpack_module, exports, __webpack_require__) {
166
166
  Object.defineProperty(exports, "__esModule", {
167
167
  value: !0
168
168
  }), exports.FunctionParser = exports.dedentFunction = exports.functionToString = exports.USED_METHOD_KEY = void 0;
@@ -300,7 +300,7 @@ __webpack_require__.add({
300
300
  }
301
301
  exports.FunctionParser = FunctionParser;
302
302
  },
303
- "../../node_modules/.pnpm/javascript-stringify@2.1.0/node_modules/javascript-stringify/dist/index.js": function(__unused_webpack_module, exports, __webpack_require__) {
303
+ "../../node_modules/.pnpm/javascript-stringify@2.1.0/node_modules/javascript-stringify/dist/index.js" (__unused_webpack_module, exports, __webpack_require__) {
304
304
  exports.stringify = void 0;
305
305
  let stringify_1 = __webpack_require__("../../node_modules/.pnpm/javascript-stringify@2.1.0/node_modules/javascript-stringify/dist/stringify.js"), quote_1 = __webpack_require__("../../node_modules/.pnpm/javascript-stringify@2.1.0/node_modules/javascript-stringify/dist/quote.js"), ROOT_SENTINEL = Symbol("root");
306
306
  function replacerToString(replacer) {
@@ -336,7 +336,7 @@ __webpack_require__.add({
336
336
  return result;
337
337
  };
338
338
  },
339
- "../../node_modules/.pnpm/javascript-stringify@2.1.0/node_modules/javascript-stringify/dist/object.js": function(__unused_webpack_module, exports, __webpack_require__) {
339
+ "../../node_modules/.pnpm/javascript-stringify@2.1.0/node_modules/javascript-stringify/dist/object.js" (__unused_webpack_module, exports, __webpack_require__) {
340
340
  Object.defineProperty(exports, "__esModule", {
341
341
  value: !0
342
342
  }), exports.objectToString = void 0;
@@ -370,7 +370,7 @@ __webpack_require__.add({
370
370
  "[object Window]": globalToString
371
371
  };
372
372
  },
373
- "../../node_modules/.pnpm/javascript-stringify@2.1.0/node_modules/javascript-stringify/dist/quote.js": function(__unused_webpack_module, exports) {
373
+ "../../node_modules/.pnpm/javascript-stringify@2.1.0/node_modules/javascript-stringify/dist/quote.js" (__unused_webpack_module, exports) {
374
374
  Object.defineProperty(exports, "__esModule", {
375
375
  value: !0
376
376
  }), exports.stringifyPath = exports.quoteKey = exports.isValidVariableName = exports.IS_VALID_IDENTIFIER = exports.quoteString = void 0;
@@ -426,7 +426,7 @@ __webpack_require__.add({
426
426
  return result;
427
427
  };
428
428
  },
429
- "../../node_modules/.pnpm/javascript-stringify@2.1.0/node_modules/javascript-stringify/dist/stringify.js": function(__unused_webpack_module, exports, __webpack_require__) {
429
+ "../../node_modules/.pnpm/javascript-stringify@2.1.0/node_modules/javascript-stringify/dist/stringify.js" (__unused_webpack_module, exports, __webpack_require__) {
430
430
  Object.defineProperty(exports, "__esModule", {
431
431
  value: !0
432
432
  }), exports.toString = void 0;
@@ -445,7 +445,7 @@ __webpack_require__.add({
445
445
  };
446
446
  exports.toString = (value, space, next, key)=>null === value ? "null" : PRIMITIVE_TYPES[typeof value](value, space, next, key);
447
447
  },
448
- "../../node_modules/.pnpm/lilconfig@3.1.3/node_modules/lilconfig/src/index.js": function(module, __unused_webpack_exports, __webpack_require__) {
448
+ "../../node_modules/.pnpm/lilconfig@3.1.3/node_modules/lilconfig/src/index.js" (module, __unused_webpack_exports, __webpack_require__) {
449
449
  let path = __webpack_require__("path"), fs = __webpack_require__("fs"), os = __webpack_require__("os"), url = __webpack_require__("url"), fsReadFileAsync = fs.promises.readFile;
450
450
  function getDefaultSearchPlaces(name, sync) {
451
451
  return [
@@ -700,7 +700,7 @@ __webpack_require__.add({
700
700
  };
701
701
  };
702
702
  },
703
- "../../node_modules/.pnpm/on-finished@2.4.1/node_modules/on-finished/index.js": function(module, __unused_webpack_exports, __webpack_require__) {
703
+ "../../node_modules/.pnpm/on-finished@2.4.1/node_modules/on-finished/index.js" (module, __unused_webpack_exports, __webpack_require__) {
704
704
  module.exports = onFinished, module.exports.isFinished = isFinished;
705
705
  var asyncHooks = tryRequireAsyncHooks(), first = __webpack_require__("../../node_modules/.pnpm/ee-first@1.1.1/node_modules/ee-first/index.js"), defer = 'function' == typeof setImmediate ? setImmediate : function(fn) {
706
706
  process.nextTick(fn.bind.apply(fn, arguments));
@@ -766,7 +766,7 @@ __webpack_require__.add({
766
766
  return (asyncHooks.AsyncResource && (res = new asyncHooks.AsyncResource(fn.name || 'bound-anonymous-fn')), res && res.runInAsyncScope) ? res.runInAsyncScope.bind(res, fn, null) : fn;
767
767
  }
768
768
  },
769
- "../../node_modules/.pnpm/postcss-load-config@6.0.1_jiti@2.6.1_postcss@8.5.6_yaml@2.8.1/node_modules/postcss-load-config/src/index.js": function(module, __unused_webpack_exports, __webpack_require__) {
769
+ "../../node_modules/.pnpm/postcss-load-config@6.0.1_jiti@2.6.1_postcss@8.5.6_yaml@2.8.1/node_modules/postcss-load-config/src/index.js" (module, __unused_webpack_exports, __webpack_require__) {
770
770
  let yaml, { resolve } = __webpack_require__("node:path"), config = __webpack_require__("../../node_modules/.pnpm/lilconfig@3.1.3/node_modules/lilconfig/src/index.js"), loadOptions = __webpack_require__("../../node_modules/.pnpm/postcss-load-config@6.0.1_jiti@2.6.1_postcss@8.5.6_yaml@2.8.1/node_modules/postcss-load-config/src/options.js"), loadPlugins = __webpack_require__("../../node_modules/.pnpm/postcss-load-config@6.0.1_jiti@2.6.1_postcss@8.5.6_yaml@2.8.1/node_modules/postcss-load-config/src/plugins.js"), req = __webpack_require__("../../node_modules/.pnpm/postcss-load-config@6.0.1_jiti@2.6.1_postcss@8.5.6_yaml@2.8.1/node_modules/postcss-load-config/src/req.js");
771
771
  async function processResult(ctx, result) {
772
772
  let obj, file = result.filepath || '', projectConfig = ((obj = result.config) && obj.__esModule ? obj : {
@@ -840,7 +840,7 @@ __webpack_require__.add({
840
840
  });
841
841
  };
842
842
  },
843
- "../../node_modules/.pnpm/postcss-load-config@6.0.1_jiti@2.6.1_postcss@8.5.6_yaml@2.8.1/node_modules/postcss-load-config/src/options.js": function(module, __unused_webpack_exports, __webpack_require__) {
843
+ "../../node_modules/.pnpm/postcss-load-config@6.0.1_jiti@2.6.1_postcss@8.5.6_yaml@2.8.1/node_modules/postcss-load-config/src/options.js" (module, __unused_webpack_exports, __webpack_require__) {
844
844
  let req = __webpack_require__("../../node_modules/.pnpm/postcss-load-config@6.0.1_jiti@2.6.1_postcss@8.5.6_yaml@2.8.1/node_modules/postcss-load-config/src/req.js");
845
845
  module.exports = async function options(config, file) {
846
846
  if (config.parser && 'string' == typeof config.parser) try {
@@ -861,7 +861,7 @@ __webpack_require__.add({
861
861
  return config;
862
862
  };
863
863
  },
864
- "../../node_modules/.pnpm/postcss-load-config@6.0.1_jiti@2.6.1_postcss@8.5.6_yaml@2.8.1/node_modules/postcss-load-config/src/plugins.js": function(module, __unused_webpack_exports, __webpack_require__) {
864
+ "../../node_modules/.pnpm/postcss-load-config@6.0.1_jiti@2.6.1_postcss@8.5.6_yaml@2.8.1/node_modules/postcss-load-config/src/plugins.js" (module, __unused_webpack_exports, __webpack_require__) {
865
865
  let req = __webpack_require__("../../node_modules/.pnpm/postcss-load-config@6.0.1_jiti@2.6.1_postcss@8.5.6_yaml@2.8.1/node_modules/postcss-load-config/src/req.js");
866
866
  async function load(plugin, options, file) {
867
867
  try {
@@ -878,9 +878,9 @@ __webpack_require__.add({
878
878
  }), list;
879
879
  };
880
880
  },
881
- "../../node_modules/.pnpm/postcss-load-config@6.0.1_jiti@2.6.1_postcss@8.5.6_yaml@2.8.1/node_modules/postcss-load-config/src/req.js": function(module, __unused_webpack_exports, __webpack_require__) {
881
+ "../../node_modules/.pnpm/postcss-load-config@6.0.1_jiti@2.6.1_postcss@8.5.6_yaml@2.8.1/node_modules/postcss-load-config/src/req.js" (module, __unused_webpack_exports, __webpack_require__) {
882
882
  let tsx, jiti;
883
- var __filename = __webpack_fileURLToPath__(import.meta.url);
883
+ var __filename = __rspack_fileURLToPath(import.meta.url);
884
884
  let { createRequire } = __webpack_require__("node:module"), { pathToFileURL } = __webpack_require__("node:url"), TS_EXT_RE = /\.[mc]?ts$/, importError = [];
885
885
  module.exports = async function req(name, rootFile = __filename) {
886
886
  let url = createRequire(rootFile).resolve(name);
@@ -909,28 +909,28 @@ __webpack_require__.add({
909
909
  throw Error(`'tsx' or 'jiti' is required for the TypeScript configuration files. Make sure it is installed\nError: ${importError.map((error)=>error.message).join('\n')}`);
910
910
  };
911
911
  },
912
- async_hooks: function(module) {
912
+ async_hooks (module) {
913
913
  module.exports = __rspack_external_async_hooks;
914
914
  },
915
- fs: function(module) {
915
+ fs (module) {
916
916
  module.exports = __rspack_external_fs;
917
917
  },
918
- "node:module": function(module) {
918
+ "node:module" (module) {
919
919
  module.exports = __rspack_external_node_module_ab9f2194;
920
920
  },
921
- "node:path": function(module) {
921
+ "node:path" (module) {
922
922
  module.exports = __rspack_external_node_path_c5b9b54f;
923
923
  },
924
- "node:url": function(module) {
924
+ "node:url" (module) {
925
925
  module.exports = __rspack_external_node_url_e96de089;
926
926
  },
927
- os: function(module) {
927
+ os (module) {
928
928
  module.exports = __rspack_external_os;
929
929
  },
930
- path: function(module) {
930
+ path (module) {
931
931
  module.exports = __rspack_external_path;
932
932
  },
933
- url: function(module) {
933
+ url (module) {
934
934
  module.exports = __rspack_external_url;
935
935
  }
936
936
  });
@@ -2395,11 +2395,14 @@ function resolveFileName(stats) {
2395
2395
  }
2396
2396
  function formatModuleTrace(stats, errorFile) {
2397
2397
  if (!stats.moduleTrace) return;
2398
- let moduleNames = stats.moduleTrace.map((trace)=>trace.originName).filter(Boolean);
2398
+ let moduleNames = stats.moduleTrace.map((trace)=>trace.originName && removeLoaderChainDelimiter(trace.originName)).filter(Boolean);
2399
2399
  if (!moduleNames.length) return;
2400
- errorFile && moduleNames.unshift(`${errorFile} ${color.bold(color.red('×'))}`);
2400
+ if (errorFile) {
2401
+ let formatted = removeLoaderChainDelimiter(errorFile);
2402
+ moduleNames[0] !== formatted && moduleNames.unshift(formatted);
2403
+ }
2401
2404
  let rawTrace = moduleNames.reverse().map((item)=>`\n ${item}`).join('');
2402
- return color.dim(`Import traces (entry → error):${rawTrace}`);
2405
+ return color.dim(`Import traces (entry → error):${rawTrace} ${color.bold(color.red('×'))}`);
2403
2406
  }
2404
2407
  function hintUnknownFiles(message) {
2405
2408
  let hint = 'You may need an appropriate loader to handle this file type.';
@@ -2441,16 +2444,17 @@ function hintUnknownFiles(message) {
2441
2444
  ])if (plugin.test.test(message)) return message.replace(hint, plugin.hint);
2442
2445
  return message;
2443
2446
  }
2444
- function formatStatsError(stats) {
2445
- let fileName = resolveFileName(stats), message = `${((fileName, stats)=>{
2447
+ function formatStatsError(stats, root) {
2448
+ let fileName = resolveFileName(stats), message = `${((fileName, stats, root)=>{
2446
2449
  if (!fileName) return '';
2447
2450
  let DATA_URI_PREFIX = "data:text/javascript,";
2448
2451
  if (fileName.startsWith(DATA_URI_PREFIX)) {
2449
2452
  let snippet = fileName.replace(DATA_URI_PREFIX, '');
2450
2453
  return snippet.length > 30 && (snippet = `${snippet.slice(0, 30)}...`), `File: ${color.cyan('data-uri virtual module')} ${color.dim(`(${snippet})`)}\n`;
2451
2454
  }
2452
- return /:\d+:\d+/.test(fileName) ? `File: ${color.cyan(fileName)}\n` : stats.loc ? `File: ${color.cyan(`${fileName}:${stats.loc}`)}\n` : `File: ${color.cyan(`${fileName}:1:1`)}\n`;
2453
- })(fileName, stats)}${stats.message}`, verbose = 'verbose' === logger.level;
2455
+ let prefix = root + external_node_path_.sep;
2456
+ return (fileName.startsWith(prefix) && (fileName = fileName.replace(prefix, `.${external_node_path_.sep}`)), /:\d+:\d+/.test(fileName)) ? `File: ${color.cyan(fileName)}\n` : stats.loc ? `File: ${color.cyan(`${fileName}:${stats.loc}`)}\n` : `File: ${color.cyan(`${fileName}:1:1`)}\n`;
2457
+ })(fileName, stats, root)}${stats.message}`, verbose = 'verbose' === logger.level;
2454
2458
  verbose && (stats.details && (message += `\nDetails: ${stats.details}\n`), stats.stack && (message += `\n${stats.stack}`));
2455
2459
  let moduleTrace = formatModuleTrace(stats, fileName);
2456
2460
  moduleTrace && (message += moduleTrace);
@@ -2472,7 +2476,7 @@ function formatStatsError(stats) {
2472
2476
  };
2473
2477
  if (message.includes('need an additional plugin to handle "node:" URIs')) return getTips('node:*');
2474
2478
  if (!message.includes("Can't resolve")) return message;
2475
- let matchArray = message.match(/Can't resolve '(\w+)'/);
2479
+ let matchArray = stripVTControlCharacters(message).match(/Can't resolve '(\w+)'/);
2476
2480
  if (!matchArray) return message;
2477
2481
  let moduleName = matchArray[1];
2478
2482
  return moduleName && [
@@ -2556,12 +2560,12 @@ function getRsbuildStats(statsInstance, compiler, action) {
2556
2560
  let statsOptions = getStatsOptions(compiler, action);
2557
2561
  return statsInstance.toJson(statsOptions);
2558
2562
  }
2559
- function formatStats(stats, hasErrors) {
2563
+ function formatStats(stats, hasErrors, root) {
2560
2564
  if (hasErrors) return {
2561
- message: formatErrorMessage(getStatsErrors(stats).map((item)=>formatStatsError(item))),
2565
+ message: formatErrorMessage(getStatsErrors(stats).map((item)=>formatStatsError(item, root))),
2562
2566
  level: 'error'
2563
2567
  };
2564
- let warningMessages = getStatsWarnings(stats).map((item)=>formatStatsError(item));
2568
+ let warningMessages = getStatsWarnings(stats).map((item)=>formatStatsError(item, root));
2565
2569
  if (warningMessages.length) {
2566
2570
  let title = color.bold(color.yellow(warningMessages.length > 1 ? 'Build warnings: \n' : 'Build warning: \n'));
2567
2571
  return {
@@ -2822,7 +2826,8 @@ let OVERRIDE_PATHS = new Set([
2822
2826
  port: '',
2823
2827
  host: '',
2824
2828
  overlay: !0,
2825
- reconnect: 100
2829
+ reconnect: 100,
2830
+ logLevel: 'info'
2826
2831
  }
2827
2832
  },
2828
2833
  server: {
@@ -2944,7 +2949,8 @@ let OVERRIDE_PATHS = new Set([
2944
2949
  strategy: 'split-by-experience'
2945
2950
  }
2946
2951
  },
2947
- environments: {}
2952
+ environments: {},
2953
+ logLevel: 'info'
2948
2954
  });
2949
2955
  function getDefaultEntry(root) {
2950
2956
  let entryFile = findExists([
@@ -2963,7 +2969,7 @@ function getDefaultEntry(root) {
2963
2969
  }
2964
2970
  let withDefaultConfig = async (rootPath, config)=>{
2965
2971
  let merged = mergeRsbuildConfig(createDefaultConfig(), config);
2966
- if (merged.root ||= rootPath, merged.source ||= {}, merged.server?.base && (config.dev?.assetPrefix === void 0 && (merged.dev ||= {}, merged.dev.assetPrefix = merged.server.base), config.output?.assetPrefix === void 0 && (merged.output ||= {}, merged.output.assetPrefix = merged.server.base)), merged.dev?.lazyCompilation === void 0 && (merged.dev ||= {}, merged.dev.lazyCompilation = {
2972
+ if (merged.root ||= rootPath, merged.source ||= {}, merged.server?.base && (config.dev?.assetPrefix === void 0 && (merged.dev ||= {}, merged.dev.assetPrefix = merged.server.base), config.output?.assetPrefix === void 0 && (merged.output ||= {}, merged.output.assetPrefix = merged.server.base)), config.dev?.client?.logLevel === void 0 && (merged.dev ||= {}, merged.dev.client ||= {}, merged.dev.client.logLevel = merged.logLevel), merged.dev?.lazyCompilation === void 0 && (merged.dev ||= {}, merged.dev.lazyCompilation = {
2967
2973
  imports: !0,
2968
2974
  entries: !1
2969
2975
  }), !merged.source.tsconfigPath) {
@@ -3414,7 +3420,7 @@ function createPublicContext(context) {
3414
3420
  async function createContext(options, userConfig) {
3415
3421
  let { cwd } = options, rootPath = userConfig.root ? ensureAbsolutePath(cwd, userConfig.root) : cwd, rsbuildConfig = await withDefaultConfig(rootPath, userConfig), cachePath = (0, external_node_path_.join)(rootPath, 'node_modules', '.cache'), specifiedEnvironments = options.environment && options.environment.length > 0 ? options.environment : void 0, bundlerType = userConfig.provider ? 'webpack' : 'rspack';
3416
3422
  return {
3417
- version: "1.6.12",
3423
+ version: "1.6.14",
3418
3424
  rootPath,
3419
3425
  distPath: '',
3420
3426
  cachePath,
@@ -4016,7 +4022,7 @@ async function createCompiler_createCompiler(options) {
4016
4022
  }), compiler.hooks.done.tap(HOOK_NAME, (statsInstance)=>{
4017
4023
  let stats = getRsbuildStats(statsInstance, compiler, context.action), hasErrors = statsInstance.hasErrors();
4018
4024
  context.buildState.stats = stats, context.buildState.status = 'done', context.buildState.hasErrors = hasErrors, context.socketServer?.onBuildDone();
4019
- let { message, level } = formatStats(stats, hasErrors);
4025
+ let { message, level } = formatStats(stats, hasErrors, options.context.rootPath);
4020
4026
  'error' === level && logger.error(message), 'warning' === level && logger.warn(message), isMultiCompiler || printTime(0, hasErrors), isCompiling = !1;
4021
4027
  }), 'dev' === context.action && registerDevHook({
4022
4028
  context,
@@ -4333,7 +4339,36 @@ async function gzipSize(input) {
4333
4339
  let data = await fileSize_gzip(input);
4334
4340
  return Buffer.byteLength(data);
4335
4341
  }
4336
- let EXCLUDE_ASSET_REGEX = /\.(?:map|LICENSE\.txt|d\.ts)$/, excludeAsset = (asset)=>EXCLUDE_ASSET_REGEX.test(asset.name), getAssetColor = (size)=>size > 300000 ? color.red : size > 100000 ? color.yellow : color.green;
4342
+ function getSnapshotPath(dir, snapshotHash) {
4343
+ return snapshotHash ? external_node_path_.default.join(dir, `rsbuild/file-sizes-${snapshotHash}.json`) : external_node_path_.default.join(dir, 'rsbuild/file-sizes.json');
4344
+ }
4345
+ function normalizeFilename(fileName) {
4346
+ return fileName.replace(/\.[a-f0-9]{8,}\./g, '.');
4347
+ }
4348
+ async function loadPrevSnapshots(snapshotPath) {
4349
+ try {
4350
+ let content = await node_fs.promises.readFile(snapshotPath, 'utf-8');
4351
+ return JSON.parse(content);
4352
+ } catch {
4353
+ return null;
4354
+ }
4355
+ }
4356
+ async function saveSnapshots(snapshotPath, snapshots) {
4357
+ try {
4358
+ await node_fs.promises.mkdir(external_node_path_.default.dirname(snapshotPath), {
4359
+ recursive: !0
4360
+ }), await node_fs.promises.writeFile(snapshotPath, JSON.stringify(snapshots, null, 2));
4361
+ } catch (err) {
4362
+ logger.debug('Failed to save file size snapshots:', err);
4363
+ }
4364
+ }
4365
+ let EXCLUDE_ASSET_REGEX = /\.(?:map|LICENSE\.txt|d\.ts)$/, excludeAsset = (asset)=>EXCLUDE_ASSET_REGEX.test(asset.name), isSignificantDiff = (diff)=>Math.abs(diff) >= 10, formatDiff = (diff)=>{
4366
+ let label = `(${diff > 0 ? '+' : '-'}${calcFileSize(Math.abs(diff))})`;
4367
+ return {
4368
+ label: (diff > 0 ? color.red : color.green)(label),
4369
+ length: label.length
4370
+ };
4371
+ }, getAssetColor = (size)=>size > 300000 ? color.red : size > 100000 ? color.yellow : color.green;
4337
4372
  function getHeader(maxFileLength, maxSizeLength, fileHeader, showGzipHeader) {
4338
4373
  let lengths = [
4339
4374
  maxFileLength,
@@ -4352,26 +4387,82 @@ function getHeader(maxFileLength, maxSizeLength, fileHeader, showGzipHeader) {
4352
4387
  let calcFileSize = (len)=>{
4353
4388
  let val = len / 1000;
4354
4389
  return `${val.toFixed(val < 1 ? 2 : 1)} kB`;
4355
- }, coloringAssetName = (assetName)=>JS_REGEX.test(assetName) ? color.cyan(assetName) : assetName.endsWith('.css') ? color.yellow(assetName) : assetName.endsWith('.html') ? color.green(assetName) : color.magenta(assetName), COMPRESSIBLE_REGEX = /\.(?:js|css|html|json|svg|txt|xml|xhtml|wasm|manifest|md)$/i;
4356
- async function printFileSizes(options, stats, rootPath, distPath, environmentName) {
4357
- let logs = [], showDetail = !1 !== options.detail, showTotal = !1 !== options.total;
4358
- if (!showTotal && !showDetail) return logs;
4359
- let exclude = options.exclude ?? excludeAsset, relativeDistPath = external_node_path_.default.relative(rootPath, distPath), formatAsset = async (asset)=>{
4360
- let fileName = asset.name.split('?')[0], contents = await node_fs.promises.readFile(external_node_path_.default.join(distPath, fileName)), size = Buffer.byteLength(contents), gzippedSize = options.compressed && COMPRESSIBLE_REGEX.test(fileName) ? await gzipSize(contents) : null, gzipSizeLabel = gzippedSize ? getAssetColor(gzippedSize)(calcFileSize(gzippedSize)) : null;
4390
+ }, COMPRESSIBLE_REGEX = /\.(?:js|css|html|json|svg|txt|xml|xhtml|wasm|manifest|md)$/i;
4391
+ async function printFileSizes(options, stats, rootPath, distPath, environmentName, previousSizes) {
4392
+ let logs = [], showDetail = !1 !== options.detail, showDiff = !1 !== options.diff && null !== previousSizes, showTotal = !1 !== options.total;
4393
+ if (!showTotal && !showDetail) return {
4394
+ logs
4395
+ };
4396
+ let relativeDistPath = external_node_path_.default.relative(rootPath, distPath), snapshot = {
4397
+ files: {},
4398
+ totalSize: 0,
4399
+ totalGzipSize: 0
4400
+ }, formatAsset = async (asset)=>{
4401
+ let fileName = asset.name.split('?')[0], contents = await node_fs.promises.readFile(external_node_path_.default.join(distPath, fileName)), size = Buffer.byteLength(contents), gzippedSize = options.compressed && COMPRESSIBLE_REGEX.test(fileName) ? await gzipSize(contents) : null, normalizedName = normalizeFilename(fileName);
4402
+ snapshot.files[normalizedName] = {
4403
+ size,
4404
+ gzippedSize: gzippedSize ?? void 0
4405
+ };
4406
+ let sizeLabel = calcFileSize(size), sizeLabelLength = sizeLabel.length, gzipSizeLabel = gzippedSize ? getAssetColor(gzippedSize)(calcFileSize(gzippedSize)) : null;
4407
+ if (showDiff) {
4408
+ let sizeData = previousSizes[environmentName]?.files[normalizedName], sizeDiff = size - (sizeData?.size ?? 0);
4409
+ if (isSignificantDiff(sizeDiff)) {
4410
+ let { label, length } = formatDiff(sizeDiff);
4411
+ sizeLabel += ` ${label}`, sizeLabelLength += length + 1;
4412
+ }
4413
+ if (null !== gzippedSize) {
4414
+ let gzipDiff = gzippedSize - (sizeData?.gzippedSize ?? 0);
4415
+ isSignificantDiff(gzipDiff) && (gzipSizeLabel += ` ${formatDiff(gzipDiff).label}`);
4416
+ }
4417
+ }
4418
+ let folder = external_node_path_.default.join(relativeDistPath, external_node_path_.default.dirname(fileName)), name = external_node_path_.default.basename(fileName), filenameLabel = color.dim(folder + external_node_path_.default.sep) + (JS_REGEX.test(name) ? color.cyan(name) : name.endsWith('.css') ? color.yellow(name) : name.endsWith('.html') ? color.green(name) : color.magenta(name)), filenameLength = (folder + external_node_path_.default.sep + name).length;
4361
4419
  return {
4420
+ name,
4421
+ filenameLabel,
4422
+ filenameLength,
4362
4423
  size,
4363
- folder: external_node_path_.default.join(relativeDistPath, external_node_path_.default.dirname(fileName)),
4364
- name: external_node_path_.default.basename(fileName),
4424
+ sizeLabel,
4425
+ sizeLabelLength,
4365
4426
  gzippedSize,
4366
- sizeLabel: calcFileSize(size),
4367
4427
  gzipSizeLabel
4368
4428
  };
4369
- }, getAssets = async ()=>Promise.all(getAssetsFromStats(stats).filter((asset)=>!exclude(asset) && (!options.include || options.include(asset))).map((asset)=>formatAsset(asset))), assets = await getAssets();
4370
- if (0 === assets.length) return logs;
4371
- logs.push(''), assets.sort((a, b)=>a.size - b.size);
4372
- let totalSize = 0, totalGzipSize = 0;
4373
- for (let asset of (showTotal = showTotal && !(showDetail && 1 === assets.length), assets))totalSize += asset.size, options.compressed && (totalGzipSize += asset.gzippedSize ?? asset.size);
4374
- let fileHeader = showDetail ? `File (${environmentName})` : '', totalSizeLabel = showTotal ? showDetail ? 'Total:' : `Total size (${environmentName}):` : '', totalSizeStr = showTotal ? calcFileSize(totalSize) : '', getCustomTotal = ()=>'function' == typeof options.total ? options.total({
4429
+ }, getAssets = async ()=>{
4430
+ let assets = getAssetsFromStats(stats), exclude = options.exclude ?? excludeAsset, filteredAssets = assets.filter((asset)=>!exclude(asset) && (!options.include || options.include(asset)));
4431
+ return (await Promise.all(filteredAssets.map((asset)=>formatAsset(asset)))).sort((a, b)=>a.size - b.size);
4432
+ }, assets = await getAssets();
4433
+ if (0 === assets.length) return {
4434
+ logs
4435
+ };
4436
+ logs.push(''), showDetail && 1 === assets.length && (showTotal = !1);
4437
+ let { totalSize, totalGzipSize } = ((assets, compressed)=>{
4438
+ let totalSize = 0, totalGzipSize = 0;
4439
+ for (let { size, gzippedSize } of assets)totalSize += size, compressed && (totalGzipSize += gzippedSize ?? size);
4440
+ return {
4441
+ totalSize,
4442
+ totalGzipSize
4443
+ };
4444
+ })(assets, options.compressed);
4445
+ snapshot.totalSize = totalSize, snapshot.totalGzipSize = totalGzipSize;
4446
+ let fileHeader = showDetail ? `File (${environmentName})` : '', { totalSizeTitle, totalSizeLabel, totalSizeLabelLength } = (()=>{
4447
+ if (!showTotal) return {
4448
+ totalSizeTitle: '',
4449
+ totalSizeLabel: '',
4450
+ totalSizeLabelLength: 0
4451
+ };
4452
+ let totalSizeTitle = showDetail ? 'Total:' : `Total size (${environmentName}):`, totalSizeLabel = calcFileSize(totalSize), totalSizeLabelLength = totalSizeLabel.length;
4453
+ if (showDiff) {
4454
+ let totalSizeDiff = totalSize - (previousSizes[environmentName]?.totalSize ?? 0);
4455
+ if (isSignificantDiff(totalSizeDiff)) {
4456
+ let { label, length } = formatDiff(totalSizeDiff);
4457
+ totalSizeLabel += ` ${label}`, totalSizeLabelLength += length + 1;
4458
+ }
4459
+ }
4460
+ return {
4461
+ totalSizeTitle,
4462
+ totalSizeLabel,
4463
+ totalSizeLabelLength
4464
+ };
4465
+ })(), getCustomTotal = ()=>'function' == typeof options.total ? options.total({
4375
4466
  environmentName,
4376
4467
  distPath: relativeDistPath,
4377
4468
  assets: assets.map((asset)=>({
@@ -4382,13 +4473,11 @@ async function printFileSizes(options, stats, rootPath, distPath, environmentNam
4382
4473
  totalGzipSize
4383
4474
  }) : null;
4384
4475
  if (showDetail) {
4385
- let maxFileLength = Math.max(...assets.map((a)=>(a.folder + external_node_path_.default.sep + a.name).length), showTotal ? totalSizeLabel.length : 0, fileHeader.length), maxSizeLength = Math.max(...assets.map((a)=>a.sizeLabel.length), totalSizeStr.length), showGzipHeader = !!(options.compressed && assets.some((item)=>null !== item.gzippedSize));
4476
+ let maxFileLength = Math.max(...assets.map((asset)=>asset.filenameLength), showTotal ? totalSizeTitle.length : 0, fileHeader.length), maxSizeLength = Math.max(...assets.map((a)=>a.sizeLabelLength), totalSizeLabelLength), showGzipHeader = !!(options.compressed && assets.some((item)=>null !== item.gzippedSize));
4386
4477
  for (let asset of (logs.push(getHeader(maxFileLength, maxSizeLength, fileHeader, showGzipHeader)), assets)){
4387
- let { sizeLabel } = asset, { name, folder, gzipSizeLabel } = asset, fileNameLength = (folder + external_node_path_.default.sep + name).length, sizeLength = sizeLabel.length;
4388
- sizeLength < maxSizeLength && (sizeLabel += ' '.repeat(maxSizeLength - sizeLength));
4389
- let fileNameLabel = color.dim(asset.folder + external_node_path_.default.sep) + coloringAssetName(asset.name);
4390
- fileNameLength < maxFileLength && (fileNameLabel += ' '.repeat(maxFileLength - fileNameLength));
4391
- let log = `${fileNameLabel} ${sizeLabel}`;
4478
+ let { sizeLabel, sizeLabelLength, gzipSizeLabel } = asset, { filenameLength } = asset, { filenameLabel } = asset;
4479
+ sizeLabelLength < maxSizeLength && (sizeLabel += ' '.repeat(maxSizeLength - sizeLabelLength)), filenameLength < maxFileLength && (filenameLabel += ' '.repeat(maxFileLength - filenameLength));
4480
+ let log = `${filenameLabel} ${sizeLabel}`;
4392
4481
  gzipSizeLabel && (log += ` ${gzipSizeLabel}`), logs.push(log);
4393
4482
  }
4394
4483
  if (showTotal) {
@@ -4397,9 +4486,12 @@ async function printFileSizes(options, stats, rootPath, distPath, environmentNam
4397
4486
  if (customTotal) logs.push(customTotal);
4398
4487
  else {
4399
4488
  let log = '';
4400
- if (log += ' '.repeat(maxFileLength - totalSizeLabel.length), log += color.magenta(totalSizeLabel), log += ` ${totalSizeStr}`, options.compressed) {
4489
+ if (log += ' '.repeat(maxFileLength - totalSizeTitle.length), log += color.magenta(totalSizeTitle), log += ` ${totalSizeLabel}`, options.compressed) {
4401
4490
  let colorFn = getAssetColor(totalGzipSize / assets.length);
4402
- log += ' '.repeat(maxSizeLength - totalSizeStr.length), log += ` ${colorFn(calcFileSize(totalGzipSize))}`;
4491
+ if (log += ' '.repeat(maxSizeLength - totalSizeLabelLength), log += ` ${colorFn(calcFileSize(totalGzipSize))}`, showDiff) {
4492
+ let totalGzipSizeDiff = totalGzipSize - (previousSizes[environmentName]?.totalGzipSize ?? 0);
4493
+ isSignificantDiff(totalGzipSizeDiff) && (log += ` ${formatDiff(totalGzipSizeDiff).label}`);
4494
+ }
4403
4495
  }
4404
4496
  logs.push(log);
4405
4497
  }
@@ -4408,11 +4500,14 @@ async function printFileSizes(options, stats, rootPath, distPath, environmentNam
4408
4500
  let customTotal = getCustomTotal();
4409
4501
  if (customTotal) logs.push(customTotal);
4410
4502
  else {
4411
- let log = `${color.magenta(totalSizeLabel)} ${totalSizeStr}`;
4503
+ let log = `${color.magenta(totalSizeTitle)} ${totalSizeLabel}`;
4412
4504
  options.compressed && (log += color.green(` (${calcFileSize(totalGzipSize)} gzipped)`)), logs.push(log);
4413
4505
  }
4414
4506
  }
4415
- return logs.push(''), logs;
4507
+ return logs.push(''), {
4508
+ logs,
4509
+ snapshot
4510
+ };
4416
4511
  }
4417
4512
  let entryNameSymbol = Symbol('entryName'), VOID_TAGS = [
4418
4513
  'area',
@@ -4804,6 +4899,7 @@ let getPort = async ({ host, port, strictPort, tryLimits = 20 })=>{
4804
4899
  if ('EADDRINUSE' !== e.code) throw e;
4805
4900
  port++, attempts++;
4806
4901
  }
4902
+ if (!found) throw Error(`${color.dim('[rsbuild:server]')} Failed to find an available port after ${tryLimits + 1} attempts, starting from ${color.yellow(original)}.`);
4807
4903
  if (port !== original && strictPort) throw Error(`${color.dim('[rsbuild:server]')} Port ${color.yellow(original)} is occupied, please choose another one.`);
4808
4904
  return port;
4809
4905
  }, getServerConfig = async ({ config })=>{
@@ -5760,7 +5856,8 @@ init({
5760
5856
  serverHost: ${JSON.stringify(resolvedHost)},
5761
5857
  serverPort: ${resolvedPort},
5762
5858
  liveReload: ${config.dev.liveReload},
5763
- browserLogs: ${!!config.dev.browserLogs}
5859
+ browserLogs: ${!!config.dev.browserLogs},
5860
+ logLevel: ${JSON.stringify(config.dev.client.logLevel)}
5764
5861
  });
5765
5862
  `;
5766
5863
  new compiler.webpack.EntryPlugin(compiler.context, createVirtualModule(hmrEntry), {
@@ -6246,7 +6343,7 @@ class SocketServer {
6246
6343
  });
6247
6344
  }
6248
6345
  sendError(errors, token) {
6249
- let formattedErrors = errors.map((item)=>formatStatsError(item));
6346
+ let formattedErrors = errors.map((item)=>formatStatsError(item, this.context.rootPath));
6250
6347
  this.sockWrite({
6251
6348
  type: 'errors',
6252
6349
  data: {
@@ -6256,7 +6353,7 @@ class SocketServer {
6256
6353
  }, token);
6257
6354
  }
6258
6355
  sendWarning(warnings, token) {
6259
- let formattedWarnings = warnings.map((item)=>formatStatsError(item));
6356
+ let formattedWarnings = warnings.map((item)=>formatStatsError(item, this.context.rootPath));
6260
6357
  this.sockWrite({
6261
6358
  type: 'warnings',
6262
6359
  data: {
@@ -7694,25 +7791,32 @@ function applyDefaultPlugins(pluginManager, context) {
7694
7791
  {
7695
7792
  name: 'rsbuild:file-size',
7696
7793
  setup (api) {
7697
- api.onAfterBuild(async ({ stats, environments, isFirstCompile })=>{
7794
+ api.onAfterBuild(async ({ stats, isFirstCompile })=>{
7698
7795
  let { hasErrors } = context.buildState;
7699
7796
  if (!stats || hasErrors || !isFirstCompile) return;
7700
- let logs = [];
7701
- await Promise.all(Object.values(environments).map(async (environment, index)=>{
7797
+ let environments = context.environmentList.filter(({ config })=>!1 !== config.performance.printFileSize);
7798
+ if (!environments.length) return;
7799
+ let showDiff = environments.some((environment)=>{
7702
7800
  let { printFileSize } = environment.config.performance;
7703
- if (!1 === printFileSize) return;
7704
- let defaultConfig = {
7705
- total: !0,
7706
- detail: !0,
7707
- compressed: 'node' !== environment.config.output.target
7708
- }, mergedConfig = !0 === printFileSize ? defaultConfig : {
7709
- ...defaultConfig,
7710
- ...printFileSize
7711
- }, statsItem = 'stats' in stats ? stats.stats[index] : stats, statsLogs = await printFileSizes(mergedConfig, statsItem, api.context.rootPath, environment.distPath, environment.name);
7712
- logs.push(...statsLogs);
7801
+ return 'object' == typeof printFileSize && !!printFileSize.diff;
7802
+ }), { configFilePath } = api.getNormalizedConfig()._privateMeta || {}, snapshotHash = showDiff && configFilePath ? await helpers_hash(configFilePath) : '', snapshotPath = showDiff ? getSnapshotPath(api.context.cachePath, snapshotHash) : '', prevSnapshots = showDiff ? await loadPrevSnapshots(snapshotPath) : null, nextSnapshots = {}, logs = await Promise.all(environments.map(async ({ name, index, config, distPath })=>{
7803
+ let statsItem = 'stats' in stats ? stats.stats[index] : stats, { logs: sizeLogs, snapshot } = await printFileSizes(((config)=>{
7804
+ let { printFileSize } = config.performance, defaultConfig = {
7805
+ total: !0,
7806
+ detail: !0,
7807
+ diff: !1,
7808
+ compressed: 'node' !== config.output.target
7809
+ };
7810
+ return !0 === printFileSize ? defaultConfig : {
7811
+ ...defaultConfig,
7812
+ ...printFileSize
7813
+ };
7814
+ })(config), statsItem, api.context.rootPath, distPath, name, prevSnapshots);
7815
+ return snapshot && (nextSnapshots[name] = snapshot), sizeLogs.join('\n');
7713
7816
  })).catch((err)=>{
7714
7817
  logger.warn('Failed to print file size.'), logger.warn(err);
7715
- }), logger.log(logs.join('\n'));
7818
+ });
7819
+ logs && logger.log(logs.join('\n')), showDiff && await saveSnapshots(snapshotPath, nextSnapshots);
7716
7820
  });
7717
7821
  }
7718
7822
  },
@@ -8374,8 +8478,12 @@ try {
8374
8478
  stage: 'summarize'
8375
8479
  }, ({ compiler, compilation })=>{
8376
8480
  if (0 === inlinedAssets.size) return;
8377
- let { devtool } = compiler.options;
8378
- for (let name of inlinedAssets)'hidden-source-map' === devtool || !1 === devtool ? compilation.deleteAsset(name) : delete compilation.assets[name];
8481
+ let { devtool } = compiler.options, hasSourceMap = 'hidden-source-map' !== devtool && !1 !== devtool;
8482
+ for (let name of inlinedAssets)hasSourceMap && compilation.updateAsset(name, compilation.assets[name], {
8483
+ related: {
8484
+ sourceMap: null
8485
+ }
8486
+ }), compilation.deleteAsset(name);
8379
8487
  inlinedAssets.clear();
8380
8488
  }), api.modifyHTMLTags(({ headTags, bodyTags }, { compiler, compilation, environment })=>{
8381
8489
  let { htmlPaths, config } = environment;
@@ -9058,7 +9166,7 @@ let applyServerOptions = (command)=>{
9058
9166
  };
9059
9167
  function setupCommands() {
9060
9168
  let cli = ((name = "")=>new CAC(name))('rsbuild');
9061
- cli.version("1.6.12"), cli.option('--base <base>', 'Set the base path of the server').option('-c, --config <config>', 'Set the configuration file (relative or absolute path)').option('--config-loader <loader>', 'Set the config file loader (auto | jiti | native)', {
9169
+ cli.version("1.6.14"), cli.option('--base <base>', 'Set the base path of the server').option('-c, --config <config>', 'Set the configuration file (relative or absolute path)').option('--config-loader <loader>', 'Set the config file loader (auto | jiti | native)', {
9062
9170
  default: 'auto'
9063
9171
  }).option('--env-dir <dir>', 'Set the directory for loading `.env` files').option('--env-mode <mode>', 'Set the env mode to load the `.env.[mode]` file').option('--environment <name>', 'Set the environment name(s) to build', {
9064
9172
  type: [
@@ -9127,7 +9235,7 @@ function initNodeEnv() {
9127
9235
  }
9128
9236
  function showGreeting() {
9129
9237
  let { npm_execpath, npm_lifecycle_event, NODE_RUN_SCRIPT_NAME } = process.env, isBun = npm_execpath?.includes('.bun');
9130
- logger.greet(`${'npx' === npm_lifecycle_event || isBun || NODE_RUN_SCRIPT_NAME ? '\n' : ''}Rsbuild v1.6.12\n`);
9238
+ logger.greet(`${'npx' === npm_lifecycle_event || isBun || NODE_RUN_SCRIPT_NAME ? '\n' : ''}Rsbuild v1.6.14\n`);
9131
9239
  }
9132
9240
  function setupLogLevel() {
9133
9241
  let logLevelIndex = process.argv.findIndex((item)=>'--log-level' === item || '--logLevel' === item);
@@ -9148,9 +9256,9 @@ function runCLI() {
9148
9256
  logger.error('Failed to start Rsbuild CLI.'), logger.error(err);
9149
9257
  }
9150
9258
  }
9151
- let src_version = "1.6.12";
9259
+ let src_version = "1.6.14";
9152
9260
  import * as __rspack_external_node_module_ab9f2194 from "node:module";
9153
9261
  import { createRequire as __rspack_createRequire } from "node:module";
9154
9262
  import * as __rspack_external_node_url_e96de089 from "node:url";
9155
- import { fileURLToPath as __webpack_fileURLToPath__ } from "node:url";
9263
+ import { fileURLToPath as __rspack_fileURLToPath } from "node:url";
9156
9264
  export { PLUGIN_CSS_NAME, PLUGIN_SWC_NAME, createRsbuild, defaultAllowedOrigins, defineConfig, ensureAssetPrefix, external_node_util_promisify, loadConfig_loadConfig as loadConfig, loadEnv, logger, mergeRsbuildConfig, node_fs, node_os, node_process, rspack_rspack as rspack, runCLI, src_version as version };
package/dist/2~open.cjs CHANGED
@@ -3,7 +3,7 @@ const __rslib_import_meta_url__ = 'undefined' == typeof document ? new (require(
3
3
  exports.ids = [
4
4
  "664"
5
5
  ], exports.modules = {
6
- "../../node_modules/.pnpm/open@11.0.0/node_modules/open/index.js": function(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
6
+ "../../node_modules/.pnpm/open@11.0.0/node_modules/open/index.js" (__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
7
7
  let isDockerCached, cachedResult, canAccessPowerShellPromise, mountPoint, defaultMountPoint;
8
8
  __webpack_require__.d(__webpack_exports__, {
9
9
  default: ()=>node_modules_open,
@@ -4,7 +4,7 @@ const __rslib_import_meta_url__ = 'undefined' == typeof document ? new (require(
4
4
  exports.ids = [
5
5
  "603"
6
6
  ], exports.modules = {
7
- "../../node_modules/.pnpm/range-parser@1.2.1/node_modules/range-parser/index.js": function(module) {
7
+ "../../node_modules/.pnpm/range-parser@1.2.1/node_modules/range-parser/index.js" (module) {
8
8
  function combineRanges(ranges) {
9
9
  for(var ordered = ranges.map(mapWithIndex).sort(sortByRangeStart), j = 0, i = 1; i < ordered.length; i++){
10
10
  var range = ordered[i], current = ordered[j];