CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-vue--runtime-core

Vue.js 3 runtime core library providing foundational APIs for building custom renderers and managing reactive component systems

Pending
Overview
Eval results
Files

reactivity.mddocs/

Reactivity System

Vue's reactivity system provides fine-grained reactive data structures with automatic dependency tracking. The system enables efficient updates by tracking which computations depend on which reactive data.

Capabilities

Reactive State Creation

Create reactive proxies that automatically track dependencies and trigger updates.

/**
 * Creates a reactive proxy of an object
 * @param target - Object to make reactive
 * @returns Reactive proxy of the target object
 */
function reactive<T extends object>(target: T): T;

/**
 * Creates a reactive reference wrapper for primitive values
 * @param value - Initial value to wrap
 * @returns Reactive reference object
 */
function ref<T>(value: T): Ref<T>;

/**
 * Creates a read-only proxy that prevents modifications
 * @param target - Object to make read-only
 * @returns Read-only proxy of the target
 */
function readonly<T>(target: T): DeepReadonly<T>;

/**
 * Creates a shallow reactive reference that only tracks .value changes
 * @param value - Initial value
 * @returns Shallow reactive reference
 */
function shallowRef<T>(value: T): ShallowRef<T>;

/**
 * Creates a shallow reactive proxy that only tracks first-level properties
 * @param target - Object to make shallow reactive
 * @returns Shallow reactive proxy
 */
function shallowReactive<T extends object>(target: T): ShallowReactive<T>;

/**
 * Creates a shallow read-only proxy
 * @param target - Object to make shallow read-only
 * @returns Shallow read-only proxy
 */
function shallowReadonly<T extends object>(target: T): Readonly<T>;

/**
 * Creates a custom ref with explicit dependency tracking control
 * @param factory - Factory function that returns get/set functions
 * @returns Custom reactive reference
 */
function customRef<T>(factory: CustomRefFactory<T>): Ref<T>;

Usage Examples:

import { reactive, ref, readonly, shallowRef } from "@vue/runtime-core";

// Reactive object
const state = reactive({
  count: 0,
  user: { name: "Alice", age: 25 }
});

// Reactive primitive
const count = ref(0);
count.value = 5; // Triggers reactivity

// Read-only state
const readonlyState = readonly(state);
// readonlyState.count = 10; // Error in TypeScript, ignored in runtime

// Shallow ref for complex objects
const complexData = shallowRef({ deep: { nested: { value: 1 } } });
complexData.value = { deep: { nested: { value: 2 } } }; // Triggers reactivity
complexData.value.deep.nested.value = 3; // Does NOT trigger reactivity

// Custom ref with debounced updates
function useDebouncedRef(value: string, delay = 200) {
  let timeout: NodeJS.Timeout;
  return customRef((track, trigger) => ({
    get() {
      track();
      return value;
    },
    set(newValue) {
      clearTimeout(timeout);
      timeout = setTimeout(() => {
        value = newValue;
        trigger();
      }, delay);
    }
  }));
}

Reactivity Utilities

Utility functions for working with reactive data and references.

/**
 * Returns the inner value if it's a ref, otherwise returns the value itself
 * @param ref - Value that may or may not be a ref
 * @returns Unwrapped value
 */
function unref<T>(ref: MaybeRef<T>): T;

/**
 * Creates a ref for a property on a reactive object
 * @param object - Reactive object
 * @param key - Property key
 * @returns Ref linked to the object property
 */
function toRef<T extends object, K extends keyof T>(object: T, key: K): ToRef<T[K]>;

/**
 * Converts all properties of a reactive object to refs
 * @param object - Reactive object to convert
 * @returns Object with all properties as refs
 */
function toRefs<T extends object>(object: T): ToRefs<T>;

/**
 * Returns the value of value/ref/getter
 * @param val - Value, ref, or getter function
 * @returns Resolved value
 */
function toValue<T>(val: MaybeRefOrGetter<T>): T;

/**
 * Proxies an object to auto-unwrap refs in properties
 * @param objectWithRefs - Object containing refs
 * @returns Proxy that auto-unwraps refs
 */
function proxyRefs<T extends object>(objectWithRefs: T): T;

/**
 * Checks if a value is a ref
 * @param val - Value to check
 * @returns True if value is a ref
 */
