From a2139133a6442802298b90d66d655f726e4996b4 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 20 Nov 2019 17:13:10 -0800 Subject: [PATCH 01/13] Fix relative paths in wasm backend source maps. Fixes #9837 --- tests/test_other.py | 15 +++++++++++++++ tools/wasm-sourcemap.py | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/tests/test_other.py b/tests/test_other.py index 68f80cb566b60..e0a594ba3a308 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -8909,6 +8909,21 @@ def test_wasm_sourcemap_dead(self): # has only two entries self.assertRegexpMatches(output, r'"mappings":\s*"[A-Za-z0-9+/]+,[A-Za-z0-9+/]+"') + def test_wasm_sourcemap_relative_paths(self): + filename = 'a.cpp' + shutil.copyfile(path_from_root('tests', 'hello_123.c'), 'a.cpp') + filenames = [ + filename, + os.path.abspath(filename) + ] + if not WINDOWS: + filenames.append('./' + filename) + for curr in filenames: + print(curr) + run_process([PYTHON, EMCC, curr, '-g4']) + with open('a.out.wasm.map', 'r') as f: + self.assertIn('"a.cpp"', str(f.read())) + def test_wasm_producers_section(self): # no producers section by default run_process([PYTHON, EMCC, path_from_root('tests', 'hello_world.c')]) diff --git a/tools/wasm-sourcemap.py b/tools/wasm-sourcemap.py index 240647747d665..53de5d6664650 100755 --- a/tools/wasm-sourcemap.py +++ b/tools/wasm-sourcemap.py @@ -263,7 +263,7 @@ def build_sourcemap(entries, code_section_offset, prefixes, collect_sources): if column == 0: column = 1 address = entry['address'] + code_section_offset - file_name = entry['file'] + file_name = os.path.relpath(entry['file']) source_name = prefixes.sources.resolve(file_name) if source_name not in sources_map: source_id = len(sources) From 4c2cf4a8709c2e72928482d4591a317805045ec9 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 21 Nov 2019 13:21:34 -0800 Subject: [PATCH 02/13] fix --- tests/test_other.py | 5 ++--- tools/shared.py | 6 +++++- tools/wasm-sourcemap.py | 8 ++++---- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/tests/test_other.py b/tests/test_other.py index 659d0f9a429e7..cdbfe7d79aa8a 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -8921,10 +8921,9 @@ def test_wasm_sourcemap_relative_paths(self): shutil.copyfile(path_from_root('tests', 'hello_123.c'), 'a.cpp') filenames = [ filename, - os.path.abspath(filename) - ] - if not WINDOWS: + os.path.abspath(filename), filenames.append('./' + filename) + ] for curr in filenames: print(curr) run_process([PYTHON, EMCC, curr, '-g4']) diff --git a/tools/shared.py b/tools/shared.py index 7b0598a03bfc1..0d40e44625b11 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -2871,10 +2871,14 @@ def path_to_system_js_libraries(library_name): @staticmethod def emit_wasm_source_map(wasm_file, map_file): + # source file paths must be relative to the location of the map (which is + # emitted alongside the wasm) + base_path = os.path.dirname(os.path.abspath(Settings.WASM_BINARY_FILE)) sourcemap_cmd = [PYTHON, path_from_root('tools', 'wasm-sourcemap.py'), wasm_file, '--dwarfdump=' + LLVM_DWARFDUMP, - '-o', map_file] + '-o', map_file, + '--basepath=' + base_path] check_call(sourcemap_cmd) @staticmethod diff --git a/tools/wasm-sourcemap.py b/tools/wasm-sourcemap.py index 53de5d6664650..3e452ee184f31 100755 --- a/tools/wasm-sourcemap.py +++ b/tools/wasm-sourcemap.py @@ -39,6 +39,7 @@ def parse_args(): parser.add_argument('-u', '--source-map-url', nargs='?', help='specifies sourceMappingURL section contest') parser.add_argument('--dwarfdump', help="path to llvm-dwarfdump executable") parser.add_argument('--dwarfdump-output', nargs='?', help=argparse.SUPPRESS) + parser.add_argument('--basepath', help='base path for source files, which will be relative to this') return parser.parse_args() @@ -243,11 +244,10 @@ def read_dwarf_entries(wasm, options): return sorted(entries, key=lambda entry: entry['address']) -def build_sourcemap(entries, code_section_offset, prefixes, collect_sources): +def build_sourcemap(entries, code_section_offset, prefixes, collect_sources, base_path): sources = [] sources_content = [] if collect_sources else None mappings = [] - sources_map = {} last_address = 0 last_source_id = 0 @@ -263,7 +263,7 @@ def build_sourcemap(entries, code_section_offset, prefixes, collect_sources): if column == 0: column = 1 address = entry['address'] + code_section_offset - file_name = os.path.relpath(entry['file']) + file_name = os.path.relpath(os.path.abspath(entry['file']), base_path) source_name = prefixes.sources.resolve(file_name) if source_name not in sources_map: source_id = len(sources) @@ -311,7 +311,7 @@ def main(): prefixes = SourceMapPrefixes(sources=Prefixes(options.prefix), load=Prefixes(options.load_prefix)) logger.debug('Saving to %s' % options.output) - map = build_sourcemap(entries, code_section_offset, prefixes, options.sources) + map = build_sourcemap(entries, code_section_offset, prefixes, options.sources, options.basepath) with open(options.output, 'w') as outfile: json.dump(map, outfile, separators=(',', ':')) From 842caafc63ee8c336b5dd7bd6bb79e57f205ce4e Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 21 Nov 2019 13:27:28 -0800 Subject: [PATCH 03/13] test --- tests/test_other.py | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/tests/test_other.py b/tests/test_other.py index cdbfe7d79aa8a..6e62ecd455ed9 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -8917,18 +8917,25 @@ def test_wasm_sourcemap_dead(self): self.assertRegexpMatches(output, r'"mappings":\s*"[A-Za-z0-9+/]+,[A-Za-z0-9+/]+"') def test_wasm_sourcemap_relative_paths(self): - filename = 'a.cpp' - shutil.copyfile(path_from_root('tests', 'hello_123.c'), 'a.cpp') - filenames = [ - filename, - os.path.abspath(filename), - filenames.append('./' + filename) - ] - for curr in filenames: - print(curr) - run_process([PYTHON, EMCC, curr, '-g4']) - with open('a.out.wasm.map', 'r') as f: - self.assertIn('"a.cpp"', str(f.read())) + def test(infile, source_map_added_dir=''): + expected_source_map_path = os.path.join(source_map_added_dir, 'a.cpp') + print(infile, expected_source_map_path) + shutil.copyfile(path_from_root('tests', 'hello_123.c'), infile) + infiles = [ + infile, + os.path.abspath(infile), + './' + infile + ] + for curr in infiles: + print(' ', curr) + run_process([PYTHON, EMCC, curr, '-g4']) + with open('a.out.wasm.map', 'r') as f: + self.assertIn('"%s"' % expected_source_map_path, str(f.read())) + + test('a.cpp') + + os.mkdir('inner') + test(os.path.join('inner', 'a.cpp'), 'inner') def test_wasm_producers_section(self): # no producers section by default From acef71d24a9f963e040ca6f05eaac16b64aa20b2 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 21 Nov 2019 13:28:44 -0800 Subject: [PATCH 04/13] fix test --- tests/test_core.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_core.py b/tests/test_core.py index 4268ed737e330..f60bb5a443522 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -7188,7 +7188,7 @@ def encode_utf8(data): # the output file. self.assertPathsIdentical(map_referent, data['file']) assert len(data['sources']) == 1, data['sources'] - self.assertPathsIdentical(os.path.abspath('src.cpp'), data['sources'][0]) + self.assertPathsIdentical('src.cpp', data['sources'][0]) if hasattr(data, 'sourcesContent'): # the sourcesContent attribute is optional, but if it is present it # needs to containt valid source text. @@ -7201,7 +7201,7 @@ def encode_utf8(data): mappings = encode_utf8(mappings) seen_lines = set() for m in mappings: - self.assertPathsIdentical(os.path.abspath('src.cpp'), m['source']) + self.assertPathsIdentical('src.cpp', m['source']) seen_lines.add(m['originalLine']) # ensure that all the 'meaningful' lines in the original code get mapped # when optimizing, the binaryen optimizer may remove some of them (by inlining, etc.) From a9467bd40ef211eb4e66ee31d1b009d5c036b50c Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 21 Nov 2019 13:34:01 -0800 Subject: [PATCH 05/13] [ci skip] --- tests/test_core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_core.py b/tests/test_core.py index f60bb5a443522..580cf50157bc4 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -8241,7 +8241,7 @@ def test_ubsan_full_static_cast(self, args): 'g4': ('-g4', [ "src.cpp:3:12: runtime error: reference binding to null pointer of type 'int'", 'in main ', - '/src.cpp:3:8' + 'src.cpp:3:8' ]), }) @no_fastcomp('ubsan not supported on fastcomp') From 18ac680d2a863de921f5a5f2f6cec060bffae22e Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 21 Nov 2019 13:55:27 -0800 Subject: [PATCH 06/13] for now --- tests/test_other.py | 6 ++++-- tools/wasm-sourcemap.py | 6 +++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/test_other.py b/tests/test_other.py index 6e62ecd455ed9..b86bf5e2cf030 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -8895,7 +8895,8 @@ def test_wasm_sourcemap(self): '--dwarfdump-output', path_from_root('tests', 'other', 'wasm_sourcemap', 'foo.wasm.dump'), '-o', 'a.out.wasm.map', - path_from_root('tests', 'other', 'wasm_sourcemap', 'foo.wasm')] + path_from_root('tests', 'other', 'wasm_sourcemap', 'foo.wasm'), + '--basepath=' + os.getcwd()] run_process(wasm_map_cmd) output = open('a.out.wasm.map').read() # has "sources" entry with file (includes also `--prefix =wasm-src:///` replacement) @@ -8910,7 +8911,8 @@ def test_wasm_sourcemap_dead(self): '--dwarfdump-output', path_from_root('tests', 'other', 'wasm_sourcemap_dead', 't.wasm.dump'), '-o', 'a.out.wasm.map', - path_from_root('tests', 'other', 'wasm_sourcemap_dead', 't.wasm')] + path_from_root('tests', 'other', 'wasm_sourcemap_dead', 't.wasm'), + '--basepath=' + os.getcwd()] run_process(wasm_map_cmd, stdout=PIPE, stderr=PIPE) output = open('a.out.wasm.map').read() # has only two entries diff --git a/tools/wasm-sourcemap.py b/tools/wasm-sourcemap.py index 3e452ee184f31..3ac3b58b7311a 100755 --- a/tools/wasm-sourcemap.py +++ b/tools/wasm-sourcemap.py @@ -263,7 +263,11 @@ def build_sourcemap(entries, code_section_offset, prefixes, collect_sources, bas if column == 0: column = 1 address = entry['address'] + code_section_offset - file_name = os.path.relpath(os.path.abspath(entry['file']), base_path) + file_name = entry['file'] + # TODO: support relative path resolvement with collect_sources. for now, + # emcc does not use that flag, so it's not urgent + if not collect_sources: + file_name = os.path.relpath(os.path.abspath(file_name), base_path) source_name = prefixes.sources.resolve(file_name) if source_name not in sources_map: source_id = len(sources) From c9a3bd08fc06f41c5b9fda3df4b6aba6e903c9a0 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 21 Nov 2019 14:24:56 -0800 Subject: [PATCH 07/13] for now --- tools/wasm-sourcemap.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tools/wasm-sourcemap.py b/tools/wasm-sourcemap.py index 3ac3b58b7311a..4efd3b5bed286 100755 --- a/tools/wasm-sourcemap.py +++ b/tools/wasm-sourcemap.py @@ -267,7 +267,16 @@ def build_sourcemap(entries, code_section_offset, prefixes, collect_sources, bas # TODO: support relative path resolvement with collect_sources. for now, # emcc does not use that flag, so it's not urgent if not collect_sources: - file_name = os.path.relpath(os.path.abspath(file_name), base_path) + # prefer to emit a relative path to the base path, which is where the + # source map file itself is, so the browser can find it. however, if they + # have no shared prefix (like one is /a/b and the other /c/d) then we + # would not end up with anything more useful (like ../../c/d), so avoid + # that + abs_file_name = os.path.abspath(file_name) + print(abs_file_name, base_path, os.path.commonprefix([abs_file_name, base_path])) + if os.path.commonprefix([abs_file_name, base_path]): + file_name = os.path.relpath(abs_file_name, base_path) + print('waka', entry['file'], ' becomes ', file_name, ' due to ', base_path) source_name = prefixes.sources.resolve(file_name) if source_name not in sources_map: source_id = len(sources) From bb04bd944693389c1163a9b86b046bc0e264d716 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 21 Nov 2019 14:28:23 -0800 Subject: [PATCH 08/13] fix --- tools/wasm-sourcemap.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tools/wasm-sourcemap.py b/tools/wasm-sourcemap.py index 4efd3b5bed286..4ec56fca14db8 100755 --- a/tools/wasm-sourcemap.py +++ b/tools/wasm-sourcemap.py @@ -271,12 +271,10 @@ def build_sourcemap(entries, code_section_offset, prefixes, collect_sources, bas # source map file itself is, so the browser can find it. however, if they # have no shared prefix (like one is /a/b and the other /c/d) then we # would not end up with anything more useful (like ../../c/d), so avoid - # that + # that (a shared prefix of size 1, like '/', is useless) abs_file_name = os.path.abspath(file_name) - print(abs_file_name, base_path, os.path.commonprefix([abs_file_name, base_path])) - if os.path.commonprefix([abs_file_name, base_path]): + if len(os.path.commonprefix([abs_file_name, base_path])) > 1: file_name = os.path.relpath(abs_file_name, base_path) - print('waka', entry['file'], ' becomes ', file_name, ' due to ', base_path) source_name = prefixes.sources.resolve(file_name) if source_name not in sources_map: source_id = len(sources) From 917b74c798e479c271fd9d2828eb2a8ec277f66e Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 21 Nov 2019 14:28:56 -0800 Subject: [PATCH 09/13] simpler --- tools/wasm-sourcemap.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/tools/wasm-sourcemap.py b/tools/wasm-sourcemap.py index 4ec56fca14db8..a4343415eb266 100755 --- a/tools/wasm-sourcemap.py +++ b/tools/wasm-sourcemap.py @@ -264,17 +264,14 @@ def build_sourcemap(entries, code_section_offset, prefixes, collect_sources, bas column = 1 address = entry['address'] + code_section_offset file_name = entry['file'] - # TODO: support relative path resolvement with collect_sources. for now, - # emcc does not use that flag, so it's not urgent - if not collect_sources: - # prefer to emit a relative path to the base path, which is where the - # source map file itself is, so the browser can find it. however, if they - # have no shared prefix (like one is /a/b and the other /c/d) then we - # would not end up with anything more useful (like ../../c/d), so avoid - # that (a shared prefix of size 1, like '/', is useless) - abs_file_name = os.path.abspath(file_name) - if len(os.path.commonprefix([abs_file_name, base_path])) > 1: - file_name = os.path.relpath(abs_file_name, base_path) + # prefer to emit a relative path to the base path, which is where the + # source map file itself is, so the browser can find it. however, if they + # have no shared prefix (like one is /a/b and the other /c/d) then we + # would not end up with anything more useful (like ../../c/d), so avoid + # that (a shared prefix of size 1, like '/', is useless) + abs_file_name = os.path.abspath(file_name) + if len(os.path.commonprefix([abs_file_name, base_path])) > 1: + file_name = os.path.relpath(abs_file_name, base_path) source_name = prefixes.sources.resolve(file_name) if source_name not in sources_map: source_id = len(sources) From 3b15d9ee9cb614aefefe72544049555cf0721b65 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 21 Nov 2019 15:05:24 -0800 Subject: [PATCH 10/13] fastcomp fixes --- tests/test_core.py | 10 ++++++++-- tests/test_other.py | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/test_core.py b/tests/test_core.py index 580cf50157bc4..2b8609a507ef0 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -7179,6 +7179,12 @@ def encode_utf8(data): else: return data + def source_map_file_loc(name): + if shared.Settings.WASM_BACKEND: + return name + # in fastcomp, we have the absolute path, which is not good + return os.path.abspath(name) + data = json.load(open(map_filename)) if str is bytes: # Python 2 compatibility @@ -7188,7 +7194,7 @@ def encode_utf8(data): # the output file. self.assertPathsIdentical(map_referent, data['file']) assert len(data['sources']) == 1, data['sources'] - self.assertPathsIdentical('src.cpp', data['sources'][0]) + self.assertPathsIdentical(source_map_file_loc('src.cpp'), data['sources'][0]) if hasattr(data, 'sourcesContent'): # the sourcesContent attribute is optional, but if it is present it # needs to containt valid source text. @@ -7201,7 +7207,7 @@ def encode_utf8(data): mappings = encode_utf8(mappings) seen_lines = set() for m in mappings: - self.assertPathsIdentical('src.cpp', m['source']) + self.assertPathsIdentical(source_map_file_loc('src.cpp'), m['source']) seen_lines.add(m['originalLine']) # ensure that all the 'meaningful' lines in the original code get mapped # when optimizing, the binaryen optimizer may remove some of them (by inlining, etc.) diff --git a/tests/test_other.py b/tests/test_other.py index b86bf5e2cf030..26a5ff42bb79a 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -8918,6 +8918,7 @@ def test_wasm_sourcemap_dead(self): # has only two entries self.assertRegexpMatches(output, r'"mappings":\s*"[A-Za-z0-9+/]+,[A-Za-z0-9+/]+"') + @no_fastcomp() def test_wasm_sourcemap_relative_paths(self): def test(infile, source_map_added_dir=''): expected_source_map_path = os.path.join(source_map_added_dir, 'a.cpp') From 8412ca778d9f487d663148680a09af0e84fee4e4 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Tue, 26 Nov 2019 11:26:50 -0800 Subject: [PATCH 11/13] review feedback --- tools/wasm-sourcemap.py | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/tools/wasm-sourcemap.py b/tools/wasm-sourcemap.py index a4343415eb266..400b5e933ae3f 100755 --- a/tools/wasm-sourcemap.py +++ b/tools/wasm-sourcemap.py @@ -74,7 +74,13 @@ def resolve(self, name): # SourceMapPrefixes contains resolver for file names that are: # - "sources" is for names that output to source maps JSON # - "load" is for paths that used to load source text -SourceMapPrefixes = namedtuple('SourceMapPrefixes', 'sources, load') +class SourceMapPrefixes: + def __init__(self, sources, load): + self.sources = sources + self.load = load + + def provided(self): + return bool(self.sources.prefixes or self.load.prefixes) def encode_vlq(n): @@ -264,15 +270,13 @@ def build_sourcemap(entries, code_section_offset, prefixes, collect_sources, bas column = 1 address = entry['address'] + code_section_offset file_name = entry['file'] - # prefer to emit a relative path to the base path, which is where the - # source map file itself is, so the browser can find it. however, if they - # have no shared prefix (like one is /a/b and the other /c/d) then we - # would not end up with anything more useful (like ../../c/d), so avoid - # that (a shared prefix of size 1, like '/', is useless) - abs_file_name = os.path.abspath(file_name) - if len(os.path.commonprefix([abs_file_name, base_path])) > 1: - file_name = os.path.relpath(abs_file_name, base_path) - source_name = prefixes.sources.resolve(file_name) + # if prefixes were provided, we use that; otherwise, we emit a relative + # path + if prefixes.provided(): + source_name = prefixes.sources.resolve(file_name) + else: + file_name = os.path.relpath(os.path.abspath(file_name), base_path) + source_name = file_name if source_name not in sources_map: source_id = len(sources) sources_map[source_name] = source_id From f2b99094f72b02321f17203de8666a1332201dd9 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 27 Nov 2019 10:00:53 -0800 Subject: [PATCH 12/13] update lsan tests to allow relative paths in stack traces --- tests/test_other.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/test_other.py b/tests/test_other.py index 89c1e8775de8f..1612dabcc2001 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -9692,17 +9692,17 @@ def test_lsan_leaks(self, ext): @parameterized({ 'c': ['c', [ r'in malloc.*a\.out\.wasm\+0x', - r'(?im)in f (/|[a-z]:).*/test_lsan_leaks\.c:6:21$', - r'(?im)in main (/|[a-z]:).*/test_lsan_leaks\.c:10:16$', - r'(?im)in main (/|[a-z]:).*/test_lsan_leaks\.c:12:3$', - r'(?im)in main (/|[a-z]:).*/test_lsan_leaks\.c:13:3$', + r'(?im)in f (|[/a-z\.]:).*/test_lsan_leaks\.c:6:21$', + r'(?im)in main (|[/a-z\.]:).*/test_lsan_leaks\.c:10:16$', + r'(?im)in main (|[/a-z\.]:).*/test_lsan_leaks\.c:12:3$', + r'(?im)in main (|[/a-z\.]:).*/test_lsan_leaks\.c:13:3$', ]], 'cpp': ['cpp', [ r'in operator new\[\]\(unsigned long\).*a\.out\.wasm\+0x', - r'(?im)in f\(\) (/|[a-z]:).*/test_lsan_leaks\.cpp:4:21$', - r'(?im)in main (/|[a-z]:).*/test_lsan_leaks\.cpp:8:16$', - r'(?im)in main (/|[a-z]:).*/test_lsan_leaks\.cpp:10:3$', - r'(?im)in main (/|[a-z]:).*/test_lsan_leaks\.cpp:11:3$', + r'(?im)in f\(\) (|[/a-z\.]:).*/test_lsan_leaks\.cpp:4:21$', + r'(?im)in main (|[/a-z\.]:).*/test_lsan_leaks\.cpp:8:16$', + r'(?im)in main (|[/a-z\.]:).*/test_lsan_leaks\.cpp:10:3$', + r'(?im)in main (|[/a-z\.]:).*/test_lsan_leaks\.cpp:11:3$', ]], }) @no_fastcomp('lsan not supported on fastcomp') From 450097cd7e4320672043b4e5a8cb0687bfd3a475 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 27 Nov 2019 10:15:22 -0800 Subject: [PATCH 13/13] flake8 --- tools/wasm-sourcemap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/wasm-sourcemap.py b/tools/wasm-sourcemap.py index 400b5e933ae3f..6c1c9abfbfc23 100755 --- a/tools/wasm-sourcemap.py +++ b/tools/wasm-sourcemap.py @@ -11,7 +11,7 @@ """ import argparse -from collections import OrderedDict, namedtuple +from collections import OrderedDict import json import logging from math import floor, log