fix(json-schema-2020-12): avoid accessing properties of null schemas (#10397)

This commit is contained in:
Oliwia Rogala
2025-04-02 08:16:08 +02:00
committed by GitHub
parent 25daec9ce9
commit d2fff7c746
9 changed files with 45 additions and 19 deletions

View File

@@ -35,7 +35,7 @@ const JSONSchema = forwardRef(
) => { ) => {
const fn = useFn() const fn = useFn()
// this implementation assumes that $id is always non-relative URI // this implementation assumes that $id is always non-relative URI
const pathToken = identifier || schema.$id || name const pathToken = identifier || schema?.$id || name
const { path } = usePath(pathToken) const { path } = usePath(pathToken)
const { isExpanded, setExpanded, setCollapsed } = useIsExpanded(pathToken) const { isExpanded, setExpanded, setCollapsed } = useIsExpanded(pathToken)
const [level, nextLevel] = useLevel() const [level, nextLevel] = useLevel()

View File

@@ -8,7 +8,6 @@ import { useFn, useComponent } from "../../hooks"
const AdditionalProperties = ({ schema }) => { const AdditionalProperties = ({ schema }) => {
const fn = useFn() const fn = useFn()
const { additionalProperties } = schema
const JSONSchema = useComponent("JSONSchema") const JSONSchema = useComponent("JSONSchema")
if (!fn.hasKeyword(schema, "additionalProperties")) return null if (!fn.hasKeyword(schema, "additionalProperties")) return null
@@ -24,14 +23,14 @@ const AdditionalProperties = ({ schema }) => {
return ( return (
<div className="json-schema-2020-12-keyword json-schema-2020-12-keyword--additionalProperties"> <div className="json-schema-2020-12-keyword json-schema-2020-12-keyword--additionalProperties">
{additionalProperties === true ? ( {schema.additionalProperties === true ? (
<> <>
{name} {name}
<span className="json-schema-2020-12__attribute json-schema-2020-12__attribute--primary"> <span className="json-schema-2020-12__attribute json-schema-2020-12__attribute--primary">
allowed allowed
</span> </span>
</> </>
) : additionalProperties === false ? ( ) : schema.additionalProperties === false ? (
<> <>
{name} {name}
<span className="json-schema-2020-12__attribute json-schema-2020-12__attribute--primary"> <span className="json-schema-2020-12__attribute json-schema-2020-12__attribute--primary">
@@ -41,7 +40,7 @@ const AdditionalProperties = ({ schema }) => {
) : ( ) : (
<JSONSchema <JSONSchema
name={name} name={name}
schema={additionalProperties} schema={schema.additionalProperties}
identifier="additionalProperties" identifier="additionalProperties"
/> />
)} )}

View File

@@ -4,17 +4,29 @@
import React from "react" import React from "react"
import PropTypes from "prop-types" import PropTypes from "prop-types"
import { isPlainObject } from "../../../fn"
/** /**
* This component represents various constraint keywords * This component represents various constraint keywords
* from JSON Schema 2020-12 validation vocabulary. * from JSON Schema 2020-12 validation vocabulary.
*/ */
const Constraint = ({ constraint }) => ( const Constraint = ({ constraint }) => {
<span if (
className={`json-schema-2020-12__constraint json-schema-2020-12__constraint--${constraint.scope}`} !isPlainObject(constraint) ||
> typeof constraint.scope !== "string" ||
{constraint.value} typeof constraint.value !== "string"
</span> ) {
) return null
}
return (
<span
className={`json-schema-2020-12__constraint json-schema-2020-12__constraint--${constraint.scope}`}
>
{constraint.value}
</span>
)
}
Constraint.propTypes = { Constraint.propTypes = {
constraint: PropTypes.shape({ constraint: PropTypes.shape({

View File

@@ -7,7 +7,9 @@ import PropTypes from "prop-types"
import * as propTypes from "../../../prop-types" import * as propTypes from "../../../prop-types"
const DependentRequired = ({ dependentRequired }) => { const DependentRequired = ({ dependentRequired }) => {
if (dependentRequired.length === 0) return null if (!Array.isArray(dependentRequired) || dependentRequired.length === 0) {
return null
}
return ( return (
<div className="json-schema-2020-12-keyword json-schema-2020-12-keyword--dependentRequired"> <div className="json-schema-2020-12-keyword json-schema-2020-12-keyword--dependentRequired">

View File

@@ -8,7 +8,6 @@ import { useFn, useComponent } from "../../hooks"
const PropertyNames = ({ schema }) => { const PropertyNames = ({ schema }) => {
const fn = useFn() const fn = useFn()
const { propertyNames } = schema
const JSONSchema = useComponent("JSONSchema") const JSONSchema = useComponent("JSONSchema")
const name = ( const name = (
<span className="json-schema-2020-12-keyword__name json-schema-2020-12-keyword__name--primary"> <span className="json-schema-2020-12-keyword__name json-schema-2020-12-keyword__name--primary">
@@ -25,7 +24,7 @@ const PropertyNames = ({ schema }) => {
<div className="json-schema-2020-12-keyword json-schema-2020-12-keyword--propertyNames"> <div className="json-schema-2020-12-keyword json-schema-2020-12-keyword--propertyNames">
<JSONSchema <JSONSchema
name={name} name={name}
schema={propertyNames} schema={schema.propertyNames}
identifier="propertyNames" identifier="propertyNames"
/> />
</div> </div>

View File

@@ -8,7 +8,6 @@ import { useFn, useComponent } from "../../hooks"
const UnevaluatedItems = ({ schema }) => { const UnevaluatedItems = ({ schema }) => {
const fn = useFn() const fn = useFn()
const { unevaluatedItems } = schema
const JSONSchema = useComponent("JSONSchema") const JSONSchema = useComponent("JSONSchema")
/** /**
@@ -26,7 +25,7 @@ const UnevaluatedItems = ({ schema }) => {
<div className="json-schema-2020-12-keyword json-schema-2020-12-keyword--unevaluatedItems"> <div className="json-schema-2020-12-keyword json-schema-2020-12-keyword--unevaluatedItems">
<JSONSchema <JSONSchema
name={name} name={name}
schema={unevaluatedItems} schema={schema.unevaluatedItems}
identifier="unevaluatedItems" identifier="unevaluatedItems"
/> />
</div> </div>

View File

@@ -8,7 +8,6 @@ import { useFn, useComponent } from "../../hooks"
const UnevaluatedProperties = ({ schema }) => { const UnevaluatedProperties = ({ schema }) => {
const fn = useFn() const fn = useFn()
const { unevaluatedProperties } = schema
const JSONSchema = useComponent("JSONSchema") const JSONSchema = useComponent("JSONSchema")
/** /**
@@ -26,7 +25,7 @@ const UnevaluatedProperties = ({ schema }) => {
<div className="json-schema-2020-12-keyword json-schema-2020-12-keyword--unevaluatedProperties"> <div className="json-schema-2020-12-keyword json-schema-2020-12-keyword--unevaluatedProperties">
<JSONSchema <JSONSchema
name={name} name={name}
schema={unevaluatedProperties} schema={schema.unevaluatedProperties}
identifier="unevaluatedProperties" identifier="unevaluatedProperties"
/> />
</div> </div>

View File

@@ -0,0 +1,12 @@
/**
* @prettier
*/
describe("Empty JSON Schema 2020-12", () => {
it("should render as schema of type `any`", () => {
cy.visit("/?url=/documents/features/json-schema-2020-12-empty-schema.yaml")
cy.get(".json-schema-2020-12__title").should("contain", "Test")
cy.get(".json-schema-2020-12__attribute").should("contain", "any")
})
})

View File

@@ -0,0 +1,4 @@
openapi: 3.1.0
components:
schemas:
Test: