Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 | 101x 101x 101x 101x 101x 101x 101x 2763x 2588x 159x 16x 2880x 101x 1037x 3x 1034x 101x 1195x 101x 100x 101x 869x 3198x 6x 6x 6x 3192x 10x 3182x 3182x 302x 2880x 2880x 133x 2747x 2747x 2747x 101x 3882x 72x 3810x 101x 10168x 101x 1115x 101x 3463x 101x 10005x 10005x 101x 3547x 3547x 101x 1270x 101x 46x | import { isObject, toRawType, def } from '@vue/shared' import { mutableHandlers, readonlyHandlers, shallowReactiveHandlers, shallowReadonlyHandlers } from './baseHandlers' import { mutableCollectionHandlers, readonlyCollectionHandlers, shallowCollectionHandlers, shallowReadonlyCollectionHandlers } from './collectionHandlers' import type { UnwrapRefSimple, Ref, RawSymbol } from './ref' export const enum ReactiveFlags { SKIP = '__v_skip', IS_REACTIVE = '__v_isReactive', IS_READONLY = '__v_isReadonly', IS_SHALLOW = '__v_isShallow', RAW = '__v_raw' } export interface Target { [ReactiveFlags.SKIP]?: boolean [ReactiveFlags.IS_REACTIVE]?: boolean [ReactiveFlags.IS_READONLY]?: boolean [ReactiveFlags.IS_SHALLOW]?: boolean [ReactiveFlags.RAW]?: any } export const reactiveMap = new WeakMap<Target, any>() export const shallowReactiveMap = new WeakMap<Target, any>() export const readonlyMap = new WeakMap<Target, any>() export const shallowReadonlyMap = new WeakMap<Target, any>() const enum TargetType { INVALID = 0, COMMON = 1, COLLECTION = 2 } function targetTypeMap(rawType: string) { switch (rawType) { case 'Object': case 'Array': return TargetType.COMMON case 'Map': case 'Set': case 'WeakMap': case 'WeakSet': return TargetType.COLLECTION default: return TargetType.INVALID } } function getTargetType(value: Target) { return value[ReactiveFlags.SKIP] || !Object.isExtensible(value) ? TargetType.INVALID : targetTypeMap(toRawType(value)) } // only unwrap nested ref export type UnwrapNestedRefs<T> = T extends Ref ? T : UnwrapRefSimple<T> /** * Creates a deeply-reactive copy of the original object. * * All (deep) refs within the object will be unwrapped, while maintaining the * ref's reactivity. This is also done for refs that are assigned after creation * of the proxy object. * * Note that the proxy object is not equal to the original object in the ES2015 * Proxy-based implementation. It is **strongly** recommended to work * exclusively with the reactive proxy and avoid relying on the original object. * * @example * ```js * const count = ref(1) * const obj = reactive({ count }) * * console.log(obj.count) // 1 (ref is unwrapped, no need for .value) * * // updating the ref will update `obj.count` * count.value++ * console.log(obj.count) // 2 * * // updating the reactive property will update the ref, too * obj.count++ * console.log(count.value) // 3 * ``` * * @param target The source object. */ export function reactive<T extends object>(target: T): UnwrapNestedRefs<T> export function reactive(target: object) { // if trying to observe a readonly proxy, return the readonly version. if (isReadonly(target)) { return target } return createReactiveObject( target, false, mutableHandlers, mutableCollectionHandlers, reactiveMap ) } export declare const ShallowReactiveMarker: unique symbol export type ShallowReactive<T> = T & { [ShallowReactiveMarker]?: true } /** * Creates a shallowly-reactive copy of the original object. * * Does **not** unwrap any nested refs. All nested values are presented "raw". * * @example * ```js * const count = ref(1) * const obj = shallowReactive({ count }) * * console.log(obj.count.value) // 1 (not unwrapped) * ``` * * @param target The source object. */ export function shallowReactive<T extends object>( target: T ): ShallowReactive<T> { return createReactiveObject( target, false, shallowReactiveHandlers, shallowCollectionHandlers, shallowReactiveMap ) } type Primitive = string | number | boolean | bigint | symbol | undefined | null type Builtin = Primitive | Function | Date | Error | RegExp export type DeepReadonly<T> = T extends Builtin ? T : T extends Map<infer K, infer V> ? ReadonlyMap<DeepReadonly<K>, DeepReadonly<V>> : T extends ReadonlyMap<infer K, infer V> ? ReadonlyMap<DeepReadonly<K>, DeepReadonly<V>> : T extends WeakMap<infer K, infer V> ? WeakMap<DeepReadonly<K>, DeepReadonly<V>> : T extends Set<infer U> ? ReadonlySet<DeepReadonly<U>> : T extends ReadonlySet<infer U> ? ReadonlySet<DeepReadonly<U>> : T extends WeakSet<infer U> ? WeakSet<DeepReadonly<U>> : T extends Promise<infer U> ? Promise<DeepReadonly<U>> : T extends Ref<infer U> ? Readonly<Ref<DeepReadonly<U>>> : T extends {} ? { readonly [K in keyof T]: DeepReadonly<T[K]> } : Readonly<T> /** * Creates a readonly copy of the original object. * * All (deep) properties within the proxy object will be readonly, too. As with * `reactive`, all (deep) refs will be unwrapped. The returned object will not * be reactive by default, but already-reactive objects can be passed to * `readonly`. * * @example * ```js * const original = reactive({ count: 0 }) * * const copy = readonly(original) * * watchEffect(() => { * // works for reactivity tracking * console.log(copy.count) * }) * * // mutating original will trigger watchers relying on the copy * original.count++ * * // mutating the copy will fail and result in a warning * copy.count++ // warning! * ``` * * @param target The source object. */ export function readonly<T extends object>( target: T ): DeepReadonly<UnwrapNestedRefs<T>> { return createReactiveObject( target, true, readonlyHandlers, readonlyCollectionHandlers, readonlyMap ) } /** * Returns a shallowly-reactive readonly copy of the original object. * * All nested values are presented "raw". This means that **neither** nested * values are made readonly **nor** nested refs are unwrapped. * * @example * ```js * const state = shallowReadonly({ * foo: 1, * nested: { * bar: 2 * } * }) * * // mutating state's own properties will fail * state.foo++ * // ...but works on nested objects * isReadonly(state.nested) // false * state.nested.bar++ // works * ``` * * @remarks This is used for creating the props proxy object for stateful components. * * @param target The source object. */ export function shallowReadonly<T extends object>(target: T): Readonly<T> { return createReactiveObject( target, true, shallowReadonlyHandlers, shallowReadonlyCollectionHandlers, shallowReadonlyMap ) } function createReactiveObject( target: Target, isReadonly: boolean, baseHandlers: ProxyHandler<any>, collectionHandlers: ProxyHandler<any>, proxyMap: WeakMap<Target, any> ) { if (!isObject(target)) { if (__DEV__) { console.warn(`value cannot be made reactive: ${String(target)}`) } return target } // target is already a Proxy, return it. // exception: calling readonly() on a reactive object if ( target[ReactiveFlags.RAW] && !(isReadonly && target[ReactiveFlags.IS_REACTIVE]) ) { return target } // target already has corresponding Proxy const existingProxy = proxyMap.get(target) if (existingProxy) { return existingProxy } // only specific value types can be observed. const targetType = getTargetType(target) if (targetType === TargetType.INVALID) { return target } const proxy = new Proxy( target, targetType === TargetType.COLLECTION ? collectionHandlers : baseHandlers ) proxyMap.set(target, proxy) return proxy } /** * Checks if an object is a reactive proxy created by `reactive`. * * It also returns `true` if the given object was created by `readonly`, but is * wrapping another proxy created by `reactive`. * * @param value The value to check. */ export function isReactive(value: unknown): boolean { if (isReadonly(value)) { return isReactive((value as Target)[ReactiveFlags.RAW]) } return !!(value && (value as Target)[ReactiveFlags.IS_REACTIVE]) } /** * Checks if an object is a readonly proxy created by `readonly`. * * @param value The value to check. */ export function isReadonly(value: unknown): boolean { return !!(value && (value as Target)[ReactiveFlags.IS_READONLY]) } export function isShallow(value: unknown): boolean { return !!(value && (value as Target)[ReactiveFlags.IS_SHALLOW]) } /** * Checks if an object is a proxy created by `reactive` or `readonly`. * * @param value The value to check. */ export function isProxy(value: unknown): boolean { return isReactive(value) || isReadonly(value) } /** * Returns the raw, original object of a reactive or readonly proxy. * * This is an escape hatch that can be used to temporarily read without * incurring proxy access/tracking overhead or write without triggering changes. * It is **not** recommended to hold a persistent reference to the original * object. Use with caution. * * @example * ```js * const foo = {} * const reactiveFoo = reactive(foo) * * console.log(toRaw(reactiveFoo) === foo) // true * ``` * * @param observed The object for which the "raw" value is requested. */ export function toRaw<T>(observed: T): T { const raw = observed && (observed as Target)[ReactiveFlags.RAW] return raw ? toRaw(raw) : observed } export type Raw<T> = T & { [RawSymbol]?: true } /** * Marks an object so that it will never be converted to a proxy. * * **Warning:** This together with the `shallowXXX` APIs allow you to opt-out of * the default deep reactive/readonly conversion. This has its uses but must be * used in caution or you might end up with in raw, non-proxied objects in * places where you might not expect them. * * Returns the original object itself. * * @example * ```js * const foo = markRaw({}) * console.log(isReactive(reactive(foo))) // false * * // also works when nested inside other reactive objects * const bar = reactive({ foo }) * console.log(isReactive(bar.foo)) // false * ``` * * @param value The object to be marked as "raw". */ export function markRaw<T extends object>(value: T): Raw<T> { def(value, ReactiveFlags.SKIP, true) return value } /** * Returns a reactive proxy of the given value (if possible). * * If the given value is not an object, the original value itself is returned. * * @param value The value for which a reactive proxy shall be created. */ export const toReactive = <T extends unknown>(value: T): T => isObject(value) ? reactive(value) : value /** * Returns a readonly proxy of the given value (if possible). * * If the given value is not an object, the original value itself is returned. * * @param value The value for which a readonly proxy shall be created. */ export const toReadonly = <T extends unknown>(value: T): T => isObject(value) ? readonly(value as Record<any, any>) : value |