Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(chore) replace source-map library #1464

Merged
merged 3 commits into from Apr 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 1 addition & 2 deletions packages/language-server/package.json
Expand Up @@ -41,20 +41,19 @@
"@types/node": "^13.9.0",
"@types/prettier": "^2.2.3",
"@types/sinon": "^7.5.2",
"@types/source-map": "^0.5.7",
"cross-env": "^7.0.2",
"mocha": "^9.2.0",
"sinon": "^11.0.0",
"ts-node": "^10.0.0"
},
"dependencies": {
"@jridgewell/trace-mapping": "^0.3.9",
"chokidar": "^3.4.1",
"estree-walker": "^2.0.1",
"fast-glob": "^3.2.7",
"lodash": "^4.17.21",
"prettier": "2.5.1",
"prettier-plugin-svelte": "~2.7.0",
"source-map": "^0.7.3",
"svelte": "^3.47.0",
"svelte-preprocess": "~4.10.1",
"svelte2tsx": "~0.5.0",
Expand Down
25 changes: 4 additions & 21 deletions packages/language-server/src/lib/documents/DocumentMapper.ts
Expand Up @@ -14,8 +14,8 @@ import {
InsertReplaceEdit
} from 'vscode-languageserver';
import { TagInformation, offsetAt, positionAt, getLineOffsets } from './utils';
import { SourceMapConsumer } from 'source-map';
import { Logger } from '../../logger';
import { generatedPositionFor, originalPositionFor, TraceMap } from '@jridgewell/trace-mapping';

export interface DocumentMapper {
/**
Expand All @@ -40,11 +40,6 @@ export interface DocumentMapper {
* Get document URL
*/
getURL(): string;

/**
* Implement this if you need teardown logic before this mapper gets cleaned up.
*/
destroy?(): void;
}

/**
Expand Down Expand Up @@ -80,10 +75,6 @@ export class IdentityMapper implements DocumentMapper {
getURL(): string {
return this.url;
}

destroy() {
this.parent?.destroy?.();
}
}

/**
Expand Down Expand Up @@ -129,7 +120,7 @@ export class FragmentMapper implements DocumentMapper {

export class SourceMapDocumentMapper implements DocumentMapper {
constructor(
protected consumer: SourceMapConsumer,
protected traceMap: TraceMap,
protected sourceUri: string,
private parent?: DocumentMapper
) {}
Expand All @@ -143,7 +134,7 @@ export class SourceMapDocumentMapper implements DocumentMapper {
return { line: -1, character: -1 };
}

const mapped = this.consumer.originalPositionFor({
const mapped = originalPositionFor(this.traceMap, {
line: generatedPosition.line + 1,
column: generatedPosition.character
});
Expand All @@ -167,7 +158,7 @@ export class SourceMapDocumentMapper implements DocumentMapper {
originalPosition = this.parent.getGeneratedPosition(originalPosition);
}

const mapped = this.consumer.generatedPositionFor({
const mapped = generatedPositionFor(this.traceMap, {
line: originalPosition.line + 1,
column: originalPosition.character,
source: this.sourceUri
Expand Down Expand Up @@ -201,14 +192,6 @@ export class SourceMapDocumentMapper implements DocumentMapper {
getURL(): string {
return this.sourceUri;
}

/**
* Needs to be called when source mapper is no longer needed in order to prevent memory leaks.
*/
destroy() {
this.parent?.destroy?.();
this.consumer.destroy();
}
}

export function mapRangeToOriginal(
Expand Down
68 changes: 16 additions & 52 deletions packages/language-server/src/plugins/svelte/SvelteDocument.ts
@@ -1,4 +1,4 @@
import { SourceMapConsumer } from 'source-map';
import { TraceMap } from '@jridgewell/trace-mapping';
import type { compile } from 'svelte/compiler';
import { CompileOptions } from 'svelte/types/compiler/interfaces';
import { PreprocessorGroup, Processed } from 'svelte/types/compiler/preprocess/types';
Expand Down Expand Up @@ -100,21 +100,10 @@ export class SvelteDocument {
const svelte = importSvelte(this.getFilePath());
return svelte.compile((await this.getTranspiled()).getText(), options);
}

/**
* Needs to be called before cleanup to prevent source map memory leaks.
*/
destroyTranspiled() {
if (this.transpiledDoc) {
this.transpiledDoc.destroy();
this.transpiledDoc = undefined;
}
}
}

export interface ITranspiledSvelteDocument extends PositionMapper {
getText(): string;
destroy(): void;
}

