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

internal-render-helpers.mddocs/

Internal Render Helpers

Vue's internal render helpers provide low-level utilities for advanced rendering scenarios, custom renderers, and compiler-generated code. These APIs are primarily used by Vue's template compiler and custom renderer implementations.

Capabilities

Block Tracking

Control Vue's block tracking system for optimized re-rendering.

/**
 * Opens a new block for tracking dynamic children
 * @param disableTracking - Whether to disable tracking for this block
 */
function openBlock(disableTracking?: boolean): void;

/**
 * Creates a block VNode with tracked dynamic children
 * @param type - Element type or component
 * @param props - Element/component props
 * @param children - Child nodes
 * @param patchFlag - Optimization hints
 * @param dynamicProps - Names of dynamic props
 * @returns Block VNode
 */
function createBlock(
  type: VNodeTypes,
  props?: VNodeProps | null,
  children?: VNodeArrayChildren,
  patchFlag?: number,
  dynamicProps?: string[]
): VNode;

/**
 * Sets the block tracking value
 * @param value - Positive number enables tracking, 0 or negative disables
 */
function setBlockTracking(value: number): void;

Usage Examples:

import { openBlock, createBlock, setBlockTracking, h } from "@vue/runtime-core";

// Manual block creation (typically done by compiler)
const createOptimizedElement = () => {
  openBlock();
  
  return createBlock('div', { class: 'container' }, [
    h('span', 'Static content'),
    // Dynamic content will be tracked
    h('span', { key: Math.random() }, 'Dynamic content')
  ]);
};

// Disable tracking for certain scenarios
const createUnoptimizedElement = () => {
  setBlockTracking(-1); // Disable tracking
  
  const element = h('div', [
    h('span', 'This won\'t be optimized')
  ]);
  
  setBlockTracking(1); // Re-enable tracking
  
  return element;
};

// Conditional block tracking
const createConditionalBlock = (optimize: boolean) => {
  if (optimize) {
    openBlock();
    return createBlock('div', null, [
      // Children will be tracked for optimization
    ]);
  } else {
    return h('div', [
      // Children won't be tracked
    ]);
  }
};

VNode Creation Helpers

Low-level VNode creation functions for specific node types.

/**
 * Creates a text VNode
 * @param text - Text content
 * @param flag - Patch flag for optimization
 * @returns Text VNode
 */
function createTextVNode(text?: string, flag?: number): VNode;

/**
 * Creates a comment VNode
 * @param text - Comment content
 * @param asBlock - Whether to create as block
 * @returns Comment VNode
 */
function createCommentVNode(text?: string, asBlock?: boolean): VNode;

/**
 * Creates a static VNode for hoisted content
 * @param content - Static HTML content
 * @param numberOfNodes - Number of nodes in the content
 * @returns Static VNode
 */
function createStaticVNode(content: string, numberOfNodes: number): VNode;

/**
 * Creates an element VNode
 * @param type - Element tag name
 * @param props - Element properties
 * @param children - Child nodes
 * @param patchFlag - Optimization flag
 * @param dynamicProps - Dynamic property names
 * @returns Element VNode
 */
function createElementVNode(
  type: string,
  props?: VNodeProps | null,
  children?: VNodeArrayChildren,
  patchFlag?: number,
  dynamicProps?: string[]
): VNode;

/**
 * Creates an element block VNode (with tracking)
 * @param type - Element tag name
 * @param props - Element properties
 * @param children - Child nodes
 * @param patchFlag - Optimization flag
 * @param dynamicProps - Dynamic property names
 * @returns Element block VNode
 */
function createElementBlock(
  type: string,
  props?: VNodeProps | null,
  children?: VNodeArrayChildren,
  patchFlag?: number,
  dynamicProps?: string[]
): VNode;

Usage Examples:

import { 
  createTextVNode, 
  createCommentVNode, 
  createStaticVNode,
  createElementVNode,
  createElementBlock 
} from "@vue/runtime-core";

