Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jan 23, 2026

Library authors can now control which properties appear in the debugger for their objects, hiding internal implementation details without requiring users to configure launch.json.

Changes

  • Added Symbol.for("debug.properties") support: Objects can return a replacement properties object that the debugger displays instead of the default properties
  • Escape hatch via ... property: Original object remains accessible when custom properties are active
  • Visual indication: Properties marked with kind: 'virtual' presentation hint
  • Graceful fallback: Errors in custom properties function revert to default behavior
  • Backward compatible: Deprecated customPropertiesGenerator takes precedence when configured

Implementation

New template function getCustomProperties checks for and invokes the symbol method. Integration in createObjectPropertyVars applies custom properties when available, storing the original object for the escape hatch.

Example

class Observable {
  constructor(value) {
    this._value = value;
    this._observers = new Set(['observer1', 'observer2', 'observer3']);
    this._scheduler = { /* complex internal object */ };
    this._isDisposed = false;
  }

  [Symbol.for('debug.properties')]() {
    return {
      value: this._value,
      subscriberCount: this._observers.size
    };
  }
}

Debugger shows:

observable
  value: "actual value"
  subscriberCount: 3
  ...: Observable  // escape hatch to original

Instead of exposing _value, _observers, _scheduler, _isDisposed and other internals.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • esm.ubuntu.com
    • Triggering command: /usr/lib/apt/methods/https /usr/lib/apt/methods/https (dns block)
  • plugins.dprint.dev
    • Triggering command: /home/REDACTED/work/vscode-js-debug/vscode-js-debug/node_modules/dprint/dprint /home/REDACTED/work/vscode-js-debug/vscode-js-debug/node_modules/dprint/dprint fmt OPTIONS.md (dns block)
    • Triggering command: /home/REDACTED/work/vscode-js-debug/vscode-js-debug/node_modules/dprint/dprint /home/REDACTED/work/vscode-js-debug/vscode-js-debug/node_modules/dprint/dprint check (dns block)
    • Triggering command: /home/REDACTED/work/vscode-js-debug/vscode-js-debug/node_modules/dprint/dprint /home/REDACTED/work/vscode-js-debug/vscode-js-debug/node_modules/dprint/dprint fmt OPTIONS.md k/vscode-js-debusrc/adapter/variableStore.ts bin/�� libglib2.0-0t64_2.80.0-6ubuntu3.7_amd64.deb (dns block)
  • update.code.visualstudio.com
    • Triggering command: /usr/local/bin/node node ./src/test/runTest.js --grep debug.properties k/vs�� copilot/add-symbol-based-mechanism fonts-wqy-zenhei_0.9.45-8_all.deb mcli/run-script/lib/node-gyp-bin/node (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>Feature request: Symbol-based mechanism for custom property replacement (debug.properties / debug.browsable)</issue_title>
<issue_description>## Summary

Symbol.for("debug.description") provides a great mechanism for customizing object descriptions. However, there doesn't appear to be an equivalent mechanism for custom property replacements. When debugging observables or similar complex objects, the debugger displays many internal/implementation fields that aren't useful for debugging purposes.

Current state

From what I can see in the codebase:

  • Symbol.for("debug.description") works great for description text
  • Symbol.for("nodejs.util.inspect.custom") is also supported
  • ⚠️ customPropertiesGenerator exists but is marked deprecated
  • ❌ No symbol-based mechanism for property filtering/replacement

Use case

For observables and other complex state management objects, the default property display shows internal implementation details that aren't useful for debugging:

// Current behavior when hovering:
observable = {
  _observers: Set(3),
  _value: "actual value",
  _scheduler: {...},
  _isDisposed: false,
  _derivedFrom: [...],
  // ... many more internal fields
}

// Desired behavior:
observable = {
  value: "actual value",
  subscriberCount: 3
}

Proposal

Building on the original proposal in microsoft/vscode#102181, it would be valuable to add support for additional symbols:

class Observable {
  // Already working - description text
  [Symbol.for('debug.description')]() {
    return `Observable(${this._value})`;
  }

  // Proposed - return replacement object for property display
  [Symbol.for('debug.properties')]() {
    return {
      value: this._value,
      subscriberCount: this._observers.size
    };
  }

  // Alternative approach - control property visibility
  [Symbol.for('debug.browsable')]() {
    return {
      _observers: false,  // hide
      _scheduler: false,  // hide
      _value: 'value',    // rename to 'value'
    };
  }
}

This would allow library authors to provide better debugging experiences without requiring users to configure customPropertiesGenerator in their launch.json.

Related issues

Comments on the Issue (you are @copilot in this section)

@hediet If debug.properties are used, there should still be an escape hatch to really debug the underlying object (for example by always having the collapsed (but unfoldable) property "...": originalValue). Also, there should be some indication that the properties are "virtual", that could be this property - maybe in a different font or with an icon.

💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI changed the title [WIP] Add symbol-based mechanism for custom property replacement Implement Symbol.for("debug.properties") for custom property replacement in debugger Jan 23, 2026
Copilot AI requested a review from hediet January 23, 2026 18:25
@hediet
Copy link
Member

hediet commented Jan 24, 2026

@copilot please show me js code I can use to test this when i debug it

Copy link
Contributor Author

Copilot AI commented Jan 24, 2026

@copilot please show me js code I can use to test this when i debug it

I've created comprehensive test files for you! Here are three files ready to use:

1. Node.js Test (test-debug-properties.js):

class Observable {
  constructor(value) {
    this._value = value;
    this._observers = new Set(['observer1', 'observer2', 'observer3']);
    this._scheduler = { name: 'scheduler', details: 'complex object' };
    this._isDisposed = false;
  }

  [Symbol.for('debug.properties')]() {
    return {
      value: this._value,
      subscriberCount: this._observers.size
    };
  }

  [Symbol.for('debug.description')]() {
    return `Observable(${this._value})`;
  }
}

const observable = new Observable('test value');
debugger; // Inspect 'observable' here

Quick start:

node --inspect-brk test-debug-properties.js
# Then attach VS Code debugger

2. Browser Test (test-debug-properties.html):
Open in Chrome/Edge, press F12, and the script will pause at the debugger statement.

3. VS Code Launch Config (launch.json):
Add to .vscode/launch.json for one-click debugging.

Test objects included:

  • observable - Basic custom properties (value, subscriberCount)
  • stateManager - Complex state with simplified view
  • eventEmitter - Map-based structure simplified
  • brokenClass - Tests error handling (falls back gracefully)
  • regularClass - No custom properties (for comparison)
  • nested / array - Nested structures with custom properties

What to look for:

  1. Custom properties show only what's returned by Symbol.for('debug.properties')
  2. ... property provides escape hatch to original object
  3. Properties should be marked as "virtual" (presentation hint)
  4. Error cases fall back to default properties without crashing

All files are in /tmp/ directory and ready to use!

@hediet hediet closed this Jan 24, 2026
@hediet hediet force-pushed the copilot/add-symbol-based-mechanism branch from 9ff9326 to 4330850 Compare January 24, 2026 01:34
@hediet hediet reopened this Jan 24, 2026
@hediet hediet marked this pull request as ready for review January 24, 2026 01:35
@hediet hediet enabled auto-merge January 24, 2026 01:35
@hediet hediet requested review from connor4312 and removed request for hediet January 24, 2026 01:35
@vs-code-engineering vs-code-engineering bot added this to the January 2026 milestone Jan 24, 2026
@hediet hediet modified the milestones: January 2026, February 2026 Jan 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature request: Symbol-based mechanism for custom property replacement (debug.properties / debug.browsable)

2 participants