From 49989ad30c79f45cccc56e7b1c51d0e52fa45d57 Mon Sep 17 00:00:00 2001 From: Yuxuan Zhang Date: Tue, 15 Apr 2025 17:45:59 -0400 Subject: [PATCH] use symbols to avoid enumeration of injected keys --- src/node/config.ts | 4 ++-- src/shared/shared.ts | 16 +++++++++------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/node/config.ts b/src/node/config.ts index 2fd6373a..cee15ed8 100644 --- a/src/node/config.ts +++ b/src/node/config.ts @@ -15,7 +15,7 @@ import type { DefaultTheme } from './defaultTheme' import { resolvePages } from './plugins/dynamicRoutesPlugin' import { APPEARANCE_KEY, - VP_SOURCE_KEY, + VP_CONFIG_SOURCE, isObject, slash, type AdditionalConfig, @@ -219,7 +219,7 @@ async function gatherAdditionalConfig( ) if (mode === 'development') { - ;(configExports.config as any)[VP_SOURCE_KEY] = '/' + slash(file) + ;(configExports.config as any)[VP_CONFIG_SOURCE] = '/' + slash(file) } return [id, configExports.config as AdditionalConfig] as const diff --git a/src/shared/shared.ts b/src/shared/shared.ts index a100faf9..5c047e1c 100644 --- a/src/shared/shared.ts +++ b/src/shared/shared.ts @@ -25,7 +25,11 @@ export type { export const EXTERNAL_URL_RE = /^(?:[a-z]+:|\/\/)/i export const APPEARANCE_KEY = 'vitepress-theme-appearance' -export const VP_SOURCE_KEY = '[VP_SOURCE]' +// Global symbols will be preserved by living-object. +export const VP_CONFIG_SOURCE = Symbol.for('VP:ConfigSource') +export const VP_CLIENT_ONLY = Symbol.for('VP:ClientOnly') +// Private symbols are distinct in each runtime environment. +// This should only be used internally. const UnpackStackView = Symbol('stack-view:unpack') const HASH_RE = /#.*$/ @@ -111,7 +115,7 @@ export function resolveSiteDataByRoute( const additionalConfigs = resolveAdditionalConfig(siteData, relativePath) if (inBrowser && (import.meta as any).env?.DEV) { - ;(localeConfig as any)[VP_SOURCE_KEY] = `locale config (${localeIndex})` + ;(localeConfig as any)[VP_CONFIG_SOURCE] = `locale config (${localeIndex})` reportConfigLayers(relativePath, [ ...additionalConfigs, localeConfig, @@ -296,7 +300,7 @@ function reportConfigLayers(path: string, layers: Partial[]) { const summary = layers.map((c, i, arr) => { const n = i + 1 if (n === arr.length) return `${n}. .vitepress/config (root)` - return `${n}. ${(c as any)?.[VP_SOURCE_KEY] ?? '(Unknown Source)'}` + return `${n}. ${(c as any)?.[VP_CONFIG_SOURCE] ?? '(Unknown Source)'}` }) console.debug( @@ -353,15 +357,13 @@ export function isObject(value: unknown): value is ObjectType { return Object.prototype.toString.call(value) === '[object Object]' } -const ClientOnlyMarker = Symbol.for('vitepress:client-only') - export function clientOnly(object: T) { - ;(object as any)[ClientOnlyMarker] = true + ;(object as any)[VP_CLIENT_ONLY] = true return object } export function isClientOnly(object?: T): boolean { - return (object as any)?.[ClientOnlyMarker] ?? false + return (object as any)?.[VP_CLIENT_ONLY] ?? false } export function propagateClientOnly(src: T, dst: T): T {