// Text node creation
const textNode = createTextVNode('Hello World');
const dynamicTextNode = createTextVNode(
  'Dynamic text', 
  1 // PatchFlags.TEXT - indicates text content can change
);

// Comment nodes
const commentNode = createCommentVNode('This is a comment');
const blockComment = createCommentVNode('Block comment', true);

// Static content (hoisted by compiler)
const staticNode = createStaticVNode(
  '<div class="static"><span>Static content</span></div>',
  2 // Number of nodes in the static content
);

// Element nodes
const simpleElement = createElementVNode('div', { id: 'simple' });

const dynamicElement = createElementVNode(
  'div',
  { class: 'dynamic' },
  [textNode],
  8, // PatchFlags.PROPS - indicates props can change
  ['class'] // Dynamic prop names
);

// Element blocks (with optimization tracking)
const elementBlock = createElementBlock(
  'div',
  { class: 'block' },
  [
    createTextVNode('Block content'),
    createElementVNode('span', null, 'Span content')
  ]
);

Render List Helpers

Utilities for rendering lists efficiently.

/**
 * Renders a list of items with a render function
 * @param source - Array, object, string, or number to iterate
 * @param renderItem - Function to render each item
 * @returns Array of VNodes
 */
function renderList<T>(
  source: T[] | Record<string | number, T> | string | number,
  renderItem: (value: T, key: string | number, index: number) => VNode
): VNode[];

Usage Examples:

import { renderList, h } from "@vue/runtime-core";

// Array rendering
const items = ['apple', 'banana', 'cherry'];
const listNodes = renderList(items, (item, key, index) => {
  return h('li', { key }, `${index}: ${item}`);
});

// Object rendering
const user = { name: 'John', age: 30, city: 'New York' };
const userInfoNodes = renderList(user, (value, key) => {
  return h('div', { key }, `${key}: ${value}`);
});

// Number rendering (1 to n)
const numberNodes = renderList(5, (value, key) => {
  return h('span', { key }, `Number ${value}`);
});

// String rendering (each character)
const charNodes = renderList('hello', (char, index) => {
  return h('span', { key: index }, char);
});

// Complete list component
const ListComponent = defineComponent({
  props: {
    items: Array,
    itemRenderer: Function
  },
  
  setup(props) {
    return () => h('ul', 
      renderList(props.items || [], (item, index) => {
        return props.itemRenderer 
          ? props.itemRenderer(item, index)
          : h('li', { key: index }, String(item));
      })
    );
  }
});

Slot Rendering Helpers

Utilities for rendering slots and slot content.

/**
 * Renders a slot with optional props and fallback content
 * @param slots - Slots object
 * @param name - Slot name
 * @param props - Props to pass to slot
 * @param fallback - Fallback content if slot is empty
 * @returns VNode or array of VNodes
 */
function renderSlot(
  slots: Slots,
  name: string,
  props?: Data,
  fallback?: () => VNodeArrayChildren
): VNode;

/**
 * Creates a slots object from slot definitions
 * @param slots - Base slots object
 * @param dynamicSlots - Dynamic slot descriptors
 * @returns Complete slots object
 */
function createSlots(
  slots: Record<string, Slot>,
  dynamicSlots: (CompiledSlotDescriptor | CompiledSlotDescriptor[])[]
): Slots;

interface CompiledSlotDescriptor {
  name: string;
  fn: Slot;
  key?: string | number;
}

Usage Examples:

import { renderSlot, createSlots, h } from "@vue/runtime-core";

// Render slot with fallback
const SlotComponent = defineComponent({
  setup(_, { slots }) {
    return () => h('div', { class: 'wrapper' }, [
      renderSlot(slots, 'header', {}, () => [
        h('h1', 'Default Header')
      ]),
      
      renderSlot(slots, 'default'),
      
      renderSlot(slots, 'footer', { timestamp: Date.now() }, () => [
        h('footer', 'Default Footer')
      ])
    ]);
  }
});