export class TranspiledSvelteDocument implements ITranspiledSvelteDocument {
Expand All @@ -141,7 +130,7 @@ export class TranspiledSvelteDocument implements ITranspiledSvelteDocument {
preprocessed.code,
preprocessed.map
? new SourceMapDocumentMapper(
await createSourceMapConsumer(preprocessed.map),
createTraceMap(preprocessed.map),
// The "sources" array only contains the Svelte filename, not its path.
// For getting generated positions, the sourcemap consumer wants an exact match
// of the source filepath. Therefore only pass in the filename here.
Expand All @@ -164,10 +153,6 @@ export class TranspiledSvelteDocument implements ITranspiledSvelteDocument {
getGeneratedPosition(originalPosition: Position): Position {
return this.mapper?.getGeneratedPosition(originalPosition) || originalPosition;
}

destroy() {
this.mapper?.destroy();
}
}

/**
Expand All @@ -185,16 +170,12 @@ export class FallbackTranspiledSvelteDocument implements ITranspiledSvelteDocume
document,
preprocessors
);
const scriptMapper = await SvelteFragmentMapper.createScript(
const scriptMapper = SvelteFragmentMapper.createScript(
document,
transpiled,
processedScripts
);
const styleMapper = await SvelteFragmentMapper.createStyle(
document,
transpiled,
processedStyles
);
const styleMapper = SvelteFragmentMapper.createStyle(document, transpiled, processedStyles);

return new FallbackTranspiledSvelteDocument(
document,
Expand Down Expand Up @@ -262,18 +243,10 @@ export class FallbackTranspiledSvelteDocument implements ITranspiledSvelteDocume

return positionAt(offset, this.getText());
}

/**
* Needs to be called before cleanup to prevent source map memory leaks.
*/
destroy() {
this.scriptMapper?.destroy();
this.styleMapper?.destroy();
}
}

export class SvelteFragmentMapper implements PositionMapper {
static async createStyle(originalDoc: Document, transpiled: string, processed: Processed[]) {
static createStyle(originalDoc: Document, transpiled: string, processed: Processed[]) {
return SvelteFragmentMapper.create(
originalDoc,
transpiled,
Expand All @@ -283,7 +256,7 @@ export class SvelteFragmentMapper implements PositionMapper {
);
}

static async createScript(originalDoc: Document, transpiled: string, processed: Processed[]) {
static createScript(originalDoc: Document, transpiled: string, processed: Processed[]) {
const scriptInfo = originalDoc.scriptInfo || originalDoc.moduleScriptInfo;
const maybeScriptTag = extractScriptTags(transpiled);
const maybeScriptTagInfo =
Expand All @@ -298,7 +271,7 @@ export class SvelteFragmentMapper implements PositionMapper {
);
}

private static async create(
private static create(
originalDoc: Document,
transpiled: string,
originalTagInfo: TagInformation | null,
Expand All @@ -307,7 +280,7 @@ export class SvelteFragmentMapper implements PositionMapper {
) {
const sourceMapper =
processed.length > 0
? await SvelteFragmentMapper.createSourceMapper(processed, originalDoc)
? SvelteFragmentMapper.createSourceMapper(processed, originalDoc)
: new IdentityMapper(originalDoc.uri);

if (originalTagInfo && transpiledTagInfo) {
Expand All @@ -327,17 +300,17 @@ export class SvelteFragmentMapper implements PositionMapper {
return null;
}

private static async createSourceMapper(processed: Processed[], originalDoc: Document) {
private static createSourceMapper(processed: Processed[], originalDoc: Document) {
return processed.reduce(
async (parent, processedSingle) =>
(parent, processedSingle) =>
processedSingle?.map
? new SourceMapDocumentMapper(
await createSourceMapConsumer(processedSingle.map),
createTraceMap(processedSingle.map),
originalDoc.uri,
await parent
parent
)
: new IdentityMapper(originalDoc.uri, await parent),
Promise.resolve<DocumentMapper>(<any>undefined)
: new IdentityMapper(originalDoc.uri, parent),
<DocumentMapper>(<any>undefined)
);
}

Expand Down Expand Up @@ -387,15 +360,6 @@ export class SvelteFragmentMapper implements PositionMapper {
);
return this.transpiledFragmentMapper.getOriginalPosition(positionInTranspiledFragment);
}

/**
* Needs to be called before cleanup to prevent source map memory leaks.
*/
destroy() {
if (this.sourceMapper.destroy) {
this.sourceMapper.destroy();
}
}
}

/**
Expand Down Expand Up @@ -485,8 +449,8 @@ async function transpile(
return { transpiled, processedScripts, processedStyles };
}

async function createSourceMapConsumer(map: any): Promise<SourceMapConsumer> {
return new SourceMapConsumer(normalizeMap(map));
function createTraceMap(map: any): TraceMap {
return new TraceMap(normalizeMap(map));

function normalizeMap(map: any) {
// We don't know what we get, could be a stringified sourcemap,
Expand Down
Expand Up @@ -223,7 +223,6 @@ export class SveltePlugin
private async getSvelteDoc(document: Document) {
let svelteDoc = this.docManager.get(document);
if (!svelteDoc || svelteDoc.version !== document.version) {
svelteDoc?.destroyTranspiled();
svelteDoc = new SvelteDocument(document);
this.docManager.set(document, svelteDoc);
}
Expand Down
@@ -1,10 +1,10 @@
import { TraceMap } from '@jridgewell/trace-mapping';
import { Position } from 'vscode-languageserver';
import { SourceMapConsumer } from 'source-map';
import { SourceMapDocumentMapper } from '../../lib/documents';

export class ConsumerDocumentMapper extends SourceMapDocumentMapper {
constructor(consumer: SourceMapConsumer, sourceUri: string, private nrPrependesLines: number) {
super(consumer, sourceUri);
constructor(traceMap: TraceMap, sourceUri: string, private nrPrependesLines: number) {
super(traceMap, sourceUri);
}

getOriginalPosition(generatedPosition: Position): Position {
Expand Down