Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/rollup/rollup into sync-6…
Browse files Browse the repository at this point in the history
…51e4935
  • Loading branch information
docschina-bot committed Aug 4, 2023
2 parents c7ab540 + 651e493 commit 9c6efd1
Show file tree
Hide file tree
Showing 9 changed files with 27 additions and 101 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# rollup changelog

## 3.27.2

_2023-08-04_

### Bug Fixes

- Revert sourcemap performance improvement for now as it causes issues with Vite (#5075)

### Pull Requests

- [#5075](https://github.com/rollup/rollup/pull/5075): Revert perf(sourcemap): lazy compute decoded mappings (@thebanjomatic)

## 3.27.1

_2023-08-03_
Expand Down
2 changes: 1 addition & 1 deletion browser/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@rollup/browser",
"version": "3.27.1",
"version": "3.27.2",
"description": "Next-generation ES module bundler browser build",
"main": "dist/rollup.browser.js",
"module": "dist/es/rollup.browser.js",
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "rollup",
"version": "3.27.1",
"version": "3.27.2",
"description": "Next-generation ES module bundler",
"main": "dist/rollup.js",
"module": "dist/es/rollup.js",
Expand Down
15 changes: 2 additions & 13 deletions src/Module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ import type {
} from './rollup/types';
import { EMPTY_OBJECT } from './utils/blank';
import { BuildPhase } from './utils/buildPhase';
import { decodedSourcemap, resetSourcemapCache } from './utils/decodedSourcemap';
import { getId } from './utils/getId';
import { getNewSet, getOrCreate } from './utils/getOrCreate';
import { getOriginalLocation } from './utils/getOriginalLocation';
Expand Down Expand Up @@ -818,18 +817,8 @@ export default class Module {

this.info.code = code;
this.originalCode = originalCode;

// We need to call decodedSourcemap on the input in case they were hydrated from json in the cache and don't
// have the lazy evaluation cache configured. Right now this isn't enforced by the type system because the
// RollupCache stores `ExistingDecodedSourcemap` instead of `ExistingRawSourcemap`
this.originalSourcemap = decodedSourcemap(originalSourcemap);
this.sourcemapChain = sourcemapChain.map(mapOrMissing =>
mapOrMissing.missing ? mapOrMissing : decodedSourcemap(mapOrMissing)
);

// If coming from cache and this value is already fully decoded, we want to re-encode here to save memory.
resetSourcemapCache(this.originalSourcemap, this.sourcemapChain);

this.originalSourcemap = originalSourcemap;
this.sourcemapChain = sourcemapChain;
if (transformFiles) {
this.transformFiles = transformFiles;
}
Expand Down
5 changes: 3 additions & 2 deletions src/rollup/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export type SourceMapSegment =

export interface ExistingDecodedSourceMap {
file?: string;
readonly mappings: SourceMapSegment[][];
mappings: SourceMapSegment[][];
names: string[];
sourceRoot?: string;
sources: string[];
Expand All @@ -74,10 +74,11 @@ export interface ExistingRawSourceMap {

export type DecodedSourceMapOrMissing =
| {
mappings?: never;
missing: true;
plugin: string;
}
| (ExistingDecodedSourceMap & { missing?: false });
| ExistingDecodedSourceMap;

export interface SourceMap {
file: string;
Expand Down
9 changes: 2 additions & 7 deletions src/utils/collapseSourcemaps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import type {
LogHandler,
SourceMapSegment
} from '../rollup/types';
import { decodedSourcemap, resetSourcemapCache } from './decodedSourcemap';
import { LOGLEVEL_WARN } from './logging';
import { error, logConflictingSourcemapSources, logSourcemapBroken } from './logs';
import { basename, dirname, relative, resolve } from './path';
Expand Down Expand Up @@ -151,7 +150,7 @@ class Link {

function getLinkMap(log: LogHandler) {
return function linkMap(source: Source | Link, map: DecodedSourceMapOrMissing): Link {
if (!map.missing) {
if (map.mappings) {
return new Link(map, [source]);
}

Expand Down Expand Up @@ -225,10 +224,6 @@ export function collapseSourcemaps(

sourcesContent = (excludeContent ? null : sourcesContent) as string[];

for (const module of modules) {
resetSourcemapCache(module.originalSourcemap, module.sourcemapChain);
}

return new SourceMap({ file, mappings, names, sources, sourcesContent });
}

Expand All @@ -251,5 +246,5 @@ export function collapseSourcemap(
getLinkMap(log)
) as Link;
const map = source.traceMappings();
return decodedSourcemap({ version: 3, ...map });
return { version: 3, ...map };
}
77 changes: 3 additions & 74 deletions src/utils/decodedSourcemap.ts
Original file line number Diff line number Diff line change
@@ -1,57 +1,12 @@
import { decode, encode } from '@jridgewell/sourcemap-codec';
import { decode } from '@jridgewell/sourcemap-codec';
import type {
DecodedSourceMapOrMissing,
ExistingDecodedSourceMap,
ExistingRawSourceMap,
SourceMapInput
} from '../rollup/types';

type Input = SourceMapInput | ExistingDecodedSourceMap | undefined;

interface CachedSourcemapData {
encodedMappings: string | undefined;
decodedMappings: ExistingDecodedSourceMap['mappings'] | undefined;
}

const sourceMapCache = new WeakMap<ExistingDecodedSourceMap, CachedSourcemapData>();

/**
* This clears the decoded array and falls back to the encoded string form.
* Sourcemap mappings arrays can be very large and holding on to them for longer
* than is necessary leads to poor heap utilization.
*/
function resetCacheToEncoded(cache: CachedSourcemapData) {
if (cache.encodedMappings === undefined && cache.decodedMappings) {
cache.encodedMappings = encode(cache.decodedMappings);
}
cache.decodedMappings = undefined;
}

export function resetSourcemapCache(
map: ExistingDecodedSourceMap | null,
sourcemapChain?: DecodedSourceMapOrMissing[]
) {
if (map) {
const cache = sourceMapCache.get(map);
if (cache) {
resetCacheToEncoded(cache);
}
}

if (!sourcemapChain) {
return;
}

for (const map of sourcemapChain) {
if (map.missing) continue;

resetSourcemapCache(map);
}
}

export function decodedSourcemap(map: null | undefined): null;
export function decodedSourcemap(map: Exclude<Input, null | undefined>): ExistingDecodedSourceMap;
export function decodedSourcemap(map: Input): ExistingDecodedSourceMap | null;
export function decodedSourcemap(map: Input): ExistingDecodedSourceMap | null {
if (!map) return null;

Expand All @@ -67,33 +22,7 @@ export function decodedSourcemap(map: Input): ExistingDecodedSourceMap | null {
};
}

const originalMappings = map.mappings;
const isAlreadyDecoded = typeof originalMappings !== 'string';
const cache = {
decodedMappings: isAlreadyDecoded ? originalMappings : undefined,
encodedMappings: isAlreadyDecoded ? undefined : originalMappings
};

const decodedMap = {
...(map as ExistingRawSourceMap | ExistingDecodedSourceMap),
// By moving mappings behind an accessor, we can avoid unneeded computation for cases
// where the mappings field is never actually accessed. This appears to greatly reduce
// the overhead of sourcemap decoding in terms of both compute time and memory usage.
get mappings() {
if (cache.decodedMappings) {
return cache.decodedMappings;
}
// If decodedMappings doesn't exist then encodedMappings should.
// The only scenario where cache.encodedMappings should be undefined is if the map
// this was constructed from was already decoded, or if mappings was set to a new
// decoded string. In either case, this line shouldn't get hit.
cache.decodedMappings = decode(cache.encodedMappings!);
cache.encodedMappings = undefined;
return cache.decodedMappings;
}
};

sourceMapCache.set(decodedMap, cache);
const mappings = typeof map.mappings === 'string' ? decode(map.mappings) : map.mappings;

return decodedMap;
return { ...(map as ExistingRawSourceMap | ExistingDecodedSourceMap), mappings };
}
2 changes: 1 addition & 1 deletion src/utils/getOriginalLocation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export function getOriginalLocation(
location: { column: number; line: number }
): { column: number; line: number } {
const filteredSourcemapChain = sourcemapChain.filter(
(sourcemap): sourcemap is ExistingDecodedSourceMap => !sourcemap.missing
(sourcemap): sourcemap is ExistingDecodedSourceMap => !!sourcemap.mappings
);
traceSourcemap: while (filteredSourcemapChain.length > 0) {
const sourcemap = filteredSourcemapChain.pop()!;
Expand Down

1 comment on commit 9c6efd1

@vercel
Copy link

@vercel vercel bot commented on 9c6efd1 Aug 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.