From df04a7d4eca365fae975f5a1a8abfba8b636c4df Mon Sep 17 00:00:00 2001 From: Brandon Date: Thu, 4 Apr 2024 14:51:01 +1300 Subject: [PATCH 1/2] feat: added maximumWalkingDepth option --- README.md | 9 +++++++++ src/main.ts | 1 + src/processTemplate.ts | 5 +++-- src/types.ts | 10 ++++++++++ 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f0b55e1..5e3c086 100755 --- a/README.md +++ b/README.md @@ -132,6 +132,15 @@ const report = await createReport({ * Defaults to false. */ fixSmartQuotes: false; + + /** + * Maximum loop iterations allowed when walking through the template. + * You can increase this to generate reports with large amount of FOR loop elements. + * Tip: You can disable infinite loop protection by using the `Infinity` constant. + * This may be useful if you implement a process timeout instead. + * (Default: 1,000,000) + */ + maximumWalkingDepth?: number; }); ``` diff --git a/src/main.ts b/src/main.ts index 3c50856..c47d813 100644 --- a/src/main.ts +++ b/src/main.ts @@ -165,6 +165,7 @@ async function createReport( options.processLineBreaksAsNewText == null ? false : options.processLineBreaksAsNewText, + maximumWalkingDepth: options.maximumWalkingDepth, }; const xmlOptions = { literalXmlDelimiter }; diff --git a/src/processTemplate.ts b/src/processTemplate.ts index a9104ca..c23ff19 100755 --- a/src/processTemplate.ts +++ b/src/processTemplate.ts @@ -210,6 +210,7 @@ export async function walkTemplate( const errors: Error[] = []; let loopCount = 0; + const maximumWalkingDepth = ctx.options?.maximumWalkingDepth || 1_000_000; while (true) { const curLoop = getCurLoop(ctx); let nextSibling: Node | null = null; @@ -249,14 +250,14 @@ export async function walkTemplate( `=== parent is null, breaking after ${loopCount} loops...` ); break; - } else if (loopCount > 1000000) { + } else if (loopCount > maximumWalkingDepth) { // adding a emergency exit to avoid infit loops logger.debug( `=== parent is still not null after ${loopCount} loops, something must be wrong ...`, debugPrintNode(parent) ); throw new InternalError( - 'something went wrong with the document. Please review and try again' + 'infinite loop or massive dataset detected. Please review and try again' ); } nodeIn = parent; diff --git a/src/types.ts b/src/types.ts index 1c406ab..cbab86b 100755 --- a/src/types.ts +++ b/src/types.ts @@ -118,6 +118,15 @@ export type UserOptions = { * (Default: false) */ processLineBreaksAsNewText?: boolean; + + /** + * Maximum loop iterations allowed when walking through the template. + * You can increase this to generate reports with large amount of FOR loop elements. + * Tip: You can disable infinite loop protection by using the `Infinity` constant. + * This may be useful if you implement a process timeout instead. + * (Default: 1,000,000) + */ + maximumWalkingDepth?: number; }; export type CreateReportOptions = { @@ -132,6 +141,7 @@ export type CreateReportOptions = { errorHandler: ErrorHandler | null; fixSmartQuotes: boolean; processLineBreaksAsNewText: boolean; + maximumWalkingDepth?: number; }; export type SandBox = { From 279a826c2a3c0622d3859e950e780021a39de1c8 Mon Sep 17 00:00:00 2001 From: Brandon Date: Thu, 4 Apr 2024 15:46:01 +1300 Subject: [PATCH 2/2] minor readme fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5e3c086..a9460ef 100755 --- a/README.md +++ b/README.md @@ -140,7 +140,7 @@ const report = await createReport({ * This may be useful if you implement a process timeout instead. * (Default: 1,000,000) */ - maximumWalkingDepth?: number; + maximumWalkingDepth: 1_000_000; }); ```