diff --git a/docs/api.md b/docs/api.md index 4f5a7c68ac..de5c358755 100644 --- a/docs/api.md +++ b/docs/api.md @@ -20135,7 +20135,7 @@ This module provides the APIs for dotdot Loading * [~parseProfilesData(db, ctx)](#module_Loader API_ Loader APIs..parseProfilesData) ⇒ * [~parseFeatureFlags(db, packageId, featureFlags)](#module_Loader API_ Loader APIs..parseFeatureFlags) ⇒ * [~parseConformanceFromXML(operand)](#module_Loader API_ Loader APIs..parseConformanceFromXML) ⇒ - * [~parseConformanceRecursively(operand, parentJoinChar)](#module_Loader API_ Loader APIs..parseConformanceRecursively) ⇒ + * [~parseConformanceRecursively(operand, depth, parentJoinChar)](#module_Loader API_ Loader APIs..parseConformanceRecursively) ⇒ * [~parseUiOptions(db, packageId, featureFlags)](#module_Loader API_ Loader APIs..parseUiOptions) ⇒ * [~parseOptions(db)](#module_Loader API_ Loader APIs..parseOptions) ⇒ * [~parseTextOptions(db, pkgRef, textOptions)](#module_Loader API_ Loader APIs..parseTextOptions) ⇒ @@ -21531,7 +21531,7 @@ Output conformance string: -### Loader API: Loader APIs~parseConformanceRecursively(operand, parentJoinChar) ⇒ +### Loader API: Loader APIs~parseConformanceRecursively(operand, depth, parentJoinChar) ⇒ helper function to parse conformance or an operand in conformance recursively The baseLevelTerms variable include terms that can not have nested terms. @@ -21540,10 +21540,11 @@ When they appear, stop recursing and return the name inside directly **Kind**: inner method of [Loader API: Loader APIs](#module_Loader API_ Loader APIs) **Returns**: The conformance string. -| Param | Type | -| --- | --- | -| operand | \* | -| parentJoinChar | \* | +| Param | Type | Default | +| --- | --- | --- | +| operand | \* | | +| depth | \* | 0 | +| parentJoinChar | \* | | @@ -21968,7 +21969,7 @@ This module provides the APIs for new data model loading * [~parseProfilesData(db, ctx)](#module_Loader API_ Loader APIs..parseProfilesData) ⇒ * [~parseFeatureFlags(db, packageId, featureFlags)](#module_Loader API_ Loader APIs..parseFeatureFlags) ⇒ * [~parseConformanceFromXML(operand)](#module_Loader API_ Loader APIs..parseConformanceFromXML) ⇒ - * [~parseConformanceRecursively(operand, parentJoinChar)](#module_Loader API_ Loader APIs..parseConformanceRecursively) ⇒ + * [~parseConformanceRecursively(operand, depth, parentJoinChar)](#module_Loader API_ Loader APIs..parseConformanceRecursively) ⇒ * [~parseUiOptions(db, packageId, featureFlags)](#module_Loader API_ Loader APIs..parseUiOptions) ⇒ * [~parseOptions(db)](#module_Loader API_ Loader APIs..parseOptions) ⇒ * [~parseTextOptions(db, pkgRef, textOptions)](#module_Loader API_ Loader APIs..parseTextOptions) ⇒ @@ -23364,7 +23365,7 @@ Output conformance string: -### Loader API: Loader APIs~parseConformanceRecursively(operand, parentJoinChar) ⇒ +### Loader API: Loader APIs~parseConformanceRecursively(operand, depth, parentJoinChar) ⇒ helper function to parse conformance or an operand in conformance recursively The baseLevelTerms variable include terms that can not have nested terms. @@ -23373,10 +23374,11 @@ When they appear, stop recursing and return the name inside directly **Kind**: inner method of [Loader API: Loader APIs](#module_Loader API_ Loader APIs) **Returns**: The conformance string. -| Param | Type | -| --- | --- | -| operand | \* | -| parentJoinChar | \* | +| Param | Type | Default | +| --- | --- | --- | +| operand | \* | | +| depth | \* | 0 | +| parentJoinChar | \* | | @@ -23801,7 +23803,7 @@ This module provides the APIs for ZCL/Data-Model loading. * [~parseProfilesData(db, ctx)](#module_Loader API_ Loader APIs..parseProfilesData) ⇒ * [~parseFeatureFlags(db, packageId, featureFlags)](#module_Loader API_ Loader APIs..parseFeatureFlags) ⇒ * [~parseConformanceFromXML(operand)](#module_Loader API_ Loader APIs..parseConformanceFromXML) ⇒ - * [~parseConformanceRecursively(operand, parentJoinChar)](#module_Loader API_ Loader APIs..parseConformanceRecursively) ⇒ + * [~parseConformanceRecursively(operand, depth, parentJoinChar)](#module_Loader API_ Loader APIs..parseConformanceRecursively) ⇒ * [~parseUiOptions(db, packageId, featureFlags)](#module_Loader API_ Loader APIs..parseUiOptions) ⇒ * [~parseOptions(db)](#module_Loader API_ Loader APIs..parseOptions) ⇒ * [~parseTextOptions(db, pkgRef, textOptions)](#module_Loader API_ Loader APIs..parseTextOptions) ⇒ @@ -25197,7 +25199,7 @@ Output conformance string: -### Loader API: Loader APIs~parseConformanceRecursively(operand, parentJoinChar) ⇒ +### Loader API: Loader APIs~parseConformanceRecursively(operand, depth, parentJoinChar) ⇒ helper function to parse conformance or an operand in conformance recursively The baseLevelTerms variable include terms that can not have nested terms. @@ -25206,10 +25208,11 @@ When they appear, stop recursing and return the name inside directly **Kind**: inner method of [Loader API: Loader APIs](#module_Loader API_ Loader APIs) **Returns**: The conformance string. -| Param | Type | -| --- | --- | -| operand | \* | -| parentJoinChar | \* | +| Param | Type | Default | +| --- | --- | --- | +| operand | \* | | +| depth | \* | 0 | +| parentJoinChar | \* | | @@ -25634,7 +25637,7 @@ This module provides the APIs for for common functionality related to loading. * [~parseProfilesData(db, ctx)](#module_Loader API_ Loader APIs..parseProfilesData) ⇒ * [~parseFeatureFlags(db, packageId, featureFlags)](#module_Loader API_ Loader APIs..parseFeatureFlags) ⇒ * [~parseConformanceFromXML(operand)](#module_Loader API_ Loader APIs..parseConformanceFromXML) ⇒ - * [~parseConformanceRecursively(operand, parentJoinChar)](#module_Loader API_ Loader APIs..parseConformanceRecursively) ⇒ + * [~parseConformanceRecursively(operand, depth, parentJoinChar)](#module_Loader API_ Loader APIs..parseConformanceRecursively) ⇒ * [~parseUiOptions(db, packageId, featureFlags)](#module_Loader API_ Loader APIs..parseUiOptions) ⇒ * [~parseOptions(db)](#module_Loader API_ Loader APIs..parseOptions) ⇒ * [~parseTextOptions(db, pkgRef, textOptions)](#module_Loader API_ Loader APIs..parseTextOptions) ⇒ @@ -27030,7 +27033,7 @@ Output conformance string: -### Loader API: Loader APIs~parseConformanceRecursively(operand, parentJoinChar) ⇒ +### Loader API: Loader APIs~parseConformanceRecursively(operand, depth, parentJoinChar) ⇒ helper function to parse conformance or an operand in conformance recursively The baseLevelTerms variable include terms that can not have nested terms. @@ -27039,10 +27042,11 @@ When they appear, stop recursing and return the name inside directly **Kind**: inner method of [Loader API: Loader APIs](#module_Loader API_ Loader APIs) **Returns**: The conformance string. -| Param | Type | -| --- | --- | -| operand | \* | -| parentJoinChar | \* | +| Param | Type | Default | +| --- | --- | --- | +| operand | \* | | +| depth | \* | 0 | +| parentJoinChar | \* | | diff --git a/src-electron/zcl/zcl-loader-silabs.js b/src-electron/zcl/zcl-loader-silabs.js index 4921730333..3e001867eb 100644 --- a/src-electron/zcl/zcl-loader-silabs.js +++ b/src-electron/zcl/zcl-loader-silabs.js @@ -2309,16 +2309,21 @@ function parseConformanceFromXML(operand) { * When they appear, stop recursing and return the name inside directly * * @param {*} operand + * @param {*} depth * @param {*} parentJoinChar * @returns The conformance string. */ -function parseConformanceRecursively(operand, parentJoinChar = '') { +function parseConformanceRecursively(operand, depth = 0, parentJoinChar = '') { + if (depth > 200) { + throw new Error(`Maximum recursion depth exceeded + when parsing conformance: ${JSON.stringify(operand)}`) + } const baseLevelTerms = ['feature', 'condition', 'attribute', 'command'] if (operand.mandatoryConform) { let insideTerm = operand.mandatoryConform[0] // Recurse further if insideTerm is not empty if (insideTerm && Object.keys(insideTerm).toString() != '$') { - return parseConformanceRecursively(operand.mandatoryConform[0]) + return parseConformanceRecursively(operand.mandatoryConform[0], depth + 1) } else { return 'M' } @@ -2327,13 +2332,15 @@ function parseConformanceRecursively(operand, parentJoinChar = '') { // check '$' key is not the only key in the object to handle special cases // e.g. '' if (insideTerm && Object.keys(insideTerm).toString() != '$') { - return `[${parseConformanceRecursively(operand.optionalConform[0])}]` + return `[${parseConformanceRecursively(operand.optionalConform[0], depth + 1)}]` } else { return 'O' } } else if (operand.otherwiseConform) { return Object.entries(operand.otherwiseConform[0]) - .map(([key, value]) => parseConformanceRecursively({ [key]: value })) + .map(([key, value]) => + parseConformanceRecursively({ [key]: value }, depth + 1) + ) .join(', ') } else if (operand.notTerm) { // need to surround terms inside a notTerm with '()' if it contains multiple terms @@ -2341,7 +2348,7 @@ function parseConformanceRecursively(operand, parentJoinChar = '') { // able to process multiple parallel notTerms, e.g. !A & !B return operand.notTerm .map((term) => { - let nt = parseConformanceRecursively(term) + let nt = parseConformanceRecursively(term, depth + 1) return nt.includes('&') || nt.includes('|') ? `!(${nt})` : `!${nt}` }) .join(` ${parentJoinChar} `) @@ -2358,7 +2365,11 @@ function parseConformanceRecursively(operand, parentJoinChar = '') { if (baseLevelTerms.includes(key)) { return value.map((operand) => operand.$.name).join(` ${joinChar} `) } else { - let terms = parseConformanceRecursively({ [key]: value }, joinChar) + let terms = parseConformanceRecursively( + { [key]: value }, + depth + 1, + joinChar + ) return terms.includes(oppositeChar) ? `(${terms})` : terms } })