Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
changeKind: fix
packages:
- "@typespec/html-program-viewer"
---

Fix type graph viewer to display Symbol-keyed decorator state
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,25 @@ const createIterator = (showNonenumerable?: boolean, sortObjectKeys?: boolean) =
i++;
}
} else {
const keys = Object.getOwnPropertyNames(data);
if (sortObjectKeys === true && !dataIsArray) {
// Get all property keys (both string and Symbol)
const stringKeys = Object.getOwnPropertyNames(data);
const symbolKeys = Object.getOwnPropertySymbols(data);
const allKeys: (string | symbol)[] = [...stringKeys, ...symbolKeys];

if (sortObjectKeys && !dataIsArray) {
// Array keys should not be sorted in alphabetical order
keys.sort();
} else if (typeof sortObjectKeys === "function") {
keys.sort(sortObjectKeys);
allKeys.sort((a, b) => {
const aStr = typeof a === "string" ? a : a.toString();
const bStr = typeof b === "string" ? b : b.toString();
return aStr.localeCompare(bStr);
});
}

for (const propertyName of keys) {
if (propertyIsEnumerable.call(data, propertyName)) {
const propertyValue = getPropertyValue(data, propertyName);
for (const key of allKeys) {
if (propertyIsEnumerable.call(data, key)) {
const propertyValue = getPropertyValue(data, key);
yield {
name: propertyName || `""`,
name: typeof key === "string" ? key || `""` : key.toString(),
data: propertyValue,
};
} else if (showNonenumerable) {
Expand All @@ -54,14 +60,14 @@ const createIterator = (showNonenumerable?: boolean, sortObjectKeys?: boolean) =
// http://stackoverflow.com/questions/31921189/caller-and-arguments-are-restricted-function-properties-and-cannot-be-access
let propertyValue;
try {
propertyValue = getPropertyValue(data, propertyName);
propertyValue = getPropertyValue(data, key);
} catch (e) {
// console.warn(e)
}

if (propertyValue !== undefined) {
yield {
name: propertyName,
name: typeof key === "string" ? key || `""` : key.toString(),
data: propertyValue,
isNonenumerable: true,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { JsValue } from "./js-value/js-value.js";
import { ObjectName } from "./object-name.js";

import style from "./object-inspector.module.css";
import { hasOwnProperty } from "./utils/object-prototype.js";
import { hasOwnProperty, propertyIsEnumerable } from "./utils/object-prototype.js";
import { getPropertyValue } from "./utils/property-utils.js";

/* intersperse arr with separator */
Expand Down Expand Up @@ -54,27 +54,36 @@ export const ObjectPreview: FC<any> = ({ data }) => {
} else {
const maxProperties = OBJECT_MAX_PROPERTIES;
const propertyNodes: ReactNode[] = [];
for (const propertyName in object) {
if (hasOwnProperty.call(object, propertyName)) {
let ellipsis;
if (
propertyNodes.length === maxProperties - 1 &&
Object.keys(object).length > maxProperties
) {
ellipsis = <span key={"ellipsis"}>…</span>;
}

const propertyValue = getPropertyValue(object, propertyName);
propertyNodes.push(
<span key={propertyName}>
<ObjectName name={propertyName || `""`} />
:&nbsp;
<JsValue value={propertyValue} />
{ellipsis}
</span>,
);
if (ellipsis) break;

// Get all property keys (both string and Symbol), filtering for enumerable ones
const stringKeys = Object.keys(object); // Object.keys only returns enumerable string properties
const symbolKeys = Object.getOwnPropertySymbols(object).filter(sym =>
propertyIsEnumerable.call(object, sym)
);
const allKeys: (string | symbol)[] = [...stringKeys, ...symbolKeys];
const totalProperties = allKeys.length;

for (let i = 0; i < allKeys.length; i++) {
const key = allKeys[i];
let ellipsis;
if (
propertyNodes.length === maxProperties - 1 &&
totalProperties > maxProperties
) {
ellipsis = <span key={"ellipsis"}>…</span>;
}

const propertyValue = getPropertyValue(object, key);
const displayName = typeof key === "string" ? key || `""` : key.toString();
propertyNodes.push(
<span key={typeof key === "string" ? key : `symbol-${i}`}>
<ObjectName name={displayName} />
:&nbsp;
<JsValue value={propertyValue} />
{ellipsis}
</span>,
);
if (ellipsis) break;
}

const objectConstructorName = object.constructor ? object.constructor.name : "Object";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export function getPropertyValue(object: any, propertyName: string) {
export function getPropertyValue(object: any, propertyName: string | symbol) {
const propertyDescriptor = Object.getOwnPropertyDescriptor(object, propertyName);
if (propertyDescriptor?.get) {
try {
Expand Down