From d76acfdc17e27b53fc53e6cd3051ff0acaefef42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Tue, 17 May 2022 16:59:35 +0200 Subject: [PATCH] fix: base64 encoding of source maps with emojis (#14607) This commit fixes source maps for files that contain emojis. This is done by updating "deno_ast" to "0.14.1" for the case of "--no-check" flag (ie using SWC emit) and by overriding TSC's default base64 encoder (which turned out to be buggy) for the type checking case. --- Cargo.lock | 4 +- cli/emit.rs | 1 + cli/tests/testdata/coverage/complex.ts | 3 ++ .../testdata/coverage/complex_expected.lcov | 5 ++- .../testdata/coverage/complex_expected.out | 2 +- cli/tsc/99_main_compiler.js | 45 +++++++++++++++++++ cli/tsc/compiler.d.ts | 2 +- 7 files changed, 56 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1cc6904e47..2f81d70e6c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -811,9 +811,9 @@ dependencies = [ [[package]] name = "deno_ast" -version = "0.14.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc8868538999df5fae866dfe9841750fb57b45be49b948e173ad6a7023c0428c" +checksum = "f0691d08faa4f1fd9898ecfbe82c32623f89969e92e7b97b5119a18399609d25" dependencies = [ "anyhow", "base64 0.13.0", diff --git a/cli/emit.rs b/cli/emit.rs index b6eef0b88d..5896d0dff9 100644 --- a/cli/emit.rs +++ b/cli/emit.rs @@ -709,6 +709,7 @@ pub fn bundle( let emit_options: deno_ast::EmitOptions = options.ts_config.into(); let source_map_config = deno_ast::SourceMapConfig { inline_sources: emit_options.inline_sources, + maybe_base: None, }; let cm = Rc::new(swc::common::SourceMap::new( diff --git a/cli/tests/testdata/coverage/complex.ts b/cli/tests/testdata/coverage/complex.ts index 47d4ffa79a..d128b54373 100644 --- a/cli/tests/testdata/coverage/complex.ts +++ b/cli/tests/testdata/coverage/complex.ts @@ -69,3 +69,6 @@ export function ƒ(): number { // This arrow function should also show up as uncovered. console.log("%s", () => 1); + +// Make sure emojis work properly +console.log("📣❓"); diff --git a/cli/tests/testdata/coverage/complex_expected.lcov b/cli/tests/testdata/coverage/complex_expected.lcov index a0af4cff35..1bb79d2770 100644 --- a/cli/tests/testdata/coverage/complex_expected.lcov +++ b/cli/tests/testdata/coverage/complex_expected.lcov @@ -48,6 +48,7 @@ DA:66,0 DA:67,0 DA:68,1 DA:71,0 -LH:22 -LF:37 +DA:74,1 +LH:23 +LF:38 end_of_record diff --git a/cli/tests/testdata/coverage/complex_expected.out b/cli/tests/testdata/coverage/complex_expected.out index e9f9a453fd..e318e20673 100644 --- a/cli/tests/testdata/coverage/complex_expected.out +++ b/cli/tests/testdata/coverage/complex_expected.out @@ -1,4 +1,4 @@ -cover [WILDCARD]/coverage/complex.ts ... 59.459% (22/37) +cover [WILDCARD]/coverage/complex.ts ... 60.526% (23/38) 46 | export function unused( 47 | foo: string, 48 | bar: string, diff --git a/cli/tsc/99_main_compiler.js b/cli/tsc/99_main_compiler.js index 6d47b6ac70..362fdd7621 100644 --- a/cli/tsc/99_main_compiler.js +++ b/cli/tsc/99_main_compiler.js @@ -72,6 +72,43 @@ delete Object.prototype.__proto__; } } + // deno-fmt-ignore + const base64abc = [ + "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", + "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", + "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", + "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", + "8", "9", "+", "/", + ]; + + /** Taken from https://deno.land/std/encoding/base64.ts */ + function convertToBase64(data) { + const uint8 = core.encode(data); + let result = "", + i; + const l = uint8.length; + for (i = 2; i < l; i += 3) { + result += base64abc[uint8[i - 2] >> 2]; + result += base64abc[((uint8[i - 2] & 0x03) << 4) | (uint8[i - 1] >> 4)]; + result += base64abc[((uint8[i - 1] & 0x0f) << 2) | (uint8[i] >> 6)]; + result += base64abc[uint8[i] & 0x3f]; + } + if (i === l + 1) { + // 1 octet yet to write + result += base64abc[uint8[i - 2] >> 2]; + result += base64abc[(uint8[i - 2] & 0x03) << 4]; + result += "=="; + } + if (i === l) { + // 2 octets yet to write + result += base64abc[uint8[i - 2] >> 2]; + result += base64abc[((uint8[i - 2] & 0x03) << 4) | (uint8[i - 1] >> 4)]; + result += base64abc[(uint8[i - 1] & 0x0f) << 2]; + result += "="; + } + return result; + } + // In the case of the LSP, this is initialized with the assets // when snapshotting and never added to or removed after that. /** @type {Map} */ @@ -485,6 +522,14 @@ delete Object.prototype.__proto__; * @param {Request} request */ function exec({ config, debug: debugFlag, rootNames }) { + // https://github.com/microsoft/TypeScript/issues/49150 + ts.base64encode = function (host, input) { + if (host && host.base64encode) { + return host.base64encode(input); + } + return convertToBase64(input); + }; + setLogDebug(debugFlag, "TS"); performanceStart(); debug(">>> exec start", { rootNames }); diff --git a/cli/tsc/compiler.d.ts b/cli/tsc/compiler.d.ts index e844848842..7d935434ba 100644 --- a/cli/tsc/compiler.d.ts +++ b/cli/tsc/compiler.d.ts @@ -8,7 +8,7 @@ declare global { namespace ts { var libs: string[]; var libMap: Map; - + var base64encode: (host: ts.CompilerHost, input: string) => string; interface SourceFile { version?: string; }