Spaces:
Sleeping
Sleeping
File size: 4,424 Bytes
5f2aab6 |
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 |
/**
* オブジェクトのシリアライゼーション可能性をチェックし、
* 問題のあるプロパティを特定するユーティリティ
*/
export function debugSerialization(obj: unknown, path = 'root'): { serializable: boolean; issues: string[] } {
const issues: string[] = [];
function checkValue(value: unknown, currentPath: string): boolean {
// null/undefined/プリミティブ型は安全
if (value === null || value === undefined) return true;
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') return true;
// 配列のチェック
if (Array.isArray(value)) {
for (let i = 0; i < value.length; i++) {
if (!checkValue(value[i], `${currentPath}[${i}]`)) {
return false;
}
}
return true;
}
// オブジェクトのチェック
if (typeof value === 'object') {
const constructor = value.constructor;
const constructorName = constructor?.name;
// 問題のあるコンストラクタを検出
if (constructorName && !['Object', 'Array'].includes(constructorName)) {
issues.push(`${currentPath}: Non-plain object with constructor '${constructorName}'`);
// 特定の問題のあるクラスを詳細に記録
if (constructorName === 'Request') {
issues.push(`${currentPath}: Request object (from fetch API or Gradio Client)`);
} else if (constructorName === 'Headers') {
issues.push(`${currentPath}: Headers object (from fetch API or Gradio Client)`);
} else if (constructorName === 'AbortSignal') {
issues.push(`${currentPath}: AbortSignal object (from fetch API or Gradio Client)`);
} else if (constructorName === 'Date') {
issues.push(`${currentPath}: Date object - use toISOString() or getTime()`);
} else if (constructorName === 'Map' || constructorName === 'Set') {
issues.push(`${currentPath}: ${constructorName} object - convert to plain object/array`);
}
return false;
}
// 関数のチェック
if (typeof value === 'function') {
issues.push(`${currentPath}: Function detected`);
return false;
}
// Symbol のチェック
if (typeof value === 'symbol') {
issues.push(`${currentPath}: Symbol detected`);
return false;
}
// オブジェクトのプロパティを再帰的にチェック
for (const [key, val] of Object.entries(value)) {
if (!checkValue(val, `${currentPath}.${key}`)) {
// 既に issues に追加されているので、falseを返すだけ
}
}
return issues.length === 0;
}
return true;
}
const serializable = checkValue(obj, path);
// 実際にJSON.stringifyを試してエラーを検出
try {
JSON.stringify(obj);
} catch (error) {
issues.push(`JSON.stringify error: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
return { serializable, issues };
}
/**
* オブジェクトをコンソールに詳細にダンプする
*/
export function dumpObjectStructure(obj: unknown, maxDepth = 3, currentDepth = 0): void {
const indent = ' '.repeat(currentDepth);
if (currentDepth >= maxDepth) {
console.log(`${indent}[Max depth reached]`);
return;
}
if (obj === null || obj === undefined) {
console.log(`${indent}${obj}`);
return;
}
if (typeof obj !== 'object') {
console.log(`${indent}${typeof obj}: ${obj}`);
return;
}
const constructor = obj.constructor;
console.log(`${indent}${constructor?.name || 'Object'} {`);
for (const [key, value] of Object.entries(obj)) {
if (value === null || value === undefined) {
console.log(`${indent} ${key}: ${value}`);
} else if (typeof value === 'object') {
const valueConstructor = value.constructor;
console.log(`${indent} ${key}: ${valueConstructor?.name || 'Object'} ${Array.isArray(value) ? `[${value.length}]` : ''}`);
if (!['Request', 'Headers', 'AbortSignal', 'Client'].includes(valueConstructor?.name || '')) {
dumpObjectStructure(value, maxDepth, currentDepth + 2);
}
} else if (typeof value === 'function') {
console.log(`${indent} ${key}: [Function]`);
} else {
console.log(`${indent} ${key}: ${typeof value}`);
}
}
console.log(`${indent}}`);
} |