Skip to content

Commit dc3bc65

Browse files
committed
fix: use only loc.start to ensure nodes begin on the correct line
1 parent ffbc96a commit dc3bc65

File tree

3 files changed

+36
-14
lines changed

3 files changed

+36
-14
lines changed

packages/bundle-source/demo/dir1/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export default function makeEncourager() {
66
return harden({
77
encourage,
88
makeError,
9+
makeError2: msg => TypeError(msg),
910
more,
1011
});
1112
}

packages/bundle-source/src/index.js

+29-14
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,9 @@ const DEFAULT_MODULE_FORMAT = 'nestedEvaluate';
1313
const DEFAULT_FILE_PREFIX = '/bundled-source';
1414
const SUPPORTED_FORMATS = ['getExport', 'nestedEvaluate'];
1515

16-
const removeComments = comments => {
17-
if (!comments) {
18-
return;
19-
}
20-
// We remove all the JS comments to prevent misidentifying HTML
21-
// comments, or import expressions.
22-
comments.splice(0, comments.length);
23-
};
16+
const IMPORT_RE = new RegExp('\\b(import)(\\s*(?:\\(|/[/*]))', 'sg');
17+
const HTML_COMMENT_START_RE = new RegExp(`${'<'}!--`, 'g');
18+
const HTML_COMMENT_END_RE = new RegExp(`--${'>'}`, 'g');
2419

2520
export function tildotPlugin() {
2621
const transformer = makeTransform(babelParser, babelGenerate);
@@ -92,11 +87,14 @@ export default async function bundleSource(
9287
// its source lines back to the right place.
9388
// eslint-disable-next-line no-await-in-loop
9489
const consumer = await new SourceMapConsumer(chunk.map);
90+
const unmapped = new WeakSet();
9591
let lastPos = ast.loc.start;
9692
unmapLoc = loc => {
97-
if (!loc) {
93+
if (!loc || unmapped.has(loc)) {
9894
return;
9995
}
96+
// Ensure we start in the right position... doesn't matter where we end.
97+
loc.end = loc.start;
10098
for (const pos of ['start', 'end']) {
10199
if (loc[pos]) {
102100
const newPos = consumer.originalPositionFor(loc[pos]);
@@ -108,29 +106,46 @@ export default async function bundleSource(
108106
loc[pos] = lastPos;
109107
}
110108
}
109+
unmapped.add(loc);
111110
};
112111
}
113112

113+
const rewriteComment = node => {
114+
node.type = 'CommentBlock';
115+
node.value = node.value
116+
.replace(/^\s*/gm, '') // Strip extraneous comment whitespace.
117+
.replace(HTML_COMMENT_START_RE, '<!X-')
118+
.replace(HTML_COMMENT_END_RE, '-X>')
119+
.replace(IMPORT_RE, 'X$1$2');
120+
if (unmapLoc) {
121+
unmapLoc(node.loc);
122+
}
123+
// console.log(JSON.stringify(node, undefined, 2));
124+
};
125+
114126
babelTraverse(ast, {
115127
enter(p) {
116128
const { loc, leadingComments, trailingComments } = p.node;
117-
// Remove all comments.
118-
removeComments(leadingComments);
119-
removeComments(trailingComments);
129+
if (p.node.comments) {
130+
p.node.comments = [];
131+
}
132+
// Rewrite all comments.
133+
(leadingComments || []).forEach(rewriteComment);
120134
if (p.node.type.startsWith('Comment')) {
121-
p.replaceWithMultiple([]);
122-
return;
135+
rewriteComment(p.node);
123136
}
124137
// If not a comment, and we are unmapping the source maps,
125138
// then do it for this location.
126139
if (unmapLoc) {
127140
unmapLoc(loc);
128141
}
142+
(trailingComments || []).forEach(rewriteComment);
129143
},
130144
});
131145

132146
// Now generate the sources with the new positions.
133147
sourceBundle[fileName] = babelGenerate(ast, { retainLines: true }).code;
148+
// console.log(`==== sourceBundle[${fileName}]\n${sourceBundle[fileName]}\n====`);
134149
}
135150

136151
if (!entrypoint) {

packages/bundle-source/test/sanity.js

+6
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ test('nestedEvaluate', async t => {
3939
'bundled source is in stack trace with correct line number',
4040
);
4141

42+
const err2 = bundle.makeError2('bar');
43+
t.assert(
44+
err2.stack.indexOf('(/bundled-source/index.js:9:') >= 0,
45+
'bundled source is in second stack trace with correct line number',
46+
);
47+
4248
const {
4349
moduleFormat: mf2,
4450
source: src2,

0 commit comments

Comments
 (0)