// Dynamic slot creation
const DynamicSlotComponent = defineComponent({
  props: {
    slotConfigs: Array
  },
  
  setup(props, { slots }) {
    return () => {
      const dynamicSlots = props.slotConfigs?.map(config => ({
        name: config.name,
        fn: (props) => h('div', `Dynamic slot: ${config.name}`)
      })) || [];
      
      const allSlots = createSlots(slots, dynamicSlots);
      
      return h('div', 
        Object.keys(allSlots).map(name => 
          renderSlot(allSlots, name)
        )
      );
    };
  }
});

Event Handler Helpers

Utilities for handling events and handler normalization.

/**
 * Converts event object to handler functions
 * @param obj - Object with event handlers
 * @returns Object with normalized handlers
 */
function toHandlers(obj: Record<string, any>): Record<string, Function | Function[]>;

Usage Examples:

import { toHandlers, h } from "@vue/runtime-core";

// Convert event object to handlers
const EventComponent = defineComponent({
  props: {
    events: Object
  },
  
  setup(props) {
    return () => {
      const handlers = toHandlers(props.events || {});
      
      return h('button', {
        ...handlers,
        class: 'event-button'
      }, 'Click me');
    };
  }
});

// Usage
const eventConfig = {
  onClick: () => console.log('clicked'),
  onMouseenter: () => console.log('mouse enter'),
  onMouseleave: () => console.log('mouse leave')
};

h(EventComponent, { events: eventConfig });

// Multiple handlers for same event
const multiHandlerConfig = {
  onClick: [
    () => console.log('First handler'),
    () => console.log('Second handler')
  ]
};

const multiHandlers = toHandlers(multiHandlerConfig);
// Results in: { onClick: [Function, Function] }

Memoization Helpers

Utilities for memoizing render functions and expensive computations.

/**
 * Memoizes a render function based on dependencies
 * @param memo - Dependency array for memoization
 * @param render - Render function to memoize
 * @param cache - Cache array for storing previous results
 * @param index - Cache index for this memoization
 * @returns Memoized result or new computation
 */
function withMemo<T>(
  memo: any[],
  render: () => T,
  cache: any[],
  index: number
): T;

/**
 * Checks if memoization dependencies are the same
 * @param cached - Previously cached dependencies
 * @param memo - Current dependencies
 * @returns True if dependencies are the same
 */
function isMemoSame(cached: any[], memo: any[]): boolean;

Usage Examples:

import { withMemo, isMemoSame, h } from "@vue/runtime-core";

const MemoizedComponent = defineComponent({
  props: {
    items: Array,
    processor: Function
  },
  
  setup(props) {
    const cache: any[] = [];
    
    return () => {
      // Memoize expensive list processing
      const processedItems = withMemo(
        [props.items, props.processor], // Dependencies
        () => {
          console.log('Processing items...');
          return props.items?.map(props.processor) || [];
        },
        cache, // Cache array
        0 // Cache index
      );
      
      return h('ul',
        processedItems.map((item, index) => 
          h('li', { key: index }, item)
        )
      );
    };
  }
});

// Manual memoization check
const useMemoCheck = () => {
  const lastDeps = ref<any[]>([]);
  const lastResult = ref<any>(null);
  
  const memoizedCompute = (deps: any[], computeFn: () => any) => {
    if (!isMemoSame(lastDeps.value, deps)) {
      lastResult.value = computeFn();
      lastDeps.value = deps;
    }
    return lastResult.value;
  };
  
  return { memoizedCompute };
};

Context and Scope Helpers

Utilities for managing render context and scoped CSS.

/**
 * Wraps a function with render context
 * @param fn - Function to wrap
 * @param ctx - Component context
 * @returns Wrapped function
 */
function withCtx<T extends Function>(fn: T, ctx?: ComponentInternalInstance): T;

/**
 * Pushes a scope ID for scoped CSS
 * @param id - Scope ID to push
 */
function pushScopeId(id: string | null): void;