function isRef<T>(val: Ref<T> | unknown): val is Ref<T>;

/**
 * Checks if a value is a reactive proxy
 * @param val - Value to check
 * @returns True if value is reactive
 */
function isProxy(val: unknown): boolean;

/**
 * Checks if a value is reactive (not readonly)
 * @param val - Value to check
 * @returns True if value is reactive
 */
function isReactive(val: unknown): boolean;

/**
 * Checks if a value is readonly
 * @param val - Value to check
 * @returns True if value is readonly
 */
function isReadonly(val: unknown): boolean;

/**
 * Checks if a value is shallow
 * @param val - Value to check
 * @returns True if value is shallow
 */
function isShallow(val: unknown): boolean;

/**
 * Marks an object to never be converted to a proxy
 * @param value - Object to mark as raw
 * @returns The same object, marked as raw
 */
function markRaw<T extends object>(value: T): T;

/**
 * Returns the raw, original object of a reactive proxy
 * @param observed - Reactive proxy
 * @returns Original object
 */
function toRaw<T>(observed: T): T;

/**
 * Manually triggers effects for a shallow ref
 * @param ref - Shallow ref to trigger
 */
function triggerRef(ref: ShallowRef): void;

Usage Examples:

import { reactive, ref, toRefs, toRef, unref, isRef } from "@vue/runtime-core";

const state = reactive({ count: 0, name: "Vue" });

// Convert object properties to refs
const { count, name } = toRefs(state);
console.log(count.value); // 0

// Create ref for single property
const countRef = toRef(state, 'count');
countRef.value = 5; // Updates state.count

// Unwrap refs safely
function processValue(maybeRef: MaybeRef<number>) {
  const value = unref(maybeRef);
  return value * 2;
}

processValue(ref(5)); // 10
processValue(10); // 20

// Check if value is ref
if (isRef(count)) {
  console.log("count is a ref:", count.value);
}

Computed Properties

Create computed values that automatically update when their dependencies change.

/**
 * Creates a computed ref with getter only
 * @param getter - Function that returns computed value
 * @returns Read-only computed ref
 */
function computed<T>(getter: () => T): ComputedRef<T>;

/**
 * Creates a computed ref with getter and setter
 * @param options - Object with get and set functions
 * @returns Writable computed ref
 */
function computed<T>(options: WritableComputedOptions<T>): WritableComputedRef<T>;

interface WritableComputedOptions<T> {
  get: () => T;
  set: (value: T) => void;
}

Usage Examples:

import { ref, computed } from "@vue/runtime-core";

const count = ref(0);

// Read-only computed
const doubled = computed(() => count.value * 2);
console.log(doubled.value); // 0
count.value = 5;
console.log(doubled.value); // 10

// Writable computed
const fullName = ref("");
const firstName = ref("John");
const lastName = ref("Doe");

const computedFullName = computed({
  get: () => `${firstName.value} ${lastName.value}`,
  set: (value) => {
    const parts = value.split(' ');
    firstName.value = parts[0] || '';
    lastName.value = parts[1] || '';
  }
});

console.log(computedFullName.value); // "John Doe"
computedFullName.value = "Jane Smith";
console.log(firstName.value); // "Jane"
console.log(lastName.value); // "Smith"

Effect System

Create and manage reactive effects with fine-grained control over execution.

/**
 * Creates a reactive effect that runs when dependencies change
 * @param fn - Effect function to run
 * @param options - Optional effect configuration
 * @returns Effect runner function
 */
function effect(fn: () => void, options?: ReactiveEffectOptions): ReactiveEffectRunner;

/**
 * Stops a reactive effect from running
 * @param runner - Effect runner to stop
 */
function stop(runner: ReactiveEffectRunner): void;

/**
 * Gets the currently running watcher/effect
 * @returns Current reactive effect or undefined
 */
function getCurrentWatcher(): ReactiveEffect | undefined;

/**
 * Registers a cleanup function for the current watcher
 * @param fn - Cleanup function to register
 */
function onWatcherCleanup(fn: () => void): void;

interface ReactiveEffectOptions {
  scheduler?: EffectScheduler;
  scope?: EffectScope;
  allowRecurse?: boolean;
  onStop?: () => void;
}

