Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions docs/errors/RDDT0002.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
outline: deep
---

# RDDT0002: JSON Parse Stream Bad Line
# RDDT0002: Rolldown Log Reader Bad Line

## Message

> JSON parse stream skip bad line {line}: {error}
> Rolldown log reader skipped bad line {line}: {error}

## Cause

Rolldown writes its build logs as newline-delimited JSON (NDJSON). When the devtools plugin reads these files, it parses each line individually using `JSON.parse`. If a line cannot be parsed as valid JSON, this warning is emitted and the line is skipped.
Rolldown writes its build logs as newline-delimited JSON (NDJSON). When the devtools plugin reads these files, it parses each line individually. If a line cannot be parsed as a valid Rolldown debug event, this warning is emitted and the line is skipped.

Common reasons a line might fail to parse:

Expand All @@ -30,4 +30,4 @@ This warning is non-fatal -- the bad line is skipped and processing continues wi

## Source

- [`packages/rolldown/src/node/utils/json-parse-stream.ts`](https://github.com/vitejs/devtools/blob/main/packages/rolldown/src/node/utils/json-parse-stream.ts) — the NDJSON line parser logs `RDDT0002` (with the line number, error message, and a 256-char preview) and skips the line when `JSON.parse` throws.
- [`packages/rolldown/src/node/rolldown/events-reader.ts`](https://github.com/vitejs/devtools/blob/main/packages/rolldown/src/node/rolldown/events-reader.ts) — `readEventLines()` logs `RDDT0002` with the line number, error message, and a 256-character preview when parsing a log line fails.
2 changes: 1 addition & 1 deletion docs/errors/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,4 @@ Emitted by `@vitejs/devtools-rolldown`.
| Code | Level | Title |
|------|-------|-------|
| [RDDT0001](./RDDT0001) | warn | Rolldown Logs Directory Not Found |
| [RDDT0002](./RDDT0002) | warn | JSON Parse Stream Bad Line |
| [RDDT0002](./RDDT0002) | warn | Rolldown Log Reader Bad Line |
3 changes: 1 addition & 2 deletions packages/rolldown/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,13 @@
"p-limit": "catalog:deps",
"pathe": "catalog:deps",
"publint": "catalog:deps",
"split2": "catalog:deps",
"tinyglobby": "catalog:deps",
"unconfig": "catalog:deps",
"unstorage": "catalog:deps",
"vue-virtual-scroller": "catalog:frontend",
"ws": "catalog:deps"
},
"devDependencies": {
"@types/split2": "catalog:types",
"@types/splitpanes": "catalog:types",
"@unocss/nuxt": "catalog:build",
"@vueuse/components": "catalog:frontend",
Expand Down Expand Up @@ -115,6 +113,7 @@
"read-yaml-file": "2.1.0",
"semver": "7.8.0",
"signal-exit": "4.1.0",
"split2": "4.2.0",
"strip-bom": "4.0.0",
"strip-comments-strings": "1.2.0",
"write-file-atomic": "5.0.1",
Expand Down
39 changes: 22 additions & 17 deletions packages/rolldown/src/app/components/assets/Folder.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import type { ModuleDest, RolldownAssetInfo, SessionContext } from '~~/shared/types'
import { computed } from 'vue'
import { toTree } from '../../utils/format'
import DisplayVirtualTree from '../display/VirtualTree.vue'

const props = defineProps<{
assets: RolldownAssetInfo[]
Expand All @@ -19,26 +20,30 @@ const assetTree = computed(() => {
})

const assetsMap = computed(() => new Map<string, RolldownAssetInfo>(props.assets.map(a => [a.filename, a])))

const assetTreeRoots = computed(() => [
{
key: 'assets',
node: assetTree.value,
icon: 'i-catppuccin:folder-dist catppuccin',
iconOpen: 'i-catppuccin:folder-dist-open catppuccin',
},
])
</script>

<template>
<div flex="~ gap-2" p4>
<DisplayTreeNode
v-if="assets?.length"
flex-1
:node="assetTree"
icon="i-catppuccin:folder-dist catppuccin"
icon-open="i-catppuccin:folder-dist-open catppuccin"
:link="true"
link-query-key="asset"
>
<template #extra="{ node }">
<span op50>
({{ assetsMap.get(node.full)?.chunk?.name?.replace(/[\[\]]/g, '') }})
</span>
</template>
</DisplayTreeNode>
</div>
<DisplayVirtualTree
v-if="assets?.length"
:roots="assetTreeRoots"
:link="true"
link-query-key="asset"
>
<template #extra="{ node }">
<span op50>
({{ assetsMap.get(node.full)?.chunk?.name?.replace(/[\[\]]/g, '') }})
</span>
</template>
</DisplayVirtualTree>
</template>

<style scoped>
Expand Down
16 changes: 13 additions & 3 deletions packages/rolldown/src/app/components/assets/List.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,29 @@
import type { RolldownAssetInfo } from '~~/shared/types'
import DataVirtualList from '@vitejs/devtools-ui/components/DataVirtualList.vue'

defineProps<{
withDefaults(defineProps<{
assets: RolldownAssetInfo[]
}>()
itemSize?: number
pageMode?: boolean
scroller?: 'dynamic' | 'window'
}>(), {
itemSize: 40,
pageMode: true,
scroller: 'window',
})
</script>

<template>
<div p4>
<DataVirtualList
:items="assets"
key-prop="filename"
:item-size="itemSize"
:page-mode="pageMode"
:scroller="scroller"
>
<template #default="{ item }">
<div flex pb2>
<div h-10 flex>
<AssetsListItem :asset="item" />
</div>
</template>
Expand Down
8 changes: 4 additions & 4 deletions packages/rolldown/src/app/components/assets/ListItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ defineProps<{
<template>
<NuxtLink
:to="{ query: { asset: asset.filename } }"
w-full font-mono border="~ rounded base" px2 py1 text-sm hover="bg-active"
block h-8 w-full min-w-0 overflow-hidden font-mono border="~ rounded base" px2 py1 text-sm hover="bg-active"
>
<div flex="~ gap-1">
<DisplayFileIcon :filename="asset.filename" />
<span overflow-hidden text-ellipsis break-all line-clamp-2>
<div h-full min-w-0 flex="~ gap-1 items-center">
<DisplayFileIcon :filename="asset.filename" flex-none />
<span min-w-0 overflow-hidden text-ellipsis whitespace-nowrap>
{{ asset.filename }}
<span op50>
({{ asset.chunk?.name?.replace(/[\[\]]/g, '') }})
Expand Down
8 changes: 8 additions & 0 deletions packages/rolldown/src/app/components/chunks/FlatList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,14 @@ withDefaults(defineProps<{
session: SessionContext
link?: boolean
basic?: boolean
itemSize?: number
pageMode?: boolean
scroller?: 'dynamic' | 'window'
}>(), {
link: true,
basic: false,
pageMode: true,
scroller: 'dynamic',
})

const emit = defineEmits<{
Expand All @@ -22,6 +27,9 @@ const emit = defineEmits<{
<DataVirtualList
:items="chunks"
key-prop="chunk_id"
:item-size="itemSize"
:page-mode="pageMode"
:scroller="scroller"
>
<template #default="{ item }">
<div flex pb2 @click="emit('select', item)">
Expand Down
123 changes: 80 additions & 43 deletions packages/rolldown/src/app/components/chunks/Graph.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import type { ChunkImport } from '@rolldown/debug'
import type { RolldownChunkInfo, SessionContext } from '~~/shared/types/data'
import type { ModuleGraphLink, ModuleGraphNode } from '~/composables/module-graph'
import DisplayBadge from '@vitejs/devtools-ui/components/DisplayBadge.vue'
import { computed, nextTick, unref } from 'vue'
import { computed, unref } from 'vue'
import { useRoute } from '#app/composables/router'
import { createModuleGraph } from '~/composables/module-graph'
import { createModuleGraph, getModuleGraphSize } from '~/composables/module-graph'

type ChunkInfo = RolldownChunkInfo & {
id: string
Expand All @@ -20,6 +20,8 @@ const props = withDefaults(defineProps<{

const chunks = computed(() => props.chunks)
const route = useRoute()
const DEFAULT_EXPANDED_DEPTH = 3
const DEFAULT_EXPANDED_SIBLINGS = 10

createModuleGraph<ChunkInfo, ChunkImport>({
modules: chunks,
Expand All @@ -31,7 +33,34 @@ createModuleGraph<ChunkInfo, ChunkImport>({
gap: 150,
},
generateGraph: (options) => {
const { isFirstCalculateGraph, scale, spacing, tree, hierarchy, collapsedNodes, container, modulesMap, nodes, links, nodesMap, linksMap, width, height, childToParentMap } = options
const { isFirstCalculateGraph, spacing, tree, hierarchy, collapsedNodes, modulesMap, nodes, links, nodesMap, linksMap, width, height, childToParentMap } = options

function registerChildParent(moduleId: string, parentId: string) {
const existingParentId = childToParentMap.get(moduleId)
if (existingParentId && existingParentId !== parentId) {
return false
}
if (!existingParentId) {
childToParentMap.set(moduleId, parentId)
}
return true
}

function createNode(module: ChunkInfo, depth: number, chunkImport?: ChunkImport, siblingIndex = 0): ModuleGraphNode<ChunkInfo, ChunkImport> {
const defaultCollapsed = depth >= DEFAULT_EXPANDED_DEPTH || siblingIndex >= DEFAULT_EXPANDED_SIBLINGS
if (isFirstCalculateGraph.value && defaultCollapsed && module.imports.length > 0) {
collapsedNodes.add(module.id)
}

return {
module,
import: chunkImport,
depth,
expanded: !collapsedNodes.has(module.id),
hasChildren: false,
}
}

return () => {
width.value = window.innerWidth
height.value = window.innerHeight
Expand All @@ -45,43 +74,30 @@ createModuleGraph<ChunkInfo, ChunkImport>({
if (`${parent.module?.id}` === '~root') {
entryChunks.forEach((x) => {
seen.add(x)

if (isFirstCalculateGraph.value) {
childToParentMap.set(x.id, '~root')
}
registerChildParent(x.id, '~root')
})
return entryChunks.map(x => ({
module: x,
expanded: !collapsedNodes.has(x.id),
hasChildren: false,
}))
return entryChunks.map((x, index) => createNode(x, 1, undefined, index))
}

if (collapsedNodes.has(`${parent.module?.id}`)) {
return []
}

const nodes = parent.module.imports
?.map((x): ModuleGraphNode<ChunkInfo, ChunkImport> | undefined => {
const module = modulesMap.value.get(`${x.chunk_id}`)
if (!module || seen.has(module))
return undefined

if (isFirstCalculateGraph.value) {
childToParentMap.set(module.id, parent.module.id)
}
const depth = (parent.depth ?? 0) + 1
const childNodes: ModuleGraphNode<ChunkInfo, ChunkImport>[] = []
for (const chunkImport of parent.module.imports) {
const module = modulesMap.value.get(`${chunkImport.chunk_id}`)
if (!module || seen.has(module))
continue

seen.add(module)
if (!registerChildParent(module.id, parent.module.id))
continue

return {
module,
expanded: !collapsedNodes.has(module.id),
hasChildren: false,
}
})
.filter(x => x !== undefined)
seen.add(module)
childNodes.push(createNode(module, depth, chunkImport, childNodes.length))
}

return nodes
return childNodes
},
)

Expand All @@ -99,6 +115,15 @@ createModuleGraph<ChunkInfo, ChunkImport>({
for (const node of _nodes) {
// Rotate the graph from top-down to left-right
[node.x, node.y] = [node.y! - unref(spacing.width), node.x!]

if (node.data.module.imports) {
node.data.hasChildren = node.data.module.imports
?.some((chunkImport) => {
const chunkId = `${chunkImport.chunk_id}`
const parentId = childToParentMap.get(chunkId)
return modulesMap.value.has(chunkId) && (!parentId || parentId === node.data.module.id)
})
}
}

// Offset the graph and adding margin
Expand Down Expand Up @@ -130,15 +155,28 @@ createModuleGraph<ChunkInfo, ChunkImport>({
}
})

const _additionalLinks = chunks.value.flatMap(chunk =>
chunk.imports
.filter(_import => !_links.some(x => x.id === `${chunk.chunk_id}|${_import.chunk_id}`))
.map(_import => ({
source: nodesMap.get(`${chunk.chunk_id}`)!,
target: nodesMap.get(`${_import.chunk_id}`)!,
id: `${chunk.chunk_id}|${_import.chunk_id}`,
})),
)
const linkIds = new Set(_links.map(link => link.id))
const _additionalLinks: ModuleGraphLink<ChunkInfo, ChunkImport>[] = []
for (const chunk of chunks.value) {
const source = nodesMap.get(`${chunk.chunk_id}`)
if (!source)
continue

for (const chunkImport of chunk.imports) {
const id = `${chunk.chunk_id}|${chunkImport.chunk_id}`
const target = nodesMap.get(`${chunkImport.chunk_id}`)
if (!target || linkIds.has(id))
continue

_additionalLinks.push({
source,
target,
import: chunkImport,
id,
})
linkIds.add(id)
}
}

const normalizedLinks = [..._links, ..._additionalLinks]

Expand All @@ -148,10 +186,9 @@ createModuleGraph<ChunkInfo, ChunkImport>({
}
links.value = normalizedLinks

nextTick(() => {
width.value = (container.value!.scrollWidth / scale.value + unref(spacing.margin))
height.value = (container.value!.scrollHeight / scale.value + unref(spacing.margin))
})
const graphSize = getModuleGraphSize(_nodes, spacing)
width.value = graphSize.width
height.value = graphSize.height
}
},
})
Expand Down
Loading
Loading