Compare commits

...

1 Commits

Author SHA1 Message Date
Shoubhit Dash
e7f4d851f6 fix(ui): avoid WebKit diff viewer crashes 2026-03-16 16:53:02 +05:30
4 changed files with 9 additions and 66 deletions

View File

@@ -6,13 +6,7 @@ import { useWorkerPool } from "../context/worker-pool"
import { createDefaultOptions, styleVariables } from "../pierre"
import { markCommentedDiffLines } from "../pierre/commented-lines"
import { fixDiffSelection } from "../pierre/diff-selection"
import {
applyViewerScheme,
clearReadyWatcher,
createReadyWatcher,
notifyShadowReady,
observeViewerScheme,
} from "../pierre/file-runtime"
import { clearReadyWatcher, createReadyWatcher, notifyShadowReady } from "../pierre/file-runtime"
import { acquireVirtualizer, virtualMetrics } from "../pierre/virtualizer"
import { File, type DiffFileProps, type FileProps } from "./file"
@@ -87,8 +81,6 @@ function DiffSSRViewer<T>(props: SSRDiffFileProps<T>) {
onMount(() => {
if (isServer) return
onCleanup(observeViewerScheme(() => fileDiffRef))
const virtualizer = getVirtualizer()
fileDiffInstance = virtualizer
? new VirtualizedFileDiff<T>(
@@ -110,8 +102,6 @@ function DiffSSRViewer<T>(props: SSRDiffFileProps<T>) {
workerPool,
)
applyViewerScheme(fileDiffRef)
// @ts-expect-error private field required for hydration
fileDiffInstance.fileContainer = fileDiffRef
fileDiffInstance.hydrate({

View File

@@ -16,20 +16,12 @@ import {
} from "@pierre/diffs"
import { type PreloadMultiFileDiffResult } from "@pierre/diffs/ssr"
import { createMediaQuery } from "@solid-primitives/media"
import { ComponentProps, createEffect, createMemo, createSignal, onCleanup, onMount, Show, splitProps } from "solid-js"
import { ComponentProps, createEffect, createMemo, createSignal, onCleanup, Show, splitProps } from "solid-js"
import { createDefaultOptions, styleVariables } from "../pierre"
import { markCommentedDiffLines, markCommentedFileLines } from "../pierre/commented-lines"
import { fixDiffSelection, findDiffSide, type DiffSelectionSide } from "../pierre/diff-selection"
import { createFileFind } from "../pierre/file-find"
import {
applyViewerScheme,
clearReadyWatcher,
createReadyWatcher,
getViewerHost,
getViewerRoot,
notifyShadowReady,
observeViewerScheme,
} from "../pierre/file-runtime"
import { clearReadyWatcher, createReadyWatcher, getViewerRoot, notifyShadowReady } from "../pierre/file-runtime"
import {
findCodeSelectionSide,
findDiffLineNumber,
@@ -154,7 +146,6 @@ function useFileViewer(config: ViewerConfig) {
const [rendered, setRendered] = createSignal(0)
const getRoot = () => getViewerRoot(container)
const getHost = () => getViewerHost(container)
const find = createFileFind({
wrapper: () => wrapper,
@@ -265,10 +256,6 @@ function useFileViewer(config: ViewerConfig) {
// -- shared effects --
onMount(() => {
onCleanup(observeViewerScheme(getHost))
})
createEffect(() => {
rendered()
const ranges = config.commentedLines()
@@ -351,7 +338,6 @@ function useFileViewer(config: ViewerConfig) {
rendered,
setRendered,
getRoot,
getHost,
find,
scheduleSelectionUpdate,
}
@@ -486,7 +472,6 @@ function renderViewer<I extends RenderTarget>(opts: {
opts.viewer.container.innerHTML = ""
opts.draw(next)
applyViewerScheme(opts.viewer.getHost())
opts.viewer.setRendered((value) => value + 1)
opts.onReady()
}

View File

@@ -23,31 +23,6 @@ export function getViewerRoot(container: HTMLElement | undefined) {
return getViewerHost(container)?.shadowRoot ?? undefined
}
export function applyViewerScheme(host: HTMLElement | undefined) {
if (!host) return
if (typeof document === "undefined") return
const scheme = document.documentElement.dataset.colorScheme
if (scheme === "dark" || scheme === "light") {
host.dataset.colorScheme = scheme
return
}
host.removeAttribute("data-color-scheme")
}
export function observeViewerScheme(getHost: () => HTMLElement | undefined) {
if (typeof document === "undefined") return () => {}
applyViewerScheme(getHost())
if (typeof MutationObserver === "undefined") return () => {}
const root = document.documentElement
const monitor = new MutationObserver(() => applyViewerScheme(getHost()))
monitor.observe(root, { attributes: true, attributeFilter: ["data-color-scheme"] })
return () => monitor.disconnect()
}
export function notifyShadowReady(opts: {
state: ReadyWatcher
container: HTMLElement

View File

@@ -37,26 +37,19 @@ const unsafeCSS = `
--diffs-bg-addition-emphasis: var(--diffs-bg-addition-emphasis-override, light-dark(rgb(from var(--diffs-addition-base) r g b / 0.07), rgb(from var(--diffs-addition-base) r g b / 0.1)));
--diffs-selection-base: var(--surface-warning-strong);
--diffs-selection-border: var(--border-warning-base);
--diffs-selection-number-fg: #1c1917;
--diffs-selection-number-fg: light-dark(#1c1917, #fdfbfb);
/* Use explicit alpha instead of color-mix(..., transparent) to avoid Safari's non-premultiplied interpolation bugs. */
--diffs-bg-selection: var(--diffs-bg-selection-override, rgb(from var(--surface-warning-base) r g b / 0.65));
--diffs-bg-selection: var(
--diffs-bg-selection-override,
light-dark(rgb(from var(--surface-warning-base) r g b / 0.65), rgb(from var(--solaris-dark-6) r g b / 0.65))
);
--diffs-bg-selection-number: var(
--diffs-bg-selection-number-override,
rgb(from var(--surface-warning-base) r g b / 0.85)
light-dark(rgb(from var(--surface-warning-base) r g b / 0.85), rgb(from var(--solaris-dark-6) r g b / 0.85))
);
--diffs-bg-selection-text: rgb(from var(--surface-warning-strong) r g b / 0.2);
}
:host([data-color-scheme='dark']) [data-diff],
:host([data-color-scheme='dark']) [data-file] {
--diffs-selection-number-fg: #fdfbfb;
--diffs-bg-selection: var(--diffs-bg-selection-override, rgb(from var(--solaris-dark-6) r g b / 0.65));
--diffs-bg-selection-number: var(
--diffs-bg-selection-number-override,
rgb(from var(--solaris-dark-6) r g b / 0.85)
);
}
[data-diff] ::selection,
[data-file] ::selection {
background-color: var(--diffs-bg-selection-text);