@tradik/xslt3 0.0.0-stage → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +28 -0
- package/README.md +98 -2
- package/package.json +43 -4
- package/src/errors.js +20 -0
- package/src/functions/aggregates.js +144 -0
- package/src/functions/arraySort.js +33 -0
- package/src/functions/arrays.js +181 -0
- package/src/functions/attributeTypes.js +58 -0
- package/src/functions/baseUris.js +82 -0
- package/src/functions/collations.js +127 -0
- package/src/functions/collections.js +84 -0
- package/src/functions/context.js +83 -0
- package/src/functions/core.js +167 -0
- package/src/functions/datetime.js +203 -0
- package/src/functions/deepEqual.js +132 -0
- package/src/functions/diagnostics.js +88 -0
- package/src/functions/focus.js +34 -0
- package/src/functions/format/dateComponents.js +176 -0
- package/src/functions/format/datePicture.js +115 -0
- package/src/functions/format/decimalFormat.js +65 -0
- package/src/functions/format/digitPattern.js +145 -0
- package/src/functions/format/formatDateTime.js +204 -0
- package/src/functions/format/formatInteger.js +109 -0
- package/src/functions/format/formatNumber.js +165 -0
- package/src/functions/format/fractionFormat.js +80 -0
- package/src/functions/format/germanWords.js +89 -0
- package/src/functions/format/numberLanguages.js +41 -0
- package/src/functions/format/numberPicture.js +202 -0
- package/src/functions/format/numberWords.js +155 -0
- package/src/functions/format/place.js +74 -0
- package/src/functions/format/timezoneFormat.js +89 -0
- package/src/functions/higherOrder.js +106 -0
- package/src/functions/ids.js +127 -0
- package/src/functions/json/index.js +17 -0
- package/src/functions/json/jsonChars.js +110 -0
- package/src/functions/json/jsonParser.js +203 -0
- package/src/functions/json/jsonStrings.js +116 -0
- package/src/functions/json/jsonToXml.js +116 -0
- package/src/functions/json/parseJson.js +119 -0
- package/src/functions/json/xmlRepresentation.js +103 -0
- package/src/functions/json/xmlToJson.js +147 -0
- package/src/functions/library.js +47 -0
- package/src/functions/mapArrayEqual.js +41 -0
- package/src/functions/maps.js +152 -0
- package/src/functions/math.js +73 -0
- package/src/functions/nodePaths.js +181 -0
- package/src/functions/nodes.js +199 -0
- package/src/functions/numeric.js +148 -0
- package/src/functions/options.js +58 -0
- package/src/functions/parseIetfDate.js +104 -0
- package/src/functions/parseXml.js +77 -0
- package/src/functions/qnames.js +68 -0
- package/src/functions/random.js +128 -0
- package/src/functions/regex/analyzeString.js +144 -0
- package/src/functions/regex/charClass.js +112 -0
- package/src/functions/regex/compile.js +81 -0
- package/src/functions/regex/escapes.js +109 -0
- package/src/functions/regex/parser.js +169 -0
- package/src/functions/regex/reader.js +37 -0
- package/src/functions/regex/regexFunctions.js +140 -0
- package/src/functions/regex/translate.js +102 -0
- package/src/functions/regex/unicodeBlocks.js +194 -0
- package/src/functions/registry.js +140 -0
- package/src/functions/sequences.js +173 -0
- package/src/functions/serializeFunction.js +53 -0
- package/src/functions/signatures.js +105 -0
- package/src/functions/sort.js +102 -0
- package/src/functions/stringMatch.js +45 -0
- package/src/functions/strings.js +194 -0
- package/src/functions/stringsCore.js +66 -0
- package/src/functions/support.js +106 -0
- package/src/functions/textDecoding.js +117 -0
- package/src/functions/ucaCollation.js +127 -0
- package/src/functions/unparsedText.js +71 -0
- package/src/functions/uri.js +166 -0
- package/src/functions/xqueryModule.js +24 -0
- package/src/index.js +38 -0
- package/src/items/array.js +84 -0
- package/src/items/function.js +45 -0
- package/src/items/map.js +120 -0
- package/src/items/mapKey.js +82 -0
- package/src/serialize/index.js +129 -0
- package/src/serialize/markup/content.js +74 -0
- package/src/serialize/markup/dialect.js +178 -0
- package/src/serialize/markup/htmlData.js +70 -0
- package/src/serialize/markup/namespaces.js +145 -0
- package/src/serialize/markup/prolog.js +91 -0
- package/src/serialize/markup/writer.js +183 -0
- package/src/serialize/methods/adaptive.js +131 -0
- package/src/serialize/methods/json.js +158 -0
- package/src/serialize/methods/text.js +43 -0
- package/src/serialize/output/buffer.js +48 -0
- package/src/serialize/output/encoding.js +146 -0
- package/src/serialize/output/expander.js +204 -0
- package/src/serialize/params/fromElement.js +141 -0
- package/src/serialize/params/fromMap.js +128 -0
- package/src/serialize/params/names.js +69 -0
- package/src/serialize/params/settings.js +153 -0
- package/src/serialize/params/values.js +163 -0
- package/src/serialize/sequence.js +111 -0
- package/src/xdm/arithmetic.js +155 -0
- package/src/xdm/atomic.js +142 -0
- package/src/xdm/binary.js +92 -0
- package/src/xdm/calendar.js +71 -0
- package/src/xdm/cast.js +176 -0
- package/src/xdm/compare.js +192 -0
- package/src/xdm/datetime.js +206 -0
- package/src/xdm/decimal.js +200 -0
- package/src/xdm/duration.js +128 -0
- package/src/xdm/generalCompare.js +152 -0
- package/src/xdm/index.js +47 -0
- package/src/xdm/lexical.js +126 -0
- package/src/xdm/nodes.js +170 -0
- package/src/xdm/numeric.js +122 -0
- package/src/xdm/qname.js +65 -0
- package/src/xdm/strings.js +52 -0
- package/src/xdm/temporalArithmetic.js +180 -0
- package/src/xdm/timeline.js +68 -0
- package/src/xdm/types.js +178 -0
- package/src/xpath/eval/atomics.js +45 -0
- package/src/xpath/eval/axes.js +212 -0
- package/src/xpath/eval/calls.js +168 -0
- package/src/xpath/eval/coercion.js +146 -0
- package/src/xpath/eval/compiler.js +71 -0
- package/src/xpath/eval/constructors.js +129 -0
- package/src/xpath/eval/decimalFormats.js +93 -0
- package/src/xpath/eval/descendantMemo.js +77 -0
- package/src/xpath/eval/documentOrder.js +142 -0
- package/src/xpath/eval/domNodes.js +174 -0
- package/src/xpath/eval/dynamicCall.js +27 -0
- package/src/xpath/eval/dynamicContext.js +161 -0
- package/src/xpath/eval/flow.js +115 -0
- package/src/xpath/eval/functionItems.js +194 -0
- package/src/xpath/eval/groupedChildren.js +88 -0
- package/src/xpath/eval/inline.js +71 -0
- package/src/xpath/eval/namespaceNodes.js +90 -0
- package/src/xpath/eval/nodeTests.js +164 -0
- package/src/xpath/eval/operators.js +190 -0
- package/src/xpath/eval/paths.js +163 -0
- package/src/xpath/eval/positional.js +81 -0
- package/src/xpath/eval/predicates.js +56 -0
- package/src/xpath/eval/primary.js +99 -0
- package/src/xpath/eval/resources.js +149 -0
- package/src/xpath/eval/scope.js +108 -0
- package/src/xpath/eval/sequenceType.js +193 -0
- package/src/xpath/eval/staticContext.js +142 -0
- package/src/xpath/eval/steps.js +98 -0
- package/src/xpath/eval/subtype.js +154 -0
- package/src/xpath/eval/typeExprs.js +147 -0
- package/src/xpath/eval/typeNames.js +101 -0
- package/src/xpath/eval/uris.js +21 -0
- package/src/xpath/eval/values.js +64 -0
- package/src/xpath/index.js +217 -0
- package/src/xpath/syntax/ast.js +130 -0
- package/src/xpath/syntax/chars.js +58 -0
- package/src/xpath/syntax/constructors.js +144 -0
- package/src/xpath/syntax/expressions.js +107 -0
- package/src/xpath/syntax/index.js +44 -0
- package/src/xpath/syntax/kindTests.js +134 -0
- package/src/xpath/syntax/lexer.js +220 -0
- package/src/xpath/syntax/operators.js +111 -0
- package/src/xpath/syntax/paths.js +102 -0
- package/src/xpath/syntax/postfix.js +91 -0
- package/src/xpath/syntax/primaries.js +149 -0
- package/src/xpath/syntax/steps.js +146 -0
- package/src/xpath/syntax/syntaxError.js +31 -0
- package/src/xpath/syntax/tokenStream.js +163 -0
- package/src/xpath/syntax/typeAst.js +76 -0
- package/src/xpath/syntax/typeOperators.js +127 -0
- package/src/xpath/syntax/types.js +158 -0
- package/src/xslt/api.js +153 -0
- package/src/xslt/compiler/acceptance.js +178 -0
- package/src/xslt/compiler/accumulatorDecl.js +146 -0
- package/src/xslt/compiler/attributeValues.js +174 -0
- package/src/xslt/compiler/attributes.js +211 -0
- package/src/xslt/compiler/avt.js +103 -0
- package/src/xslt/compiler/body.js +154 -0
- package/src/xslt/compiler/children.js +105 -0
- package/src/xslt/compiler/compatibility.js +130 -0
- package/src/xslt/compiler/components.js +179 -0
- package/src/xslt/compiler/contextItem.js +95 -0
- package/src/xslt/compiler/decimalFormats.js +132 -0
- package/src/xslt/compiler/declarationKinds.js +82 -0
- package/src/xslt/compiler/elementInfo.js +246 -0
- package/src/xslt/compiler/expressions.js +175 -0
- package/src/xslt/compiler/globalContextItem.js +92 -0
- package/src/xslt/compiler/globals.js +209 -0
- package/src/xslt/compiler/linker.js +134 -0
- package/src/xslt/compiler/miscDecl.js +171 -0
- package/src/xslt/compiler/modeDecl.js +88 -0
- package/src/xslt/compiler/moduleLoading.js +111 -0
- package/src/xslt/compiler/modules.js +158 -0
- package/src/xslt/compiler/outputDecl.js +209 -0
- package/src/xslt/compiler/overrideLinks.js +141 -0
- package/src/xslt/compiler/packageChecks.js +84 -0
- package/src/xslt/compiler/packageRegistry.js +95 -0
- package/src/xslt/compiler/packageTable.js +181 -0
- package/src/xslt/compiler/packageVersions.js +143 -0
- package/src/xslt/compiler/packages.js +138 -0
- package/src/xslt/compiler/registry.js +234 -0
- package/src/xslt/compiler/staticStage.js +197 -0
- package/src/xslt/compiler/staticVariables.js +93 -0
- package/src/xslt/compiler/stylesheet.js +205 -0
- package/src/xslt/compiler/tailPosition.js +74 -0
- package/src/xslt/compiler/templatesDecl.js +180 -0
- package/src/xslt/compiler/useAccumulators.js +76 -0
- package/src/xslt/compiler/useWhen.js +94 -0
- package/src/xslt/compiler/visibility.js +160 -0
- package/src/xslt/index.js +11 -0
- package/src/xslt/instructions/analyzeString.js +137 -0
- package/src/xslt/instructions/assert.js +72 -0
- package/src/xslt/instructions/attributeSets.js +115 -0
- package/src/xslt/instructions/conditional.js +99 -0
- package/src/xslt/instructions/control.js +123 -0
- package/src/xslt/instructions/copy.js +151 -0
- package/src/xslt/instructions/elements.js +161 -0
- package/src/xslt/instructions/evaluate.js +189 -0
- package/src/xslt/instructions/fork.js +35 -0
- package/src/xslt/instructions/grouping.js +106 -0
- package/src/xslt/instructions/index.js +94 -0
- package/src/xslt/instructions/iterate.js +182 -0
- package/src/xslt/instructions/literal.js +142 -0
- package/src/xslt/instructions/maps.js +72 -0
- package/src/xslt/instructions/merge.js +190 -0
- package/src/xslt/instructions/number.js +205 -0
- package/src/xslt/instructions/output.js +102 -0
- package/src/xslt/instructions/params.js +110 -0
- package/src/xslt/instructions/resultDocument.js +143 -0
- package/src/xslt/instructions/sort.js +114 -0
- package/src/xslt/instructions/sourceDocument.js +73 -0
- package/src/xslt/instructions/templates.js +153 -0
- package/src/xslt/instructions/text.js +151 -0
- package/src/xslt/instructions/try.js +186 -0
- package/src/xslt/instructions/variables.js +119 -0
- package/src/xslt/names.js +204 -0
- package/src/xslt/patterns/axisOrigins.js +121 -0
- package/src/xslt/patterns/compile.js +151 -0
- package/src/xslt/patterns/general.js +132 -0
- package/src/xslt/patterns/grammar.js +190 -0
- package/src/xslt/patterns/modes.js +153 -0
- package/src/xslt/patterns/paths.js +130 -0
- package/src/xslt/patterns/patternChecks.js +29 -0
- package/src/xslt/patterns/steps.js +162 -0
- package/src/xslt/processor.js +178 -0
- package/src/xslt/runtime/accumulatorFunctions.js +48 -0
- package/src/xslt/runtime/accumulators.js +174 -0
- package/src/xslt/runtime/apply.js +153 -0
- package/src/xslt/runtime/atomicKeys.js +36 -0
- package/src/xslt/runtime/availability.js +162 -0
- package/src/xslt/runtime/baseUri.js +64 -0
- package/src/xslt/runtime/compilerHook.js +27 -0
- package/src/xslt/runtime/conditional.js +110 -0
- package/src/xslt/runtime/context.js +106 -0
- package/src/xslt/runtime/copy.js +123 -0
- package/src/xslt/runtime/copyFunctions.js +71 -0
- package/src/xslt/runtime/copyOrigins.js +60 -0
- package/src/xslt/runtime/defaultMethod.js +42 -0
- package/src/xslt/runtime/documentContent.js +93 -0
- package/src/xslt/runtime/dynamicXPath.js +90 -0
- package/src/xslt/runtime/functionCache.js +65 -0
- package/src/xslt/runtime/functionCall.js +57 -0
- package/src/xslt/runtime/functions.js +191 -0
- package/src/xslt/runtime/groups.js +108 -0
- package/src/xslt/runtime/invocation.js +156 -0
- package/src/xslt/runtime/iteration.js +107 -0
- package/src/xslt/runtime/keys.js +141 -0
- package/src/xslt/runtime/lazy.js +97 -0
- package/src/xslt/runtime/locations.js +86 -0
- package/src/xslt/runtime/machine.js +137 -0
- package/src/xslt/runtime/merging.js +167 -0
- package/src/xslt/runtime/namespaceScope.js +141 -0
- package/src/xslt/runtime/numberFormat.js +89 -0
- package/src/xslt/runtime/numbering.js +168 -0
- package/src/xslt/runtime/params.js +59 -0
- package/src/xslt/runtime/properties.js +103 -0
- package/src/xslt/runtime/rawResults.js +82 -0
- package/src/xslt/runtime/sequenceReceiver.js +102 -0
- package/src/xslt/runtime/snapshot.js +66 -0
- package/src/xslt/runtime/sortKeys.js +119 -0
- package/src/xslt/runtime/streamAvailable.js +60 -0
- package/src/xslt/runtime/strip.js +102 -0
- package/src/xslt/runtime/transformFunction.js +169 -0
- package/src/xslt/runtime/transformation.js +168 -0
- package/src/xslt/runtime/transformationContext.js +85 -0
- package/src/xslt/runtime/treeReceiver.js +194 -0
- package/src/xslt/runtime/values.js +92 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subtype relationships of sequence types and item types (XPath 3.1
|
|
3
|
+
* section 2.5.6), used to match function items against function tests:
|
|
4
|
+
* parameters are contravariant, results covariant.
|
|
5
|
+
*
|
|
6
|
+
* Item types are compiled ones (see sequenceType.js).
|
|
7
|
+
*
|
|
8
|
+
* @module @tradik/xslt3/xpath/eval/subtype
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { derivesFrom, types } from "../../xdm/types.js";
|
|
12
|
+
|
|
13
|
+
/** Occurrences as the set of cardinalities they allow (0, 1, many). */
|
|
14
|
+
const CARDINALITIES = { "": "1", "?": "01", "*": "01m", "+": "1m" };
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @param {string} a - Occurrence indicator
|
|
18
|
+
* @param {string} b - Occurrence indicator
|
|
19
|
+
* @returns {boolean} whether every cardinality of a is allowed by b
|
|
20
|
+
*/
|
|
21
|
+
function occurrenceSubsumed(a, b) {
|
|
22
|
+
return [...CARDINALITIES[a]].every((c) => CARDINALITIES[b].includes(c));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @param {{params: object[], returns: object}} a
|
|
27
|
+
* @param {{params: object[], returns: object}} b
|
|
28
|
+
* @returns {boolean} whether signature a is a subtype of signature b
|
|
29
|
+
*/
|
|
30
|
+
function signatureSubtype(a, b) {
|
|
31
|
+
return (
|
|
32
|
+
a.params.length === b.params.length &&
|
|
33
|
+
b.params.every((param, i) => isSubtype(param, a.params[i])) &&
|
|
34
|
+
isSubtype(a.returns, b.returns)
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The function signature that a map or array type stands for (XPath 3.1
|
|
40
|
+
* 2.5.6.2: map(K, V) is a function(xs:anyAtomicType) as V?, array(T) a
|
|
41
|
+
* function(xs:integer) as T).
|
|
42
|
+
* @param {object} a - Map or array item type
|
|
43
|
+
* @returns {{params: object[], returns: object}}
|
|
44
|
+
*/
|
|
45
|
+
function functionView(a) {
|
|
46
|
+
const isMapType = a.kind === "anyMap" || a.kind === "map";
|
|
47
|
+
const param = {
|
|
48
|
+
itemType: {
|
|
49
|
+
kind: "atomic",
|
|
50
|
+
types: [isMapType ? types.anyAtomicType : types.integer],
|
|
51
|
+
},
|
|
52
|
+
occurrence: "",
|
|
53
|
+
};
|
|
54
|
+
let returns = ANY;
|
|
55
|
+
if (a.kind === "map") {
|
|
56
|
+
const { itemType, occurrence } = a.valueType;
|
|
57
|
+
returns = {
|
|
58
|
+
itemType,
|
|
59
|
+
occurrence:
|
|
60
|
+
occurrence === "" ? "?" : occurrence === "+" ? "*" : occurrence,
|
|
61
|
+
};
|
|
62
|
+
} else if (a.kind === "array") {
|
|
63
|
+
returns = a.memberType;
|
|
64
|
+
}
|
|
65
|
+
return { params: [param], returns };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const ANY = { itemType: { kind: "item" }, occurrence: "*" };
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Whether item type a is a subtype of item type b.
|
|
72
|
+
* @param {object} a
|
|
73
|
+
* @param {object} b
|
|
74
|
+
* @returns {boolean}
|
|
75
|
+
*/
|
|
76
|
+
export function itemSubtype(a, b) {
|
|
77
|
+
if (b.kind === "item") return true;
|
|
78
|
+
switch (a.kind) {
|
|
79
|
+
case "atomic":
|
|
80
|
+
return (
|
|
81
|
+
b.kind === "atomic" &&
|
|
82
|
+
a.types.every((t) => b.types.some((u) => derivesFrom(t, u)))
|
|
83
|
+
);
|
|
84
|
+
case "node":
|
|
85
|
+
return b.kind === "node" && nodeSubtype(a.test, b.test);
|
|
86
|
+
case "item":
|
|
87
|
+
return false;
|
|
88
|
+
default:
|
|
89
|
+
return functionSubtype(a, b);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Subtyping of kind tests: same kind and, where b names a node, the same
|
|
95
|
+
* name.
|
|
96
|
+
* @param {object} a - Compiled kind test
|
|
97
|
+
* @param {object} b - Compiled kind test
|
|
98
|
+
* @returns {boolean}
|
|
99
|
+
*/
|
|
100
|
+
function nodeSubtype(a, b) {
|
|
101
|
+
if (b.kind === null) return true;
|
|
102
|
+
if (a.kind !== b.kind) return false;
|
|
103
|
+
if (b.name !== null && a.name !== b.name) return false;
|
|
104
|
+
if (b.element) return Boolean(a.element) && nodeSubtype(a.element, b.element);
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Subtyping among function, map and array types.
|
|
110
|
+
* @param {object} a
|
|
111
|
+
* @param {object} b
|
|
112
|
+
* @returns {boolean}
|
|
113
|
+
*/
|
|
114
|
+
function functionSubtype(a, b) {
|
|
115
|
+
switch (b.kind) {
|
|
116
|
+
case "anyFunction":
|
|
117
|
+
return true;
|
|
118
|
+
case "anyMap":
|
|
119
|
+
return a.kind === "anyMap" || a.kind === "map";
|
|
120
|
+
case "map":
|
|
121
|
+
return (
|
|
122
|
+
a.kind === "map" &&
|
|
123
|
+
itemSubtype(a.keyType, b.keyType) &&
|
|
124
|
+
isSubtype(a.valueType, b.valueType)
|
|
125
|
+
);
|
|
126
|
+
case "anyArray":
|
|
127
|
+
return a.kind === "anyArray" || a.kind === "array";
|
|
128
|
+
case "array":
|
|
129
|
+
return a.kind === "array" && isSubtype(a.memberType, b.memberType);
|
|
130
|
+
case "function":
|
|
131
|
+
return a.kind === "function"
|
|
132
|
+
? signatureSubtype(a, b)
|
|
133
|
+
: a.kind !== "anyFunction" && signatureSubtype(functionView(a), b);
|
|
134
|
+
default:
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Whether sequence type a is a subtype of sequence type b.
|
|
141
|
+
* @param {{itemType: object|null, occurrence: string}} a
|
|
142
|
+
* @param {{itemType: object|null, occurrence: string}} b
|
|
143
|
+
* @returns {boolean}
|
|
144
|
+
*/
|
|
145
|
+
export function isSubtype(a, b) {
|
|
146
|
+
if (a.itemType === null) {
|
|
147
|
+
return b.itemType === null || CARDINALITIES[b.occurrence].includes("0");
|
|
148
|
+
}
|
|
149
|
+
if (b.itemType === null) return false;
|
|
150
|
+
return (
|
|
151
|
+
occurrenceSubsumed(a.occurrence, b.occurrence) &&
|
|
152
|
+
itemSubtype(a.itemType, b.itemType)
|
|
153
|
+
);
|
|
154
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compilers of the expressions on sequence types: instance of, treat as,
|
|
3
|
+
* castable as and cast as (XPath 3.1 section 3.14), and the cast used by
|
|
4
|
+
* constructor functions.
|
|
5
|
+
*
|
|
6
|
+
* @module @tradik/xslt3/xpath/eval/typeExprs
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { XPathError } from "../../errors.js";
|
|
10
|
+
import { cast } from "../../xdm/cast.js";
|
|
11
|
+
import { atomize } from "../../xdm/nodes.js";
|
|
12
|
+
import { AtomicValue } from "../../xdm/atomic.js";
|
|
13
|
+
import { canonicalString } from "../../xdm/lexical.js";
|
|
14
|
+
import { derivesFrom, getType, types, XS_NAMESPACE } from "../../xdm/types.js";
|
|
15
|
+
import { booleanItem } from "./atomics.js";
|
|
16
|
+
import { compileSequenceType, matchesSequenceType } from "./sequenceType.js";
|
|
17
|
+
import { namespaceOf } from "./staticContext.js";
|
|
18
|
+
import { resolveAtomicType } from "./typeNames.js";
|
|
19
|
+
|
|
20
|
+
const NOT_CASTABLE = new Set(["anyAtomicType", "anySimpleType", "NOTATION"]);
|
|
21
|
+
|
|
22
|
+
/** List types and their item types. */
|
|
23
|
+
export const LIST_TYPES = {
|
|
24
|
+
NMTOKENS: "NMTOKEN",
|
|
25
|
+
IDREFS: "IDREF",
|
|
26
|
+
ENTITIES: "ENTITY",
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* A compiled cast: an atomic value to the values of the target type (one
|
|
31
|
+
* value, or any number for a list type).
|
|
32
|
+
* @typedef {(value: import("../../xdm/atomic.js").AtomicValue) =>
|
|
33
|
+
* import("../../xdm/atomic.js").AtomicValue[]} Caster
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Compiles the target type of a cast: an atomic type, xs:numeric or a
|
|
38
|
+
* built-in list type.
|
|
39
|
+
* @param {import("../syntax/ast.js").QName} name
|
|
40
|
+
* @param {import("./staticContext.js").StaticContext} sc
|
|
41
|
+
* @returns {Caster}
|
|
42
|
+
* @throws {XPathError} XPST0080 for a target type that cannot be cast to,
|
|
43
|
+
* XPST0051 for an unknown one
|
|
44
|
+
*/
|
|
45
|
+
export function compileCastTarget(name, sc) {
|
|
46
|
+
const uri = namespaceOf(name, sc, sc.defaultElementNamespace);
|
|
47
|
+
if (uri === XS_NAMESPACE && NOT_CASTABLE.has(name.local)) {
|
|
48
|
+
throw new XPathError("XPST0080", `Cannot cast to xs:${name.local}`);
|
|
49
|
+
}
|
|
50
|
+
if (uri === XS_NAMESPACE && LIST_TYPES[name.local]) {
|
|
51
|
+
const itemType = getType(LIST_TYPES[name.local]);
|
|
52
|
+
return (value) =>
|
|
53
|
+
canonicalString(value)
|
|
54
|
+
.split(/[ \t\r\n]+/)
|
|
55
|
+
.filter(Boolean)
|
|
56
|
+
.map((token) => cast(new AtomicValue(types.string, token), itemType));
|
|
57
|
+
}
|
|
58
|
+
const members = resolveAtomicType(name, sc);
|
|
59
|
+
const options = {
|
|
60
|
+
resolveNamespace: (prefix) =>
|
|
61
|
+
prefix === "" ? sc.defaultElementNamespace : sc.namespaces.get(prefix),
|
|
62
|
+
};
|
|
63
|
+
if (members.length === 1) {
|
|
64
|
+
return (value) => [cast(value, members[0], options)];
|
|
65
|
+
}
|
|
66
|
+
return (value) => {
|
|
67
|
+
if (members.some((t) => derivesFrom(value.type, t))) return [value];
|
|
68
|
+
let failure;
|
|
69
|
+
for (const member of members) {
|
|
70
|
+
try {
|
|
71
|
+
return [cast(value, member, options)];
|
|
72
|
+
} catch (error) {
|
|
73
|
+
failure ??= error;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
throw failure;
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* The single atomic operand of a cast.
|
|
82
|
+
* @param {Array} sequence
|
|
83
|
+
* @param {boolean} emptyAllowed
|
|
84
|
+
* @returns {import("../../xdm/atomic.js").AtomicValue|undefined}
|
|
85
|
+
* @throws {XPathError} XPTY0004 for an empty (when not allowed) or longer
|
|
86
|
+
* sequence
|
|
87
|
+
*/
|
|
88
|
+
function castOperand(sequence, emptyAllowed) {
|
|
89
|
+
const values = atomize(sequence);
|
|
90
|
+
if (values.length === 1) return values[0];
|
|
91
|
+
if (values.length === 0 && emptyAllowed) return undefined;
|
|
92
|
+
throw new XPathError(
|
|
93
|
+
"XPTY0004",
|
|
94
|
+
`A cast needs one atomic value, not ${values.length}`,
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Compilers by node type. */
|
|
99
|
+
export const typeCompilers = {
|
|
100
|
+
InstanceOfExpr(node, scope, compile) {
|
|
101
|
+
const expr = compile(node.expr, scope);
|
|
102
|
+
const type = compileSequenceType(node.sequenceType, scope.sc);
|
|
103
|
+
return (ctx) => [booleanItem(matchesSequenceType(expr(ctx), type))];
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
TreatExpr(node, scope, compile) {
|
|
107
|
+
const expr = compile(node.expr, scope);
|
|
108
|
+
const type = compileSequenceType(node.sequenceType, scope.sc);
|
|
109
|
+
return (ctx) => {
|
|
110
|
+
const value = expr(ctx);
|
|
111
|
+
if (!matchesSequenceType(value, type)) {
|
|
112
|
+
throw new XPathError(
|
|
113
|
+
"XPDY0050",
|
|
114
|
+
"The value does not match the type of treat as",
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
return value;
|
|
118
|
+
};
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
CastExpr(node, scope, compile) {
|
|
122
|
+
const expr = compile(node.expr, scope);
|
|
123
|
+
const caster = compileCastTarget(node.targetType, scope.sc);
|
|
124
|
+
return (ctx) => {
|
|
125
|
+
const value = castOperand(expr(ctx), node.emptyAllowed);
|
|
126
|
+
return value === undefined ? [] : caster(value);
|
|
127
|
+
};
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
CastableExpr(node, scope, compile) {
|
|
131
|
+
const expr = compile(node.expr, scope);
|
|
132
|
+
const caster = compileCastTarget(node.targetType, scope.sc);
|
|
133
|
+
return (ctx) => {
|
|
134
|
+
const values = atomize(expr(ctx));
|
|
135
|
+
if (values.length !== 1) {
|
|
136
|
+
return [booleanItem(values.length === 0 && node.emptyAllowed)];
|
|
137
|
+
}
|
|
138
|
+
try {
|
|
139
|
+
caster(values[0]);
|
|
140
|
+
return [booleanItem(true)];
|
|
141
|
+
} catch (error) {
|
|
142
|
+
if (!(error instanceof XPathError)) throw error;
|
|
143
|
+
return [booleanItem(false)];
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
},
|
|
147
|
+
};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolution of the type names written in an expression: atomic and union
|
|
3
|
+
* types of sequence types and casts, and the type annotations of element()
|
|
4
|
+
* and attribute() tests. Without a schema the in-scope schema types are
|
|
5
|
+
* the built-in ones; nodes are untyped (elements xs:untyped, attributes
|
|
6
|
+
* xs:untypedAtomic).
|
|
7
|
+
*
|
|
8
|
+
* @module @tradik/xslt3/xpath/eval/typeNames
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { XPathError } from "../../errors.js";
|
|
12
|
+
import { getType, types, XS_NAMESPACE } from "../../xdm/types.js";
|
|
13
|
+
import { namespaceOf } from "./staticContext.js";
|
|
14
|
+
|
|
15
|
+
/** Members of the union type xs:numeric. */
|
|
16
|
+
export const NUMERIC_MEMBERS = Object.freeze([
|
|
17
|
+
types.double,
|
|
18
|
+
types.float,
|
|
19
|
+
types.decimal,
|
|
20
|
+
]);
|
|
21
|
+
|
|
22
|
+
/** Built-in types that are neither atomic nor unions. */
|
|
23
|
+
const COMPLEX_OR_SIMPLE = new Set(["anyType", "anySimpleType", "untyped"]);
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @param {import("../syntax/ast.js").QName} name
|
|
27
|
+
* @param {import("./staticContext.js").StaticContext} sc
|
|
28
|
+
* @returns {{uri: string, local: string}} the expanded type name (the
|
|
29
|
+
* default element/type namespace applies)
|
|
30
|
+
*/
|
|
31
|
+
function expand(name, sc) {
|
|
32
|
+
return {
|
|
33
|
+
uri: namespaceOf(name, sc, sc.defaultElementNamespace),
|
|
34
|
+
local: name.local,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Looks up a built-in atomic type by local name.
|
|
40
|
+
* @param {string} local
|
|
41
|
+
* @returns {object|null}
|
|
42
|
+
*/
|
|
43
|
+
function builtIn(local) {
|
|
44
|
+
try {
|
|
45
|
+
return getType(local);
|
|
46
|
+
} catch {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Resolves the name of a generalized atomic type (an atomic type or
|
|
53
|
+
* xs:numeric) to its member types.
|
|
54
|
+
* @param {import("../syntax/ast.js").QName} name
|
|
55
|
+
* @param {import("./staticContext.js").StaticContext} sc
|
|
56
|
+
* @returns {object[]} atomic type descriptors (several for a union)
|
|
57
|
+
* @throws {XPathError} XPST0051 when the name is not a known atomic or
|
|
58
|
+
* union type, XPST0081 for an undeclared prefix
|
|
59
|
+
*/
|
|
60
|
+
export function resolveAtomicType(name, sc) {
|
|
61
|
+
const { uri, local } = expand(name, sc);
|
|
62
|
+
if (uri === XS_NAMESPACE) {
|
|
63
|
+
if (local === "numeric") return NUMERIC_MEMBERS;
|
|
64
|
+
const type = builtIn(local);
|
|
65
|
+
if (type) return [type];
|
|
66
|
+
}
|
|
67
|
+
throw new XPathError(
|
|
68
|
+
"XPST0051",
|
|
69
|
+
`${name.prefix ? `${name.prefix}:` : ""}${local} is not an atomic type`,
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Whether a type is a known schema type (for the type annotation of an
|
|
75
|
+
* element() or attribute() test).
|
|
76
|
+
* @param {{uri: string, local: string}} name
|
|
77
|
+
* @returns {boolean}
|
|
78
|
+
*/
|
|
79
|
+
const isKnownType = ({ uri, local }) =>
|
|
80
|
+
uri === XS_NAMESPACE &&
|
|
81
|
+
(COMPLEX_OR_SIMPLE.has(local) || local === "numeric" || !!builtIn(local));
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Whether untyped nodes of a kind have, or derive from, a type annotation.
|
|
85
|
+
* @param {import("../syntax/ast.js").QName} name - Type in an element() or
|
|
86
|
+
* attribute() test
|
|
87
|
+
* @param {"element"|"attribute"} kind
|
|
88
|
+
* @param {import("./staticContext.js").StaticContext} sc
|
|
89
|
+
* @returns {boolean} true when the nodes match the annotation
|
|
90
|
+
* @throws {XPathError} XPST0008 for an unknown type
|
|
91
|
+
*/
|
|
92
|
+
export function untypedMatches(name, kind, sc) {
|
|
93
|
+
const expanded = expand(name, sc);
|
|
94
|
+
if (!isKnownType(expanded)) {
|
|
95
|
+
throw new XPathError("XPST0008", `Unknown type ${name.local}`);
|
|
96
|
+
}
|
|
97
|
+
const { local } = expanded;
|
|
98
|
+
if (local === "anyType") return true;
|
|
99
|
+
if (kind === "element") return local === "untyped";
|
|
100
|
+
return ["anySimpleType", "anyAtomicType", "untypedAtomic"].includes(local);
|
|
101
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* URI resolution against a base URI (RFC 3986, through the WHATWG URL
|
|
3
|
+
* parser of the platform).
|
|
4
|
+
*
|
|
5
|
+
* @module @tradik/xslt3/xpath/eval/uris
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Resolves a URI against a base URI.
|
|
10
|
+
* @param {string} uri
|
|
11
|
+
* @param {string|undefined} base
|
|
12
|
+
* @returns {string} the absolute URI, or the URI unchanged when it cannot
|
|
13
|
+
* be resolved
|
|
14
|
+
*/
|
|
15
|
+
export function resolveUri(uri, base) {
|
|
16
|
+
try {
|
|
17
|
+
return new globalThis.URL(uri, base).href;
|
|
18
|
+
} catch {
|
|
19
|
+
return uri;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conversion of JavaScript values to XDM sequences, for variable values
|
|
3
|
+
* and the context item given to the public API.
|
|
4
|
+
*
|
|
5
|
+
* | JavaScript | XDM |
|
|
6
|
+
* |---|---|
|
|
7
|
+
* | null, undefined | empty sequence |
|
|
8
|
+
* | string | xs:string |
|
|
9
|
+
* | number | xs:double |
|
|
10
|
+
* | bigint | xs:integer |
|
|
11
|
+
* | boolean | xs:boolean |
|
|
12
|
+
* | Date | xs:dateTime (UTC) |
|
|
13
|
+
* | Array | sequence of the converted elements (flattened) |
|
|
14
|
+
* | Map, plain object | map with xs:string keys (Map keys converted) |
|
|
15
|
+
* | DOM node, XDM item | itself |
|
|
16
|
+
*
|
|
17
|
+
* @module @tradik/xslt3/xpath/eval/values
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { XdmMap } from "../../items/map.js";
|
|
21
|
+
import { AtomicValue, ITEM_KIND } from "../../xdm/atomic.js";
|
|
22
|
+
import { types } from "../../xdm/types.js";
|
|
23
|
+
import { dateTimeOf } from "./dynamicContext.js";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Converts a JS value used as a single atomic map key.
|
|
27
|
+
* @param {*} key
|
|
28
|
+
* @returns {AtomicValue}
|
|
29
|
+
*/
|
|
30
|
+
function keyOf(key) {
|
|
31
|
+
const [value] = toSequence(key);
|
|
32
|
+
return value instanceof AtomicValue
|
|
33
|
+
? value
|
|
34
|
+
: new AtomicValue(types.string, String(key));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Converts a JS value to an XDM sequence.
|
|
39
|
+
* @param {*} value
|
|
40
|
+
* @returns {Array} the sequence
|
|
41
|
+
*/
|
|
42
|
+
export function toSequence(value) {
|
|
43
|
+
if (value === null || value === undefined) return [];
|
|
44
|
+
switch (typeof value) {
|
|
45
|
+
case "string":
|
|
46
|
+
return [new AtomicValue(types.string, value)];
|
|
47
|
+
case "number":
|
|
48
|
+
return [new AtomicValue(types.double, value)];
|
|
49
|
+
case "bigint":
|
|
50
|
+
return [new AtomicValue(types.integer, value)];
|
|
51
|
+
case "boolean":
|
|
52
|
+
return [new AtomicValue(types.boolean, value)];
|
|
53
|
+
default:
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
if (Array.isArray(value)) return value.flatMap(toSequence);
|
|
57
|
+
if (value instanceof AtomicValue || value[ITEM_KIND]) return [value];
|
|
58
|
+
if (typeof value.nodeType === "number") return [value];
|
|
59
|
+
if (value instanceof Date) {
|
|
60
|
+
return [new AtomicValue(types.dateTime, dateTimeOf(value, 0))];
|
|
61
|
+
}
|
|
62
|
+
const entries = value instanceof Map ? [...value] : Object.entries(value);
|
|
63
|
+
return [XdmMap.from(entries.map(([k, v]) => [keyOf(k), toSequence(v)]))];
|
|
64
|
+
}
|