Skip to content

Commit 58f5c95

Browse files
committed
Implement loose/strict decoding for scope start/end
1 parent 6ceea20 commit 58f5c95

File tree

2 files changed

+43
-4
lines changed

2 files changed

+43
-4
lines changed

src/decode/decode.test.ts

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
assertThrows,
1313
} from "jsr:@std/assert";
1414
import { encodeSigned, encodeUnsigned } from "../vlq.ts";
15-
import { decode } from "./decode.ts";
15+
import { decode, DecodeMode } from "./decode.ts";
1616
import type { SourceMapJson } from "../scopes.d.ts";
1717
import { OriginalScopeFlags, Tag } from "../codec.ts";
1818

@@ -142,11 +142,39 @@ describe("decode", () => {
142142
assertStrictEquals(info.scopes[0].kind, undefined);
143143
});
144144

145-
it("throws when encountering an ORIGINAL_SCOPE_END without start", () => {
145+
it("throws when encountering an ORIGINAL_SCOPE_END without start in strict mode", () => {
146146
const encoder = new ItemEncoder();
147147
encoder.addUnsignedVLQs(Tag.ORIGINAL_SCOPE_END, 0, 0).finishItem();
148148
const map = createMap(encoder.encode(), []);
149149

150-
assertThrows(() => decode(map));
150+
assertThrows(() => decode(map, { mode: DecodeMode.STRICT }));
151+
});
152+
153+
it("ignores miss-matched ORIGINAL_SCOPE_END items", () => {
154+
const encoder = new ItemEncoder();
155+
encoder.addUnsignedVLQs(Tag.ORIGINAL_SCOPE_END, 0, 0).finishItem();
156+
const map = createMap(encoder.encode(), []);
157+
158+
const info = decode(map, { mode: DecodeMode.LOOSE });
159+
160+
assertEquals(info.scopes, []);
161+
});
162+
163+
it("throws in strict mode when there are 'open' scopes left at the end", () => {
164+
const encoder = new ItemEncoder();
165+
encoder.addUnsignedVLQs(Tag.ORIGINAL_SCOPE_START, 0, 0, 0).finishItem();
166+
const map = createMap(encoder.encode(), []);
167+
168+
assertThrows(() => decode(map, { mode: DecodeMode.STRICT }));
169+
});
170+
171+
it("ignores 'open' scopes left at the end in loose mode", () => {
172+
const encoder = new ItemEncoder();
173+
encoder.addUnsignedVLQs(Tag.ORIGINAL_SCOPE_START, 0, 0, 0).finishItem();
174+
const map = createMap(encoder.encode(), []);
175+
176+
const info = decode(map, { mode: DecodeMode.LOOSE });
177+
178+
assertEquals(info.scopes, []);
151179
});
152180
});

src/decode/decode.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,10 @@ class Decoder {
139139

140140
const scope = this.#scopeStack.pop();
141141
if (!scope) {
142-
throw new Error(
142+
this.#throwInStrictMode(
143143
"Encountered ORIGINAL_SCOPE_END without matching ORIGINAL_SCOPE_START!",
144144
);
145+
continue;
145146
}
146147

147148
scope.end = { line: this.#scopeState.line, column: item.column };
@@ -244,6 +245,12 @@ class Decoder {
244245
}
245246
}
246247

248+
if (this.#scopeStack.length > 0) {
249+
this.#throwInStrictMode(
250+
"Encountered ORIGINAL_SCOPE_START without matching END!",
251+
);
252+
}
253+
247254
const info = { scopes: this.#scopes, ranges: this.#ranges };
248255

249256
this.#scopes = [];
@@ -356,4 +363,8 @@ class Decoder {
356363
yield EmptyItem;
357364
}
358365
}
366+
367+
#throwInStrictMode(message: string) {
368+
if (this.#mode === DecodeMode.STRICT) throw new Error(message);
369+
}
359370
}

0 commit comments

Comments
 (0)