From 5efcd754ede1f34e293ba29c1e254ee6ac6a9fbb Mon Sep 17 00:00:00 2001 From: Tommaso De Rossi Date: Wed, 28 Jun 2023 12:53:26 +0200 Subject: [PATCH] feat: inspect sourcemaps button (#79) Co-authored-by: Anthony Fu --- src/client/logic/utils.ts | 56 +++++++++++++++++++++++++++++++ src/client/pages/index/module.vue | 22 ++++++++++-- src/node/index.ts | 9 ++--- src/types.ts | 1 + 4 files changed, 82 insertions(+), 6 deletions(-) diff --git a/src/client/logic/utils.ts b/src/client/logic/utils.ts index f57f26e..b9bc8d1 100644 --- a/src/client/logic/utils.ts +++ b/src/client/logic/utils.ts @@ -33,3 +33,59 @@ export function guessMode(code: string) { return 'css' return 'javascript' } + +export function inspectSourcemaps({ code, sourcemaps }: { + code: string + sourcemaps?: string +}) { + // easier debugging of sourcemaps + // eslint-disable-next-line no-console + console.info('sourcemaps', JSON.stringify(sourcemaps, null, 2)) + + const serialized = serializeForSourcemapsVisualizer(code, sourcemaps!) + // open link in new tab + window.open(`https://evanw.github.io/source-map-visualization#${serialized}`, '_blank') +} + +export function safeJsonParse(str: string) { + try { + return JSON.parse(str) + } + catch (e) { + console.error('Failed to parse JSON', str) + return null + } +} + +// serialize to base64 and delimited by null characters and code length +// parser code: https://github.com/evanw/source-map-visualization/blob/5c08ef62f3eff597796f1b5c73ae822d9f467d00/code.js#L1794 +function serializeForSourcemapsVisualizer(code: string, map: string) { + const encoder = new TextEncoder() + + // Convert the strings to Uint8Array + const codeArray = encoder.encode(code) + const mapArray = encoder.encode(map) + + // Create Uint8Array for the lengths + const codeLengthArray = encoder.encode(codeArray.length.toString()) + const mapLengthArray = encoder.encode(mapArray.length.toString()) + + // Combine the lengths and the data + const combinedArray = new Uint8Array(codeLengthArray.length + 1 + codeArray.length + mapLengthArray.length + 1 + mapArray.length) + + combinedArray.set(codeLengthArray) + combinedArray.set([0], codeLengthArray.length) + combinedArray.set(codeArray, codeLengthArray.length + 1) + combinedArray.set(mapLengthArray, codeLengthArray.length + 1 + codeArray.length) + combinedArray.set([0], codeLengthArray.length + 1 + codeArray.length + mapLengthArray.length) + combinedArray.set(mapArray, codeLengthArray.length + 1 + codeArray.length + mapLengthArray.length + 1) + + // Convert the Uint8Array to a binary string + let binary = '' + const len = combinedArray.byteLength + for (let i = 0; i < len; i++) + binary += String.fromCharCode(combinedArray[i]) + + // Convert the binary string to a base64 string and return it + return btoa(binary) +} diff --git a/src/client/pages/index/module.vue b/src/client/pages/index/module.vue index cac42a1..cc07f34 100644 --- a/src/client/pages/index/module.vue +++ b/src/client/pages/index/module.vue @@ -2,7 +2,7 @@ import { useRouteQuery } from '@vueuse/router' import { Pane, Splitpanes } from 'splitpanes' import { msToTime } from '../../logic/utils' -import { enableDiff, inspectSSR, lineWrapping, onRefetch, showOneColumn } from '../../logic' +import { enableDiff, inspectSSR, inspectSourcemaps, lineWrapping, onRefetch, safeJsonParse, showOneColumn } from '../../logic' import { rpc } from '../../logic/rpc' import type { HMRData } from '../../../types' import { getHot } from '../../logic/hot' @@ -26,6 +26,21 @@ watch([id, inspectSSR], refetch) const from = computed(() => data.value?.transforms[currentIndex.value - 1]?.result || '') const to = computed(() => data.value?.transforms[currentIndex.value]?.result || '') +const sourcemaps = computed(() => { + let sourcemaps = data.value?.transforms[currentIndex.value]?.sourcemaps + if (!sourcemaps) + return undefined + if (typeof sourcemaps === 'string') + sourcemaps = safeJsonParse(sourcemaps) + if (!sourcemaps?.mappings) + return + + if (sourcemaps && !sourcemaps.sourcesContent) { + sourcemaps.sourcesContent = [] + sourcemaps.sourcesContent[0] = from.value + } + return JSON.stringify(sourcemaps) +}) getHot().then((hot) => { if (hot) { @@ -54,6 +69,9 @@ getHot().then((hot) => { + @@ -83,7 +101,7 @@ getHot().then((hot) => {