From 16b66eb12d628d5230f32b2acb33457435a090bd Mon Sep 17 00:00:00 2001 From: Andrew Bradley Date: Sat, 22 May 2021 22:15:45 -0400 Subject: [PATCH] recognize when //# sourceMappingURL is percent-encoded (#1330) * recognize when //# sourceMappingURL is percent-encoded * lint-fix * dedupe const value * fix * use encodeURI instead of url.format because it seems closer to what TS does; it percent-encodes the square brackets in [eval].ts * remove unused import --- src/index.ts | 54 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/src/index.ts b/src/index.ts index e8d44384d..9aea226d4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1318,20 +1318,46 @@ function updateOutput( 'utf8' ).toString('base64'); const sourceMapContent = `//# sourceMappingURL=data:application/json;charset=utf-8;base64,${base64Map}`; - // Expected form: `//# sourceMappingURL=foo.js.map` for input file foo.tsx - const sourceMapLength = - /*//# sourceMappingURL=*/ 21 + - /*foo.tsx*/ basename(fileName).length - - /*.tsx*/ extname(fileName).length + - /*.js*/ getExtension(fileName).length + - /*.map*/ 4; - // Only rewrite if existing directive exists, to support compilers that do not append a sourcemap directive - return ( - (outputText.slice(-sourceMapLength, -sourceMapLength + 21) === - '//# sourceMappingURL=' - ? outputText.slice(0, -sourceMapLength) - : outputText) + sourceMapContent - ); + // Expected form: `//# sourceMappingURL=foo bar.js.map` or `//# sourceMappingURL=foo%20bar.js.map` for input file "foo bar.tsx" + // Percent-encoding behavior added in TS 4.1.1: https://github.com/microsoft/TypeScript/issues/40951 + const prefix = '//# sourceMappingURL='; + const prefixLength = prefix.length; + const baseName = /*foo.tsx*/ basename(fileName); + const extName = /*.tsx*/ extname(fileName); + const extension = /*.js*/ getExtension(fileName); + const sourcemapFilename = + baseName.slice(0, -extName.length) + extension + '.map'; + const sourceMapLengthWithoutPercentEncoding = + prefixLength + sourcemapFilename.length; + /* + * Only rewrite if existing directive exists at the location we expect, to support: + * a) compilers that do not append a sourcemap directive + * b) situations where we did the math wrong + * Not ideal, but appending our sourcemap *after* a pre-existing sourcemap still overrides, so the end-user is happy. + */ + if ( + outputText.substr(-sourceMapLengthWithoutPercentEncoding, prefixLength) === + prefix + ) { + return ( + outputText.slice(0, -sourceMapLengthWithoutPercentEncoding) + + sourceMapContent + ); + } + // If anyone asks why we're not using URL, the URL equivalent is: `u = new URL('http://d'); u.pathname = "/" + sourcemapFilename; return u.pathname.slice(1); + const sourceMapLengthWithPercentEncoding = + prefixLength + encodeURI(sourcemapFilename).length; + if ( + outputText.substr(-sourceMapLengthWithPercentEncoding, prefixLength) === + prefix + ) { + return ( + outputText.slice(0, -sourceMapLengthWithPercentEncoding) + + sourceMapContent + ); + } + + return `${outputText}\n${sourceMapContent}`; } /**