Skip to content

Commit be74046

Browse files
committed
Fix generated JS output to not insert indentation characters inside multiline `` strings.
1 parent 1f46cb4 commit be74046

File tree

5 files changed

+70
-6
lines changed

5 files changed

+70
-6
lines changed

src/parseTools.mjs

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -331,14 +331,39 @@ function splitI64(value) {
331331
export function indentify(text, indent) {
332332
// Don't try to indentify huge strings - we may run out of memory
333333
if (text.length > 1024 * 1024) return text;
334-
if (typeof indent == 'number') {
335-
const len = indent;
336-
indent = '';
337-
for (let i = 0; i < len; i++) {
338-
indent += ' ';
334+
335+
indent = ' '.repeat(indent);
336+
337+
// Perform indentation in a smart fashion that does not leak indentation
338+
// inside multiline strings enclosed in `` characters.
339+
let out = '';
340+
for (let i = 0; i < text.length; ++i) {
341+
// Output a C++ comment as-is, don't get confused by ` inside a C++ comment.
342+
if (text[i] == '/' && text[i + 1] == '/') {
343+
for (; i < text.length && text[i] != '\n'; ++i) {
344+
out += text[i];
345+
}
346+
}
347+
348+
if (text[i] == '/' && text[i + 1] == '*') {
349+
// Skip /* so that /*/ won't be mistaken as start& end of a /* */ comment.
350+
out += text[i++];
351+
out += text[i++];
352+
for (; i < text.length && !(text[i - 1] == '*' && text[i] == '/'); ++i) {
353+
out += text[i];
354+
}
355+
}
356+
357+
if (text[i] == '`') {
358+
out += text[i++]; // Emit `
359+
for (; i < text.length && text[i] != '`'; ++i) {
360+
out += text[i];
361+
}
339362
}
363+
out += text[i];
364+
if (text[i] == '\n') out += indent;
340365
}
341-
return text.replace(/\n/g, `\n${indent}`);
366+
return out;
342367
}
343368

344369
// Correction tools

test/test_multiline_string.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
4+
char *test_multiline_string(void);
5+
6+
int main() {
7+
char *str = test_multiline_string();
8+
printf("%s\n", str);
9+
free(str);
10+
}

test/test_multiline_string.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
mergeInto(LibraryManager.library, {
2+
test_multiline_string__deps: ['$stringToNewUTF8'],
3+
test_multiline_string__sig: 'p',
4+
test_multiline_string: function() {
5+
// do not get confused by ` inside a comment.
6+
var a = `abc
7+
def
8+
ghi`;
9+
/* or a ` inside a C comment. */
10+
var b = `abc
11+
def
12+
ghi`;
13+
return stringToNewUTF8(a + b);
14+
}
15+
});

test/test_multiline_string.out

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
abc
2+
def
3+
ghiabc
4+
def
5+
ghi

test/test_other.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15283,3 +15283,12 @@ def test_binary_encode(self, extra):
1528315283
console.log('OK');'''
1528415284
write_file('test.js', read_file(path_from_root('src/binaryDecode.js')) + '\nvar src = ' + binary_encoded + ';\n' + test_js)
1528515285
self.assertContained('OK', self.run_js('test.js'))
15286+
15287+
# Tests that JS library functions containing multiline strings are not disturbed by e.g. inserting indentation into the output.
15288+
@parameterized({
15289+
'': ([],),
15290+
'single_file': (['-sSINGLE_FILE'],),
15291+
'closure': (['--closure', '1'],),
15292+
})
15293+
def test_multiline_string(self, args):
15294+
self.do_run_in_out_file_test('test_multiline_string.c', cflags=['--js-library', test_file('test_multiline_string.js')] + args)

0 commit comments

Comments
 (0)