@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.
Files changed (286) hide show
  1. package/LICENSE.md +28 -0
  2. package/README.md +98 -2
  3. package/package.json +43 -4
  4. package/src/errors.js +20 -0
  5. package/src/functions/aggregates.js +144 -0
  6. package/src/functions/arraySort.js +33 -0
  7. package/src/functions/arrays.js +181 -0
  8. package/src/functions/attributeTypes.js +58 -0
  9. package/src/functions/baseUris.js +82 -0
  10. package/src/functions/collations.js +127 -0
  11. package/src/functions/collections.js +84 -0
  12. package/src/functions/context.js +83 -0
  13. package/src/functions/core.js +167 -0
  14. package/src/functions/datetime.js +203 -0
  15. package/src/functions/deepEqual.js +132 -0
  16. package/src/functions/diagnostics.js +88 -0
  17. package/src/functions/focus.js +34 -0
  18. package/src/functions/format/dateComponents.js +176 -0
  19. package/src/functions/format/datePicture.js +115 -0
  20. package/src/functions/format/decimalFormat.js +65 -0
  21. package/src/functions/format/digitPattern.js +145 -0
  22. package/src/functions/format/formatDateTime.js +204 -0
  23. package/src/functions/format/formatInteger.js +109 -0
  24. package/src/functions/format/formatNumber.js +165 -0
  25. package/src/functions/format/fractionFormat.js +80 -0
  26. package/src/functions/format/germanWords.js +89 -0
  27. package/src/functions/format/numberLanguages.js +41 -0
  28. package/src/functions/format/numberPicture.js +202 -0
  29. package/src/functions/format/numberWords.js +155 -0
  30. package/src/functions/format/place.js +74 -0
  31. package/src/functions/format/timezoneFormat.js +89 -0
  32. package/src/functions/higherOrder.js +106 -0
  33. package/src/functions/ids.js +127 -0
  34. package/src/functions/json/index.js +17 -0
  35. package/src/functions/json/jsonChars.js +110 -0
  36. package/src/functions/json/jsonParser.js +203 -0
  37. package/src/functions/json/jsonStrings.js +116 -0
  38. package/src/functions/json/jsonToXml.js +116 -0
  39. package/src/functions/json/parseJson.js +119 -0
  40. package/src/functions/json/xmlRepresentation.js +103 -0
  41. package/src/functions/json/xmlToJson.js +147 -0
  42. package/src/functions/library.js +47 -0
  43. package/src/functions/mapArrayEqual.js +41 -0
  44. package/src/functions/maps.js +152 -0
  45. package/src/functions/math.js +73 -0
  46. package/src/functions/nodePaths.js +181 -0
  47. package/src/functions/nodes.js +199 -0
  48. package/src/functions/numeric.js +148 -0
  49. package/src/functions/options.js +58 -0
  50. package/src/functions/parseIetfDate.js +104 -0
  51. package/src/functions/parseXml.js +77 -0
  52. package/src/functions/qnames.js +68 -0
  53. package/src/functions/random.js +128 -0
  54. package/src/functions/regex/analyzeString.js +144 -0
  55. package/src/functions/regex/charClass.js +112 -0
  56. package/src/functions/regex/compile.js +81 -0
  57. package/src/functions/regex/escapes.js +109 -0
  58. package/src/functions/regex/parser.js +169 -0
  59. package/src/functions/regex/reader.js +37 -0
  60. package/src/functions/regex/regexFunctions.js +140 -0
  61. package/src/functions/regex/translate.js +102 -0
  62. package/src/functions/regex/unicodeBlocks.js +194 -0
  63. package/src/functions/registry.js +140 -0
  64. package/src/functions/sequences.js +173 -0
  65. package/src/functions/serializeFunction.js +53 -0
  66. package/src/functions/signatures.js +105 -0
  67. package/src/functions/sort.js +102 -0
  68. package/src/functions/stringMatch.js +45 -0
  69. package/src/functions/strings.js +194 -0
  70. package/src/functions/stringsCore.js +66 -0
  71. package/src/functions/support.js +106 -0
  72. package/src/functions/textDecoding.js +117 -0
  73. package/src/functions/ucaCollation.js +127 -0
  74. package/src/functions/unparsedText.js +71 -0
  75. package/src/functions/uri.js +166 -0
  76. package/src/functions/xqueryModule.js +24 -0
  77. package/src/index.js +38 -0
  78. package/src/items/array.js +84 -0
  79. package/src/items/function.js +45 -0
  80. package/src/items/map.js +120 -0
  81. package/src/items/mapKey.js +82 -0
  82. package/src/serialize/index.js +129 -0
  83. package/src/serialize/markup/content.js +74 -0
  84. package/src/serialize/markup/dialect.js +178 -0
  85. package/src/serialize/markup/htmlData.js +70 -0
  86. package/src/serialize/markup/namespaces.js +145 -0
  87. package/src/serialize/markup/prolog.js +91 -0
  88. package/src/serialize/markup/writer.js +183 -0
  89. package/src/serialize/methods/adaptive.js +131 -0
  90. package/src/serialize/methods/json.js +158 -0
  91. package/src/serialize/methods/text.js +43 -0
  92. package/src/serialize/output/buffer.js +48 -0
  93. package/src/serialize/output/encoding.js +146 -0
  94. package/src/serialize/output/expander.js +204 -0
  95. package/src/serialize/params/fromElement.js +141 -0
  96. package/src/serialize/params/fromMap.js +128 -0
  97. package/src/serialize/params/names.js +69 -0
  98. package/src/serialize/params/settings.js +153 -0
  99. package/src/serialize/params/values.js +163 -0
  100. package/src/serialize/sequence.js +111 -0
  101. package/src/xdm/arithmetic.js +155 -0
  102. package/src/xdm/atomic.js +142 -0
  103. package/src/xdm/binary.js +92 -0
  104. package/src/xdm/calendar.js +71 -0
  105. package/src/xdm/cast.js +176 -0
  106. package/src/xdm/compare.js +192 -0
  107. package/src/xdm/datetime.js +206 -0
  108. package/src/xdm/decimal.js +200 -0
  109. package/src/xdm/duration.js +128 -0
  110. package/src/xdm/generalCompare.js +152 -0
  111. package/src/xdm/index.js +47 -0
  112. package/src/xdm/lexical.js +126 -0
  113. package/src/xdm/nodes.js +170 -0
  114. package/src/xdm/numeric.js +122 -0
  115. package/src/xdm/qname.js +65 -0
  116. package/src/xdm/strings.js +52 -0
  117. package/src/xdm/temporalArithmetic.js +180 -0
  118. package/src/xdm/timeline.js +68 -0
  119. package/src/xdm/types.js +178 -0
  120. package/src/xpath/eval/atomics.js +45 -0
  121. package/src/xpath/eval/axes.js +212 -0
  122. package/src/xpath/eval/calls.js +168 -0
  123. package/src/xpath/eval/coercion.js +146 -0
  124. package/src/xpath/eval/compiler.js +71 -0
  125. package/src/xpath/eval/constructors.js +129 -0
  126. package/src/xpath/eval/decimalFormats.js +93 -0
  127. package/src/xpath/eval/descendantMemo.js +77 -0
  128. package/src/xpath/eval/documentOrder.js +142 -0
  129. package/src/xpath/eval/domNodes.js +174 -0
  130. package/src/xpath/eval/dynamicCall.js +27 -0
  131. package/src/xpath/eval/dynamicContext.js +161 -0
  132. package/src/xpath/eval/flow.js +115 -0
  133. package/src/xpath/eval/functionItems.js +194 -0
  134. package/src/xpath/eval/groupedChildren.js +88 -0
  135. package/src/xpath/eval/inline.js +71 -0
  136. package/src/xpath/eval/namespaceNodes.js +90 -0
  137. package/src/xpath/eval/nodeTests.js +164 -0
  138. package/src/xpath/eval/operators.js +190 -0
  139. package/src/xpath/eval/paths.js +163 -0
  140. package/src/xpath/eval/positional.js +81 -0
  141. package/src/xpath/eval/predicates.js +56 -0
  142. package/src/xpath/eval/primary.js +99 -0
  143. package/src/xpath/eval/resources.js +149 -0
  144. package/src/xpath/eval/scope.js +108 -0
  145. package/src/xpath/eval/sequenceType.js +193 -0
  146. package/src/xpath/eval/staticContext.js +142 -0
  147. package/src/xpath/eval/steps.js +98 -0
  148. package/src/xpath/eval/subtype.js +154 -0
  149. package/src/xpath/eval/typeExprs.js +147 -0
  150. package/src/xpath/eval/typeNames.js +101 -0
  151. package/src/xpath/eval/uris.js +21 -0
  152. package/src/xpath/eval/values.js +64 -0
  153. package/src/xpath/index.js +217 -0
  154. package/src/xpath/syntax/ast.js +130 -0
  155. package/src/xpath/syntax/chars.js +58 -0
  156. package/src/xpath/syntax/constructors.js +144 -0
  157. package/src/xpath/syntax/expressions.js +107 -0
  158. package/src/xpath/syntax/index.js +44 -0
  159. package/src/xpath/syntax/kindTests.js +134 -0
  160. package/src/xpath/syntax/lexer.js +220 -0
  161. package/src/xpath/syntax/operators.js +111 -0
  162. package/src/xpath/syntax/paths.js +102 -0
  163. package/src/xpath/syntax/postfix.js +91 -0
  164. package/src/xpath/syntax/primaries.js +149 -0
  165. package/src/xpath/syntax/steps.js +146 -0
  166. package/src/xpath/syntax/syntaxError.js +31 -0
  167. package/src/xpath/syntax/tokenStream.js +163 -0
  168. package/src/xpath/syntax/typeAst.js +76 -0
  169. package/src/xpath/syntax/typeOperators.js +127 -0
  170. package/src/xpath/syntax/types.js +158 -0
  171. package/src/xslt/api.js +153 -0
  172. package/src/xslt/compiler/acceptance.js +178 -0
  173. package/src/xslt/compiler/accumulatorDecl.js +146 -0
  174. package/src/xslt/compiler/attributeValues.js +174 -0
  175. package/src/xslt/compiler/attributes.js +211 -0
  176. package/src/xslt/compiler/avt.js +103 -0
  177. package/src/xslt/compiler/body.js +154 -0
  178. package/src/xslt/compiler/children.js +105 -0
  179. package/src/xslt/compiler/compatibility.js +130 -0
  180. package/src/xslt/compiler/components.js +179 -0
  181. package/src/xslt/compiler/contextItem.js +95 -0
  182. package/src/xslt/compiler/decimalFormats.js +132 -0
  183. package/src/xslt/compiler/declarationKinds.js +82 -0
  184. package/src/xslt/compiler/elementInfo.js +246 -0
  185. package/src/xslt/compiler/expressions.js +175 -0
  186. package/src/xslt/compiler/globalContextItem.js +92 -0
  187. package/src/xslt/compiler/globals.js +209 -0
  188. package/src/xslt/compiler/linker.js +134 -0
  189. package/src/xslt/compiler/miscDecl.js +171 -0
  190. package/src/xslt/compiler/modeDecl.js +88 -0
  191. package/src/xslt/compiler/moduleLoading.js +111 -0
  192. package/src/xslt/compiler/modules.js +158 -0
  193. package/src/xslt/compiler/outputDecl.js +209 -0
  194. package/src/xslt/compiler/overrideLinks.js +141 -0
  195. package/src/xslt/compiler/packageChecks.js +84 -0
  196. package/src/xslt/compiler/packageRegistry.js +95 -0
  197. package/src/xslt/compiler/packageTable.js +181 -0
  198. package/src/xslt/compiler/packageVersions.js +143 -0
  199. package/src/xslt/compiler/packages.js +138 -0
  200. package/src/xslt/compiler/registry.js +234 -0
  201. package/src/xslt/compiler/staticStage.js +197 -0
  202. package/src/xslt/compiler/staticVariables.js +93 -0
  203. package/src/xslt/compiler/stylesheet.js +205 -0
  204. package/src/xslt/compiler/tailPosition.js +74 -0
  205. package/src/xslt/compiler/templatesDecl.js +180 -0
  206. package/src/xslt/compiler/useAccumulators.js +76 -0
  207. package/src/xslt/compiler/useWhen.js +94 -0
  208. package/src/xslt/compiler/visibility.js +160 -0
  209. package/src/xslt/index.js +11 -0
  210. package/src/xslt/instructions/analyzeString.js +137 -0
  211. package/src/xslt/instructions/assert.js +72 -0
  212. package/src/xslt/instructions/attributeSets.js +115 -0
  213. package/src/xslt/instructions/conditional.js +99 -0
  214. package/src/xslt/instructions/control.js +123 -0
  215. package/src/xslt/instructions/copy.js +151 -0
  216. package/src/xslt/instructions/elements.js +161 -0
  217. package/src/xslt/instructions/evaluate.js +189 -0
  218. package/src/xslt/instructions/fork.js +35 -0
  219. package/src/xslt/instructions/grouping.js +106 -0
  220. package/src/xslt/instructions/index.js +94 -0
  221. package/src/xslt/instructions/iterate.js +182 -0
  222. package/src/xslt/instructions/literal.js +142 -0
  223. package/src/xslt/instructions/maps.js +72 -0
  224. package/src/xslt/instructions/merge.js +190 -0
  225. package/src/xslt/instructions/number.js +205 -0
  226. package/src/xslt/instructions/output.js +102 -0
  227. package/src/xslt/instructions/params.js +110 -0
  228. package/src/xslt/instructions/resultDocument.js +143 -0
  229. package/src/xslt/instructions/sort.js +114 -0
  230. package/src/xslt/instructions/sourceDocument.js +73 -0
  231. package/src/xslt/instructions/templates.js +153 -0
  232. package/src/xslt/instructions/text.js +151 -0
  233. package/src/xslt/instructions/try.js +186 -0
  234. package/src/xslt/instructions/variables.js +119 -0
  235. package/src/xslt/names.js +204 -0
  236. package/src/xslt/patterns/axisOrigins.js +121 -0
  237. package/src/xslt/patterns/compile.js +151 -0
  238. package/src/xslt/patterns/general.js +132 -0
  239. package/src/xslt/patterns/grammar.js +190 -0
  240. package/src/xslt/patterns/modes.js +153 -0
  241. package/src/xslt/patterns/paths.js +130 -0
  242. package/src/xslt/patterns/patternChecks.js +29 -0
  243. package/src/xslt/patterns/steps.js +162 -0
  244. package/src/xslt/processor.js +178 -0
  245. package/src/xslt/runtime/accumulatorFunctions.js +48 -0
  246. package/src/xslt/runtime/accumulators.js +174 -0
  247. package/src/xslt/runtime/apply.js +153 -0
  248. package/src/xslt/runtime/atomicKeys.js +36 -0
  249. package/src/xslt/runtime/availability.js +162 -0
  250. package/src/xslt/runtime/baseUri.js +64 -0
  251. package/src/xslt/runtime/compilerHook.js +27 -0
  252. package/src/xslt/runtime/conditional.js +110 -0
  253. package/src/xslt/runtime/context.js +106 -0
  254. package/src/xslt/runtime/copy.js +123 -0
  255. package/src/xslt/runtime/copyFunctions.js +71 -0
  256. package/src/xslt/runtime/copyOrigins.js +60 -0
  257. package/src/xslt/runtime/defaultMethod.js +42 -0
  258. package/src/xslt/runtime/documentContent.js +93 -0
  259. package/src/xslt/runtime/dynamicXPath.js +90 -0
  260. package/src/xslt/runtime/functionCache.js +65 -0
  261. package/src/xslt/runtime/functionCall.js +57 -0
  262. package/src/xslt/runtime/functions.js +191 -0
  263. package/src/xslt/runtime/groups.js +108 -0
  264. package/src/xslt/runtime/invocation.js +156 -0
  265. package/src/xslt/runtime/iteration.js +107 -0
  266. package/src/xslt/runtime/keys.js +141 -0
  267. package/src/xslt/runtime/lazy.js +97 -0
  268. package/src/xslt/runtime/locations.js +86 -0
  269. package/src/xslt/runtime/machine.js +137 -0
  270. package/src/xslt/runtime/merging.js +167 -0
  271. package/src/xslt/runtime/namespaceScope.js +141 -0
  272. package/src/xslt/runtime/numberFormat.js +89 -0
  273. package/src/xslt/runtime/numbering.js +168 -0
  274. package/src/xslt/runtime/params.js +59 -0
  275. package/src/xslt/runtime/properties.js +103 -0
  276. package/src/xslt/runtime/rawResults.js +82 -0
  277. package/src/xslt/runtime/sequenceReceiver.js +102 -0
  278. package/src/xslt/runtime/snapshot.js +66 -0
  279. package/src/xslt/runtime/sortKeys.js +119 -0
  280. package/src/xslt/runtime/streamAvailable.js +60 -0
  281. package/src/xslt/runtime/strip.js +102 -0
  282. package/src/xslt/runtime/transformFunction.js +169 -0
  283. package/src/xslt/runtime/transformation.js +168 -0
  284. package/src/xslt/runtime/transformationContext.js +85 -0
  285. package/src/xslt/runtime/treeReceiver.js +194 -0
  286. 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
+ }