-
Notifications
You must be signed in to change notification settings - Fork 361
/
Copy pathtest-spec-tests.js
208 lines (193 loc) · 6.69 KB
/
test-spec-tests.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
/* -*- Mode: js; js-indent-level: 2; -*- */
/*
* Copyright 2024 Mozilla Foundation and contributors
* Licensed under the New BSD license. See LICENSE or:
* http://opensource.org/licenses/BSD-3-Clause
*/
const fs = require("fs").promises;
const SourceMapConsumer =
require("../lib/source-map-consumer").SourceMapConsumer;
const sourceMapSpecTests = require("./source-map-tests/source-map-spec-tests.json");
async function readJSON(path) {
const file = await fs.open(require.resolve(path));
const json = JSON.parse(await file.readFile());
file.close();
return json;
}
// Known failures due to intentional implementation choices or due to bugs.
const skippedTests = [
// Versions are explicitly checked a bit loosely.
"versionNumericString",
// Stricter sources array checking isn't implemented.
"sourcesNotStringOrNull",
"sourcesAndSourcesContentBothNull",
// Stricter names array checking isn't implemented.
"namesMissing",
"namesNotString",
// This check isn't as strict in this library.
"invalidMappingNotAString1",
// A mapping segment with no fields is technically invalid in the spec.
"invalidMappingSegmentWithZeroFields",
// These tests fail due to imprecision in the spec about the 32-bit limit.
"invalidMappingSegmentWithColumnExceeding32Bits",
"invalidMappingSegmentWithOriginalLineExceeding32Bits",
"invalidMappingSegmentWithOriginalColumnExceeding32Bits",
// A large VLQ that should parse, but currently does not.
"validMappingLargeVLQ",
// The library currently doesn't check the types of offset lines/columns.
"indexMapOffsetLineWrongType",
"indexMapOffsetColumnWrongType",
// The spec is not totally clear about this case.
"indexMapInvalidBaseMappings",
// The spec's definition of overlap can be refined
"indexMapInvalidOverlap",
// The library doesn't support the new ignoreList feature yet.
"ignoreListWrongType1",
"ignoreListWrongType2",
"ignoreListWrongType3",
"ignoreListOutOfBounds",
];
// The source-map library converts null sources to the "null" URL in its
// sources list, so for equality checking we accept this as null.
function nullish(nullOrString) {
if (nullOrString === "null") {
return null;
}
return nullOrString;
}
function mapLine(line) {
return line + 1;
}
async function testMappingAction(assert, rawSourceMap, action) {
return SourceMapConsumer.with(rawSourceMap, null, consumer => {
let mappedPosition = consumer.originalPositionFor({
line: mapLine(action.generatedLine),
column: action.generatedColumn,
});
assert.equal(
mappedPosition.line,
mapLine(action.originalLine),
`original line didn't match, expected ${mapLine(
action.originalLine
)} got ${mappedPosition.line}`
);
assert.equal(
mappedPosition.column,
action.originalColumn,
`original column didn't match, expected ${action.originalColumn} got ${mappedPosition.column}`
);
assert.equal(
nullish(mappedPosition.source),
action.originalSource,
`original source didn't match, expected ${action.originalSource} got ${mappedPosition.source}`
);
if (action.mappedName) {
assert.equal(
mappedPosition.name,
action.mappedName,
`mapped name didn't match, expected ${action.mappedName} got ${mappedPosition.name}`
);
}
// When the source is null, a reverse lookup may not make sense
// because there isn't a unique way to look it up.
if (action.originalSource !== null) {
mappedPosition = consumer.generatedPositionFor({
source: action.originalSource,
line: mapLine(action.originalLine),
column: action.originalColumn,
});
assert.equal(
mappedPosition.line,
mapLine(action.generatedLine),
`generated line didn't match, expected ${mapLine(
action.generatedLine
)} got ${mappedPosition.line}`
);
assert.equal(
mappedPosition.column,
action.generatedColumn,
`generated column didn't match, expected ${action.generatedColumn} got ${mappedPosition.column}`
);
}
});
}
async function testTransitiveMappingAction(assert, rawSourceMap, action) {
return SourceMapConsumer.with(rawSourceMap, null, async consumer => {
assert.ok(
Array.isArray(action.intermediateMaps),
"transitive mapping case requires intermediate maps"
);
let mappedPosition = consumer.originalPositionFor({
line: mapLine(action.generatedLine),
column: action.generatedColumn,
});
for (const intermediateMapPath of action.intermediateMaps) {
const intermediateMap = await readJSON(
`./source-map-tests/resources/${intermediateMapPath}`
);
await SourceMapConsumer.with(
intermediateMap,
null,
consumerIntermediate => {
mappedPosition = consumerIntermediate.originalPositionFor({
line: mappedPosition.line,
column: mappedPosition.column,
});
}
);
}
assert.equal(
mappedPosition.line,
mapLine(action.originalLine),
`original line didn't match, expected ${mapLine(
action.originalLine
)} got ${mappedPosition.line}`
);
assert.equal(
mappedPosition.column,
action.originalColumn,
`original column didn't match, expected ${action.originalColumn} got ${mappedPosition.column}`
);
assert.equal(
mappedPosition.source,
action.originalSource,
`original source didn't match, expected ${action.originalSource} got ${mappedPosition.source}`
);
});
}
for (const testCase of sourceMapSpecTests.tests) {
if (skippedTests.includes(testCase.name)) {
continue;
}
exports[`test from source map spec tests, name: ${testCase.name}`] =
async function (assert) {
const json = await readJSON(
`./source-map-tests/resources/${testCase.sourceMapFile}`
);
try {
const map = await new SourceMapConsumer(json);
map.eachMapping(() => {});
map.destroy();
} catch (exn) {
if (testCase.sourceMapIsValid) {
assert.fail(
"Expected valid source map but failed to load successfully: " +
exn.message
);
}
return;
}
if (!testCase.sourceMapIsValid) {
assert.fail("Expected invalid source map but loaded successfully");
}
if (testCase.testActions) {
for (const testAction of testCase.testActions) {
if (testAction.actionType == "checkMapping") {
await testMappingAction(assert, json, testAction);
} else if (testAction.actionType == "checkMappingTransitive") {
await testTransitiveMappingAction(assert, json, testAction);
}
}
}
};
}