diff --git a/src/expressions/functions/builtInFunctions_fontoxpath.ts b/src/expressions/functions/builtInFunctions_fontoxpath.ts index f55ef9f83..995b4cc1e 100644 --- a/src/expressions/functions/builtInFunctions_fontoxpath.ts +++ b/src/expressions/functions/builtInFunctions_fontoxpath.ts @@ -42,7 +42,7 @@ function buildResultIterator( args: ISequence, staticContext: StaticContext, executionParameters: ExecutionParameters, -): { queryValue: Value; resultIterator: IIterator } { +): { evaluableExpression: EvaluableExpression; resultIterator: IIterator } { const queryValue = query.first(); const variables = (args.first() as MapValue).keyValuePairs.reduce((expandedArgs, arg) => { expandedArgs[arg.key.value] = createDoublyIterableSequence(arg.value()); @@ -53,9 +53,11 @@ function buildResultIterator( const contextItemSequence = variables['.'] ? variables['.']() : sequenceFactory.empty(); delete variables['.']; + const evaluableExpression = getEvaluableExpressionFromValue(queryValue); + try { const { expression, staticContext: innerStaticContext } = staticallyCompileXPath( - getEvaluableExpressionFromValue(queryValue), + evaluableExpression, { allowUpdating: false, allowXQuery: true, @@ -87,10 +89,10 @@ function buildResultIterator( return { resultIterator: expression.evaluate(innerDynamicContext, executionParameters).value, - queryValue, + evaluableExpression, }; } catch (error) { - printAndRethrowError(queryValue.value, error); + printAndRethrowError(evaluableExpression, error); } } @@ -102,11 +104,11 @@ const fontoxpathEvaluate: FunctionDefinitionType = ( args, ) => { let resultIterator: IIterator; - let queryValue: Value; + let evaluableExpression: EvaluableExpression; return sequenceFactory.create({ next: () => { if (!resultIterator) { - ({ resultIterator, queryValue } = buildResultIterator( + ({ resultIterator, evaluableExpression } = buildResultIterator( query, args, staticContext, @@ -117,7 +119,7 @@ const fontoxpathEvaluate: FunctionDefinitionType = ( try { return resultIterator.next(IterationHint.NONE); } catch (error) { - printAndRethrowError(queryValue.value, error); + printAndRethrowError(evaluableExpression, error); } }, }); diff --git a/test/specs/parsing/functions/functions.fontoxpath.tests.ts b/test/specs/parsing/functions/functions.fontoxpath.tests.ts index b386bc4ae..075aec5ec 100644 --- a/test/specs/parsing/functions/functions.fontoxpath.tests.ts +++ b/test/specs/parsing/functions/functions.fontoxpath.tests.ts @@ -3,8 +3,10 @@ import { domFacade, evaluateXPath, evaluateXPathToBoolean, + evaluateXPathToFirstNode, evaluateXPathToNumber, evaluateXPathToString, + parseScript, registerCustomXPathFunction, } from 'fontoxpath'; import * as slimdom from 'slimdom'; @@ -158,6 +160,21 @@ describe('extension functions', () => { 42, )); + it('throws when passed an XQueryX program with stack traces that throws', () => { + const expr = parseScript('format-integer($n,"A")', { debug: true }, documentNode); + chai.assert.throws( + () => + evaluateXPathToString( + `fontoxpath:evaluate($expr, map{ 'n': 1.2 })`, + documentNode, + domFacade, + { expr }, + { language: evaluateXPath.XQUERY_3_1_LANGUAGE, debug: true }, + ), + 'XPTY0004', + ); + }); + it('throws when passed nonsense as an XQueryX program', () => chai.assert.throws( () =>