/**
 * Pops the current scope ID
 */
function popScopeId(): void;

/**
 * Wraps a function to run with a specific scope ID
 * @param id - Scope ID to use
 * @returns Function wrapper
 */
function withScopeId<T extends Function>(id: string): (fn: T) => T;

Usage Examples:

import { withCtx, pushScopeId, popScopeId, withScopeId } from "@vue/runtime-core";

// Context wrapping
const ContextComponent = defineComponent({
  setup() {
    const instance = getCurrentInstance();
    
    const wrappedHandler = withCtx(() => {
      console.log('Handler called with context');
    }, instance);
    
    return () => h('button', { onClick: wrappedHandler }, 'Click');
  }
});

// Scoped CSS management
const ScopedComponent = defineComponent({
  setup() {
    const scopeId = 'data-v-123abc';
    
    return () => {
      pushScopeId(scopeId);
      
      const element = h('div', { class: 'scoped' }, [
        h('span', 'Scoped content')
      ]);
      
      popScopeId();
      
      return element;
    };
  }
});

// Scope ID wrapper
const createScopedRenderer = (scopeId: string) => {
  const withScope = withScopeId(scopeId);
  
  return withScope((props: any) => {
    return h('div', { class: 'scoped-component' }, props.children);
  });
};

const ScopedRenderer = createScopedRenderer('data-v-456def');

Advanced Usage Patterns

Custom Render Pipeline

// Custom render function with optimizations
const createOptimizedRenderer = () => {
  const cache: any[] = [];
  let blockStack: VNode[] = [];
  
  const render = (component: any, props: any) => {
    openBlock();
    
    const vnode = withMemo(
      [component, props],
      () => {
        setBlockTracking(1);
        
        const result = createElementBlock(
          'div',
          { class: 'optimized' },
          [
            createTextVNode('Optimized content'),
            renderList(props.items || [], (item, index) => 
              createElementVNode('span', { key: index }, item)
            )
          ]
        );
        
        setBlockTracking(0);
        return result;
      },
      cache,
      0
    );
    
    return vnode;
  };
  
  return { render };
};

// Static hoisting simulation
const createHoistedContent = () => {
  // This would typically be done by the compiler
  const hoistedStatic = createStaticVNode(
    '<div class="static-header"><h1>Static Title</h1></div>',
    2
  );
  
  return (dynamicContent: VNode[]) => {
    return createElementBlock('div', null, [
      hoistedStatic,
      ...dynamicContent
    ]);
  };
};

Types

interface Slots {
  [name: string]: Slot | undefined;
}

type Slot<T = any> = (...args: any[]) => VNode[];

interface CompiledSlotDescriptor {
  name: string;
  fn: Slot;
  key?: string | number;
}

type Data = Record<string, unknown>;

// Patch flags for optimization
enum PatchFlags {
  TEXT = 1,
  CLASS = 2,
  STYLE = 4,
  PROPS = 8,
  FULL_PROPS = 16,
  HYDRATE_EVENTS = 32,
  STABLE_FRAGMENT = 64,
  KEYED_FRAGMENT = 128,
  UNKEYED_FRAGMENT = 256,
  NEED_PATCH = 512,
  DYNAMIC_SLOTS = 1024,
  HOISTED = -1,
  BAIL = -2
}

Performance Considerations

Block Tracking Benefits

  1. Selective Updates: Only tracked dynamic children are diffed
  2. Skip Static Content: Static content is completely skipped during updates
  3. Efficient Reconciliation: Reduces the number of nodes to compare

Memoization Guidelines

  1. Use for Expensive Operations: Only memoize computationally expensive functions
  2. Dependency Management: Keep dependency arrays minimal and specific
  3. Cache Management: Consider cache size limits for long-running applications

Static Hoisting

  1. Compiler Optimization: Static content is hoisted outside render functions
  2. Memory Efficiency: Static VNodes are created once and reused
  3. Performance Improvement: Reduces VNode creation overhead

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