interface ReactiveEffectRunner<T = any> {
  (): T;
  effect: ReactiveEffect;
}

Usage Examples:

import { ref, effect, stop } from "@vue/runtime-core";

const count = ref(0);
const name = ref("Vue");

// Basic effect
const runner = effect(() => {
  console.log(`Count is: ${count.value}`);
});

count.value = 1; // Logs: "Count is: 1"

// Effect with scheduler
const scheduledRunner = effect(
  () => {
    console.log(`Scheduled: ${name.value}`);
  },
  {
    scheduler: (job) => {
      // Custom scheduling logic
      setTimeout(job, 100);
    }
  }
);

// Stop an effect
stop(runner);
count.value = 2; // No longer logs

Effect Scope

Manage groups of effects with automatic cleanup.

/**
 * Creates an effect scope for managing multiple effects
 * @param detached - Whether the scope is detached from parent
 * @returns New effect scope
 */
function effectScope(detached?: boolean): EffectScope;

/**
 * Gets the current active effect scope
 * @returns Current effect scope or undefined
 */
function getCurrentScope(): EffectScope | undefined;

/**
 * Registers a dispose callback for the current scope
 * @param fn - Callback to run when scope is disposed
 */
function onScopeDispose(fn: () => void): void;

interface EffectScope {
  run<T>(fn: () => T): T | undefined;
  stop(): void;
}

Usage Examples:

import { ref, effect, effectScope, onScopeDispose } from "@vue/runtime-core";

const count = ref(0);

// Create a scope
const scope = effectScope();

scope.run(() => {
  // Effects created in this scope will be collected
  effect(() => {
    console.log(`Count: ${count.value}`);
  });
  
  effect(() => {
    console.log(`Count doubled: ${count.value * 2}`);
  });
  
  // Cleanup when scope is disposed
  onScopeDispose(() => {
    console.log("Scope disposed");
  });
});

count.value = 1; // Both effects run

// Stop all effects in scope
scope.stop(); // Logs: "Scope disposed"
count.value = 2; // No effects run

Types

interface Ref<T> {
  value: T;
}

interface ShallowRef<T> extends Ref<T> {
  /**
   * Type differentiator only.
   * We need this to be in public d.ts but don't want it to show up in IDE
   * autocomplete, so we use a private Symbol instead.
   */
  [ShallowRefMarker]?: true;
}

interface ComputedRef<T> extends WritableComputedRef<T> {
  readonly value: T;
}

interface WritableComputedRef<T> extends Ref<T> {
  readonly effect: ReactiveEffect<T>;
}

type MaybeRef<T> = T | Ref<T>;
type MaybeRefOrGetter<T> = T | Ref<T> | (() => T);

type ToRef<T> = T extends Ref ? T : Ref<T>;

type ToRefs<T> = {
  [K in keyof T]: ToRef<T[K]>;
};

type UnwrapRef<T> = T extends ShallowRef<infer V>
  ? V
  : T extends Ref<infer V>
  ? UnwrapRefSimple<V>
  : UnwrapRefSimple<T>;

interface CustomRefFactory<T> {
  (track: () => void, trigger: () => void): {
    get: () => T;
    set: (value: T) => void;
  };
}

interface ReactiveEffect<T = any> {
  (): T;
  _isEffect: true;
  id: number;
  active: boolean;
  raw: () => T;
  deps: Array<Dep>;
  options: ReactiveEffectOptions;
  allowRecurse: boolean;
}

type EffectScheduler = (fn: () => void) => void;

interface EffectScope {
  detached: boolean;
  parent: EffectScope | undefined;
  scopes: EffectScope[] | undefined;
  effects: ReactiveEffect[] | undefined;
  cleanups: (() => void)[] | undefined;
  
  run<T>(fn: () => T): T | undefined;
  on(): void;
  off(): void;
  stop(fromParent?: boolean): void;
}

Install with Tessl CLI

npx tessl i tessl/npm-vue--runtime-core

docs

asset-resolution.md

builtin-components.md

components.md

composition-helpers.md

dependency-injection.md

error-handling.md

hydration.md

index.md

internal-render-helpers.md

lifecycle.md

reactivity.md

scheduler-timing.md

ssr-context.md

vdom-rendering.md

watch-effects.md

tile.json