Merge branch 'codex/tool-json-schema-dsl' into codex/canonical-tool-output
This commit is contained in:
@@ -12,20 +12,35 @@
|
|||||||
*/
|
*/
|
||||||
export type JsonValue = null | boolean | number | string | JsonValue[] | { [key: string]: JsonValue }
|
export type JsonValue = null | boolean | number | string | JsonValue[] | { [key: string]: JsonValue }
|
||||||
|
|
||||||
|
/** Whether a realm-owned intrinsic prototype names and points back to its constructor. */
|
||||||
|
function hasIntrinsicConstructor(prototype: object, name: 'Array' | 'Object'): boolean {
|
||||||
|
const descriptor = Object.getOwnPropertyDescriptor(prototype, 'constructor')
|
||||||
|
const constructor: unknown = descriptor?.value
|
||||||
|
return typeof constructor === 'function'
|
||||||
|
&& constructor.name === name
|
||||||
|
&& constructor.prototype === prototype
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Whether a candidate is one realm's intrinsic `Object.prototype`. */
|
||||||
|
function isIntrinsicObjectPrototype(value: object): boolean {
|
||||||
|
return Object.getPrototypeOf(value) === null && hasIntrinsicConstructor(value, 'Object')
|
||||||
|
}
|
||||||
|
|
||||||
/** Whether an array uses one realm's intrinsic `Array.prototype`, not a subclass or forged prototype. */
|
/** Whether an array uses one realm's intrinsic `Array.prototype`, not a subclass or forged prototype. */
|
||||||
function hasPlainArrayPrototype(value: unknown[]): boolean {
|
function hasPlainArrayPrototype(value: unknown[]): boolean {
|
||||||
const prototype: unknown = Object.getPrototypeOf(value)
|
const prototype: unknown = Object.getPrototypeOf(value)
|
||||||
if (!Array.isArray(prototype)) return false
|
if (!Array.isArray(prototype) || !hasIntrinsicConstructor(prototype, 'Array')) return false
|
||||||
const objectPrototype: unknown = Object.getPrototypeOf(prototype)
|
const objectPrototype: unknown = Object.getPrototypeOf(prototype)
|
||||||
return objectPrototype !== null
|
return typeof objectPrototype === 'object'
|
||||||
&& !Array.isArray(objectPrototype)
|
&& objectPrototype !== null
|
||||||
&& Object.getPrototypeOf(objectPrototype) === null
|
&& isIntrinsicObjectPrototype(objectPrototype)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Whether an object is a plain or null-prototype record from any JavaScript realm. */
|
/** Whether an object is a plain or null-prototype record from any JavaScript realm. */
|
||||||
function hasPlainObjectPrototype(value: object): boolean {
|
function hasPlainObjectPrototype(value: object): boolean {
|
||||||
const prototype: unknown = Object.getPrototypeOf(value)
|
const prototype: unknown = Object.getPrototypeOf(value)
|
||||||
return prototype === null || Object.getPrototypeOf(prototype) === null
|
return prototype === null
|
||||||
|
|| typeof prototype === 'object' && isIntrinsicObjectPrototype(prototype)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return every JSON-visible object key, or reject own data JSON would discard. */
|
/** Return every JSON-visible object key, or reject own data JSON would discard. */
|
||||||
|
|||||||
@@ -94,6 +94,8 @@ describe('snapshotJsonValue', () => {
|
|||||||
Object.defineProperty(symbolDecorated, Symbol('extra'), { value: true })
|
Object.defineProperty(symbolDecorated, Symbol('extra'), { value: true })
|
||||||
const hiddenObject = Object.defineProperty({}, 'hidden', { value: true })
|
const hiddenObject = Object.defineProperty({}, 'hidden', { value: true })
|
||||||
const symbolObject = { [Symbol('extra')]: true }
|
const symbolObject = { [Symbol('extra')]: true }
|
||||||
|
const customPrototype = Object.create(null) as Record<string, unknown>
|
||||||
|
const customPrototypeObject = Object.assign(Object.create(customPrototype) as Record<string, unknown>, { value: 1 })
|
||||||
const forgedPrototype: unknown[] = []
|
const forgedPrototype: unknown[] = []
|
||||||
Object.setPrototypeOf(forgedPrototype, null)
|
Object.setPrototypeOf(forgedPrototype, null)
|
||||||
const forgedArray = [1]
|
const forgedArray = [1]
|
||||||
@@ -117,6 +119,7 @@ describe('snapshotJsonValue', () => {
|
|||||||
expect(snapshotJsonValue(symbolDecorated)).toBeUndefined()
|
expect(snapshotJsonValue(symbolDecorated)).toBeUndefined()
|
||||||
expect(snapshotJsonValue(hiddenObject)).toBeUndefined()
|
expect(snapshotJsonValue(hiddenObject)).toBeUndefined()
|
||||||
expect(snapshotJsonValue(symbolObject)).toBeUndefined()
|
expect(snapshotJsonValue(symbolObject)).toBeUndefined()
|
||||||
|
expect(snapshotJsonValue(customPrototypeObject)).toBeUndefined()
|
||||||
expect(snapshotJsonValue(forgedArray)).toBeUndefined()
|
expect(snapshotJsonValue(forgedArray)).toBeUndefined()
|
||||||
expect(snapshotJsonValue(cyclic)).toBeUndefined()
|
expect(snapshotJsonValue(cyclic)).toBeUndefined()
|
||||||
expect(snapshotJsonValue([undefined])).toBeUndefined()
|
expect(snapshotJsonValue([undefined])).toBeUndefined()
|
||||||
@@ -188,6 +191,8 @@ describe('isJsonValue', () => {
|
|||||||
Object.defineProperty(symbolDecorated, Symbol('extra'), { value: true })
|
Object.defineProperty(symbolDecorated, Symbol('extra'), { value: true })
|
||||||
const hiddenObject = Object.defineProperty({}, 'hidden', { value: true })
|
const hiddenObject = Object.defineProperty({}, 'hidden', { value: true })
|
||||||
const symbolObject = { [Symbol('extra')]: true }
|
const symbolObject = { [Symbol('extra')]: true }
|
||||||
|
const customPrototype = Object.create(null) as Record<string, unknown>
|
||||||
|
const customPrototypeObject = Object.assign(Object.create(customPrototype) as Record<string, unknown>, { value: 1 })
|
||||||
const forgedPrototype: unknown[] = []
|
const forgedPrototype: unknown[] = []
|
||||||
Object.setPrototypeOf(forgedPrototype, null)
|
Object.setPrototypeOf(forgedPrototype, null)
|
||||||
const forgedArray = [1]
|
const forgedArray = [1]
|
||||||
@@ -201,6 +206,7 @@ describe('isJsonValue', () => {
|
|||||||
expect(isJsonValue(symbolDecorated)).toBe(false)
|
expect(isJsonValue(symbolDecorated)).toBe(false)
|
||||||
expect(isJsonValue(hiddenObject)).toBe(false)
|
expect(isJsonValue(hiddenObject)).toBe(false)
|
||||||
expect(isJsonValue(symbolObject)).toBe(false)
|
expect(isJsonValue(symbolObject)).toBe(false)
|
||||||
|
expect(isJsonValue(customPrototypeObject)).toBe(false)
|
||||||
expect(isJsonValue(forgedArray)).toBe(false)
|
expect(isJsonValue(forgedArray)).toBe(false)
|
||||||
expect(isJsonValue(new ExoticArray(1))).toBe(false)
|
expect(isJsonValue(new ExoticArray(1))).toBe(false)
|
||||||
expect(isJsonValue([undefined])).toBe(false)
|
expect(isJsonValue([undefined])).toBe(false)
|
||||||
|
|||||||
Reference in New Issue
Block a user