use symbols to avoid enumeration of injected keys

pull/4663/head
Yuxuan Zhang 5 months ago
parent 44657faa34
commit 49989ad30c
No known key found for this signature in database
GPG Key ID: 6910B04F3351EF7D

@ -15,7 +15,7 @@ import type { DefaultTheme } from './defaultTheme'
import { resolvePages } from './plugins/dynamicRoutesPlugin' import { resolvePages } from './plugins/dynamicRoutesPlugin'
import { import {
APPEARANCE_KEY, APPEARANCE_KEY,
VP_SOURCE_KEY, VP_CONFIG_SOURCE,
isObject, isObject,
slash, slash,
type AdditionalConfig, type AdditionalConfig,
@ -219,7 +219,7 @@ async function gatherAdditionalConfig(
) )
if (mode === 'development') { 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 return [id, configExports.config as AdditionalConfig] as const

@ -25,7 +25,11 @@ export type {
export const EXTERNAL_URL_RE = /^(?:[a-z]+:|\/\/)/i export const EXTERNAL_URL_RE = /^(?:[a-z]+:|\/\/)/i
export const APPEARANCE_KEY = 'vitepress-theme-appearance' 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 UnpackStackView = Symbol('stack-view:unpack')
const HASH_RE = /#.*$/ const HASH_RE = /#.*$/
@ -111,7 +115,7 @@ export function resolveSiteDataByRoute(
const additionalConfigs = resolveAdditionalConfig(siteData, relativePath) const additionalConfigs = resolveAdditionalConfig(siteData, relativePath)
if (inBrowser && (import.meta as any).env?.DEV) { 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, [ reportConfigLayers(relativePath, [
...additionalConfigs, ...additionalConfigs,
localeConfig, localeConfig,
@ -296,7 +300,7 @@ function reportConfigLayers(path: string, layers: Partial<SiteData>[]) {
const summary = layers.map((c, i, arr) => { const summary = layers.map((c, i, arr) => {
const n = i + 1 const n = i + 1
if (n === arr.length) return `${n}. .vitepress/config (root)` 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( console.debug(
@ -353,15 +357,13 @@ export function isObject(value: unknown): value is ObjectType {
return Object.prototype.toString.call(value) === '[object Object]' return Object.prototype.toString.call(value) === '[object Object]'
} }
const ClientOnlyMarker = Symbol.for('vitepress:client-only')
export function clientOnly<T extends object>(object: T) { export function clientOnly<T extends object>(object: T) {
;(object as any)[ClientOnlyMarker] = true ;(object as any)[VP_CLIENT_ONLY] = true
return object return object
} }
export function isClientOnly<T extends object>(object?: T): boolean { export function isClientOnly<T extends object>(object?: T): boolean {
return (object as any)?.[ClientOnlyMarker] ?? false return (object as any)?.[VP_CLIENT_ONLY] ?? false
} }
export function propagateClientOnly<T extends object>(src: T, dst: T): T { export function propagateClientOnly<T extends object>(src: T, dst: T): T {

Loading…
Cancel
Save