leptris 1.9.287.0-ppc64le-linux → 1.9.290.0-ppc64le-linux
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.
- checksums.yaml +4 -4
- data/Rakefile +1 -1
- data/lib/leptris/version.rb +1 -1
- data/lib/leptris/xml/descriptor.rb +12 -0
- data/lib/leptris/xml/ffi.rb +7 -1
- data/lib/libleptris.so +0 -0
- data/vendor-src/README.md +1 -1
- data/vendor-src/libleptris/CHANGELOG.md +32 -0
- data/vendor-src/libleptris/CMakeLists.txt +1 -1
- data/vendor-src/libleptris/src/include/leptris/descriptor.h +12 -0
- data/vendor-src/libleptris/src/include/leptris.h +39 -18
- data/vendor-src/libleptris/src/leptris/descriptor/plan.c +72 -1
- data/vendor-src/libleptris/src/leptris/html/html_parse.c +190 -151
- data/vendor-src/libleptris/src/leptris/xslt/xslt_exec.c +64 -39
- data/vendor-src/libleptris/src/leptris/xslt/xslt_internal.h +16 -11
- data/vendor-src/libleptris/src/leptris/xslt/xslt_public.c +36 -20
- data/vendor-src/libleptris/test/abi/test_descriptor.cpp +74 -0
- data/vendor-src/libleptris/test/xpath/test_xslt.cpp +85 -2
- data/vendor-src/libleptris/test/xquery/qt3/fn/not.xml +771 -0
- data/vendor-src/libleptris/test/xquery/test_qt3.cpp +11 -0
- data/vendor-src/libleptris/vcpkg.json +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 505fb9e6093b335b955a6c776e97beb0cd43d9e498d8f44333b3faccc93bee26
|
|
4
|
+
data.tar.gz: 69b07068ad720f0da28fbc713625884621cf067a0fe0134b88bed2eba8549fa5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: aba2088b46d2f97563715259e4a8c8f12fa49f5918a42272f849c64030aad24fa0051449e9f29a0e90c5f7e118be49cc8dc9eae14f4575f4c7552c524715205c
|
|
7
|
+
data.tar.gz: ea9d90fb9c71b40bcd3692b81d138752a9e4d5aca9943baa6f6a62769f1136773cb0b54e28ed36e0c7ca4a46c7e40b874351f4d76ebdbf227d64611f38502bad
|
data/Rakefile
CHANGED
|
@@ -8,7 +8,7 @@ RSpec::Core::RakeTask.new(:spec)
|
|
|
8
8
|
# Pin for `rake compile` and the platform-gem builds. Keep in lockstep
|
|
9
9
|
# with .github/workflows/build.yml (which calls `rake compile`) and the
|
|
10
10
|
# CHANGELOG when libleptris releases.
|
|
11
|
-
LIBLEPTRIS_VERSION = "1.9.
|
|
11
|
+
LIBLEPTRIS_VERSION = "1.9.290"
|
|
12
12
|
# Vendored alongside libleptris for fn:normalize-unicode (TODO
|
|
13
13
|
# .restructure/20): built per platform with a RELOCATABLE @rpath
|
|
14
14
|
# install name, loaded by ffi.rb before libleptris so the
|
data/lib/leptris/version.rb
CHANGED
|
@@ -167,6 +167,18 @@ class Leptris::XML::Descriptor
|
|
|
167
167
|
ap[:wire_name] = anchor_string(anchors, row.fetch(:name))
|
|
168
168
|
ap[:kind] = kind_code(row[:kind] || :scalar)
|
|
169
169
|
ap[:type_tag] = type_tag_code(row)
|
|
170
|
+
# Attribute-level namespace form (libleptris 1.9.289, #1486):
|
|
171
|
+
# ns rows match by (URI, local) — the wire prefix is irrelevant.
|
|
172
|
+
# Mirrors the child-row packing.
|
|
173
|
+
ap[:ns_form] =
|
|
174
|
+
case row[:ns]
|
|
175
|
+
when :any then Leptris::XML::FFI::PLAN_NS_ANY
|
|
176
|
+
when Hash then Leptris::XML::FFI::PLAN_NS_EXACT
|
|
177
|
+
else Leptris::XML::FFI::PLAN_NS_NONE
|
|
178
|
+
end
|
|
179
|
+
ap[:ns_uri] =
|
|
180
|
+
row[:ns].is_a?(Hash) ?
|
|
181
|
+
anchor_string(anchors, row[:ns].fetch(:exact)) : nil
|
|
170
182
|
pack_predicates(ap, row, anchors)
|
|
171
183
|
end
|
|
172
184
|
ep[:attribute_count] = attrs.size
|
data/lib/leptris/xml/ffi.rb
CHANGED
|
@@ -299,7 +299,13 @@ module Leptris
|
|
|
299
299
|
:type_tag, :uint8,
|
|
300
300
|
:predicate_count, :uint16,
|
|
301
301
|
:pad_pred, :uint16,
|
|
302
|
-
:predicates, :pointer
|
|
302
|
+
:predicates, :pointer,
|
|
303
|
+
# libleptris 1.9.289 (#1486): attribute-level namespace
|
|
304
|
+
# form — ns rows match by (URI, local), wire_name is the
|
|
305
|
+
# LOCAL name; NONE keeps wire-name-exact matching.
|
|
306
|
+
:ns_form, :uint8,
|
|
307
|
+
:pad_ns, :uint8,
|
|
308
|
+
:ns_uri, :pointer
|
|
303
309
|
end
|
|
304
310
|
class ChildPlan < ::FFI::Struct
|
|
305
311
|
layout :wire_name, :pointer,
|
data/lib/libleptris.so
CHANGED
|
Binary file
|
data/vendor-src/README.md
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [1.9.290] - 2026-10-02
|
|
4
|
+
|
|
5
|
+
<!-- Edit this section with the actual release notes. -->
|
|
6
|
+
<!-- See https://keepachangelog.com for format guidance. -->
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
- namespace forms for attribute plan rows — `ns_form`/`ns_uri` on `leptris_attr_plan` (#1486)
|
|
11
|
+
- Extends #1115's child-row pattern to attribute rows: `ns_form = 0` (the zero value) keeps the historical wire-name lookup byte-for-byte and existing aggregate initializers stay valid; `LEPTRIS_PLAN_NS_EXACT` + `ns_uri` makes `wire_name` the LOCAL name and binds the (namespace URI, local) identity through the element's in-scope prefix bindings — prefix-spelling-independent, so a `w14:paraId`-typed row binds whatever prefix the document uses for the Word 2010 URI. `LEPTRIS_PLAN_NS_ANY` matches the local name in any namespace; unprefixed attributes have no namespace and never bind EXACT (XML Namespaces §5.2).
|
|
12
|
+
- Unlocks the plan fast path for typed-attribute models: lutaml-model's `attr_type_ns` opt-out (one `w14:paraId` leaf cascading the WordprocessingML paragraph chain out of the plan path, against a measured 33% parse-CPU saving) can now emit ns-exact attribute rows instead.
|
|
13
|
+
- Build deep-copies `ns_uri`, zero-guards the trailing fields for hosts that `malloc` the spec without value-initialization (#1272 lesson), rejects `EXACT` without a URI as `INVALID_ARG`; free releases the copies. RED-first spec plus the full battery (1773/1773). (#1487)
|
|
14
|
+
|
|
15
|
+
## [1.9.289] - 2026-10-02
|
|
16
|
+
|
|
17
|
+
### Performance
|
|
18
|
+
|
|
19
|
+
- open-id compares for the scope/table-context stack walks (#1218 slice 6, tranche 2) (html)
|
|
20
|
+
- The scope walks (p-in-button-scope, button-in-scope, AFE `kn`), the table-context searches, and the table-context dispatch block compare `b->open_id[k]` integers instead of fetching the element name and running case-insensitive literal chains per stack slot. The AFE furthest-block scan deliberately keeps the name fetch — it runs mid-AFE between stack splices, where the id stack is not yet authoritative (webkit02:14). Interleaved A/B vs the tranche-1 tree: 48.2-53.7 -> 51.0-58.2 MB/s (+11% median) on the 2.6MB table-rows shape. (#1485)
|
|
21
|
+
- id-LUT membership for the foster/formatting/stack checks (#1218 slice 6) (html)
|
|
22
|
+
- The classifier table grows the 22 compared-but-unlisted names (HTML4 formatting set + MathML/SVG integration points, inert flags); `h_is_formatting` (14-way) and `h_fosterable` (15-way) become id-LUT lookups; 15 insertion-mode stack checks read `open_id[]` directly. 56.1 -> 59.0 MB/s (+5.2%) interleaved. Cumulative slice 6: ~+15% on the issue's fixture shape; the 3.4-7x deficit the issue reported at 1.9.203 is now a 1.3-1.55x LEAD over htmlReadMemory locally. (#1484)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
## [1.9.288] - 2026-10-02
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
|
|
30
|
+
- top-level param values are XPath expressions (libxslt convention) — follow-up to #1478 (xslt)
|
|
31
|
+
- **Semantics correction to `leptris_xslt_apply_params` / `leptris_xslt_apply_string_params`, released briefly in 1.9.287:** value strings are now evaluated as XPath EXPRESSIONS (libxslt `params` convention; nokogiri's `quote_params` exists for exactly this), not bound as raw strings. Callers pass quoted literals — `{"n", "'7'"}` binds the string `7`; under 1.9.287 the quotes were part of the value. Numbers and source-derived expressions work (`7 * 6` → 42, `string(/r/@v)`), a later pair may reference an earlier one, a global `xsl:variable` may consume a caller value (§11 ordering), undeclared names bind into scope (libxslt parity), and a malformed expression fails the transform. Caller values bind before the globals run and a declared `xsl:param` default whose name a caller supplied never evaluates (§11.4). Specs ported from #1478 plus three RED-first expression cases; 1771/1771 and an external-consumer end-to-end probe. (#1481)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
3
35
|
## [1.9.287] - 2026-10-02
|
|
4
36
|
|
|
5
37
|
### Added
|
|
@@ -95,6 +95,18 @@ typedef struct {
|
|
|
95
95
|
uint16_t predicate_count;
|
|
96
96
|
uint16_t pad_pred;
|
|
97
97
|
const leptris_attr_predicate* predicates;
|
|
98
|
+
/* #1486 (additive trailing fields, the #1115 child-row
|
|
99
|
+
* pattern): attribute-level namespace form. A row with
|
|
100
|
+
* ns_form set matches by (namespace URI, local name) —
|
|
101
|
+
* wire_name is the LOCAL name and the prefix spelling on the
|
|
102
|
+
* wire is irrelevant. NONE (0, the zero value) keeps the
|
|
103
|
+
* historical behavior: lookup by wire_name exactly as it
|
|
104
|
+
* appears on the wire (prefixed or bare). Unprefixed
|
|
105
|
+
* attributes have no namespace; EXACT requires a prefixed
|
|
106
|
+
* attribute whose prefix binds to ns_uri. */
|
|
107
|
+
uint8_t ns_form; /* LeptrisPlanNsForm */
|
|
108
|
+
uint8_t pad_ns;
|
|
109
|
+
const char* ns_uri; /* LEPTRIS_PLAN_NS_EXACT only */
|
|
98
110
|
} leptris_attr_plan;
|
|
99
111
|
|
|
100
112
|
typedef struct {
|
|
@@ -3096,20 +3096,6 @@ LEPTRIS_API void leptris_xslt_free(LeptrisXslt xslt);
|
|
|
3096
3096
|
*/
|
|
3097
3097
|
LEPTRIS_API LeptrisDocument leptris_xslt_apply(LeptrisXslt xslt,
|
|
3098
3098
|
LeptrisDocument doc);
|
|
3099
|
-
/**
|
|
3100
|
-
* Apply a compiled stylesheet with top-level xsl:param overrides
|
|
3101
|
-
*
|
|
3102
|
-
* `pairs` is a flat name/value array: 2*pair_count entries,
|
|
3103
|
-
* pairs[2*i] is the param name, pairs[2*i+1] its string value
|
|
3104
|
-
* (bound as an XPath string — consumers doing numeric quoting own
|
|
3105
|
-
* that, matching libxslt conventions). A supplied name never
|
|
3106
|
-
* evaluates the param's select/@default; absent names keep them.
|
|
3107
|
-
* The array is borrowed for the duration of the call only.
|
|
3108
|
-
*/
|
|
3109
|
-
LEPTRIS_API LeptrisDocument leptris_xslt_apply_params(
|
|
3110
|
-
LeptrisXslt xslt, LeptrisDocument doc,
|
|
3111
|
-
const char* const* pairs, size_t pair_count);
|
|
3112
|
-
|
|
3113
3099
|
/**
|
|
3114
3100
|
* Apply a compiled stylesheet and serialize the result
|
|
3115
3101
|
*
|
|
@@ -3123,15 +3109,50 @@ LEPTRIS_API LeptrisDocument leptris_xslt_apply_params(
|
|
|
3123
3109
|
*/
|
|
3124
3110
|
LEPTRIS_API char* leptris_xslt_apply_string(LeptrisXslt xslt,
|
|
3125
3111
|
LeptrisDocument doc);
|
|
3112
|
+
|
|
3113
|
+
/**
|
|
3114
|
+
* Apply a compiled stylesheet with caller-supplied top-level params
|
|
3115
|
+
*
|
|
3116
|
+
* Binds the given xsl:param values BEFORE the stylesheet's globals
|
|
3117
|
+
* run (XSLT §11.4): a caller value replaces the declared default,
|
|
3118
|
+
* unspecified params keep their defaults, and the value expressions
|
|
3119
|
+
* may reference the source document and earlier pairs.
|
|
3120
|
+
*
|
|
3121
|
+
* pairs is a flat name/value array — [name0, value0, name1,
|
|
3122
|
+
* value1, ...] — and count is the number of PAIRS (the array holds
|
|
3123
|
+
* 2*count entries). Each value is an XPath EXPRESSION evaluated
|
|
3124
|
+
* with the source document node as context; callers pre-quote
|
|
3125
|
+
* string literals ("'text'"), matching the libxslt convention.
|
|
3126
|
+
*
|
|
3127
|
+
* @param xslt Compiled stylesheet
|
|
3128
|
+
* @param doc Source document (not modified)
|
|
3129
|
+
* @param pairs Flat name/expression array, or NULL with count 0
|
|
3130
|
+
* @param count Number of name/expression pairs
|
|
3131
|
+
* @return Result tree (free with leptris_document_free), or NULL on
|
|
3132
|
+
* error — including a value expression that fails to
|
|
3133
|
+
* compile (message via leptris_document_last_error)
|
|
3134
|
+
*/
|
|
3135
|
+
LEPTRIS_API LeptrisDocument leptris_xslt_apply_params(
|
|
3136
|
+
LeptrisXslt xslt, LeptrisDocument doc,
|
|
3137
|
+
const char* const* pairs, size_t count);
|
|
3138
|
+
|
|
3126
3139
|
/**
|
|
3127
|
-
* Apply with top-level
|
|
3140
|
+
* Apply with caller-supplied top-level params and serialize
|
|
3141
|
+
*
|
|
3142
|
+
* leptris_xslt_apply_params + the leptris_xslt_apply_string
|
|
3143
|
+
* serialization contract (top-level text nodes and fragments
|
|
3144
|
+
* preserved).
|
|
3128
3145
|
*
|
|
3129
|
-
*
|
|
3130
|
-
*
|
|
3146
|
+
* @param xslt Compiled stylesheet
|
|
3147
|
+
* @param doc Source document
|
|
3148
|
+
* @param pairs Flat name/expression array (see
|
|
3149
|
+
* leptris_xslt_apply_params), or NULL with count 0
|
|
3150
|
+
* @param count Number of name/expression pairs
|
|
3151
|
+
* @return Serialized result (free with leptris_free_string), or NULL
|
|
3131
3152
|
*/
|
|
3132
3153
|
LEPTRIS_API char* leptris_xslt_apply_string_params(
|
|
3133
3154
|
LeptrisXslt xslt, LeptrisDocument doc,
|
|
3134
|
-
const char* const* pairs, size_t
|
|
3155
|
+
const char* const* pairs, size_t count);
|
|
3135
3156
|
|
|
3136
3157
|
/**
|
|
3137
3158
|
* Custom XPath function handler (string-valued).
|
|
@@ -246,6 +246,7 @@ static void dp_plan_free(LeptrisPlan p) {
|
|
|
246
246
|
dp_plan* d = &p->plans[i];
|
|
247
247
|
for (uint32_t a = 0; a < d->attribute_count; a++) {
|
|
248
248
|
free((char *)d->attribute_plans[a].wire_name);
|
|
249
|
+
free((char *)d->attribute_plans[a].ns_uri);
|
|
249
250
|
for (uint16_t pi = 0;
|
|
250
251
|
pi < d->attribute_plans[a].predicate_count; pi++) {
|
|
251
252
|
free((char*)d->attribute_plans[a]
|
|
@@ -332,6 +333,32 @@ LEPTRIS_API LeptrisPlan leptris_plan_build(const leptris_plan_spec* spec,
|
|
|
332
333
|
d->attribute_plans[a].predicate_count = 0;
|
|
333
334
|
d->attribute_plans[a].pad_pred = 0;
|
|
334
335
|
}
|
|
336
|
+
/* #1486 additive-ABI guard (the #1272 lesson): a
|
|
337
|
+
* host that mallocs the spec leaves the trailing
|
|
338
|
+
* ns fields garbage — normalize unset forms so the
|
|
339
|
+
* walker never reads a garbage pointer, and deep-
|
|
340
|
+
* copy EXACT uris. EXACT without a uri cannot
|
|
341
|
+
* express an identity: reject the spec. */
|
|
342
|
+
if (!s->attribute_plans[a].ns_form) {
|
|
343
|
+
d->attribute_plans[a].ns_form = 0;
|
|
344
|
+
d->attribute_plans[a].pad_ns = 0;
|
|
345
|
+
d->attribute_plans[a].ns_uri = NULL;
|
|
346
|
+
} else {
|
|
347
|
+
d->attribute_plans[a].pad_ns = 0;
|
|
348
|
+
if (s->attribute_plans[a].ns_form ==
|
|
349
|
+
LEPTRIS_PLAN_NS_EXACT) {
|
|
350
|
+
if (!s->attribute_plans[a].ns_uri) {
|
|
351
|
+
if (status) *status = LEPTRIS_ERROR_INVALID_ARG;
|
|
352
|
+
dp_plan_free(p);
|
|
353
|
+
return NULL;
|
|
354
|
+
}
|
|
355
|
+
d->attribute_plans[a].ns_uri =
|
|
356
|
+
dp_strdup(s->attribute_plans[a].ns_uri);
|
|
357
|
+
if (!d->attribute_plans[a].ns_uri) goto oom;
|
|
358
|
+
} else {
|
|
359
|
+
d->attribute_plans[a].ns_uri = NULL;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
335
362
|
if (s->attribute_plans[a].wire_name) {
|
|
336
363
|
d->attribute_plans[a].wire_name =
|
|
337
364
|
dp_strdup(s->attribute_plans[a].wire_name);
|
|
@@ -491,6 +518,50 @@ static int dp_walk_children(LeptrisElement elem, const dp_plan* plan,
|
|
|
491
518
|
const LeptrisPlan pool,
|
|
492
519
|
struct leptris_plan_result* out);
|
|
493
520
|
|
|
521
|
+
/* #1486 attribute-row binding. ns_form 0 = the historical
|
|
522
|
+
* wire-name lookup (the string exactly as it appears on the
|
|
523
|
+
* wire). A set form matches (namespace, local): the row's
|
|
524
|
+
* wire_name is the LOCAL name; each attribute's prefix resolves
|
|
525
|
+
* through the ELEMENT's in-scope bindings, so the identity holds
|
|
526
|
+
* across prefix spellings. Unprefixed attributes have no
|
|
527
|
+
* namespace (XML namespaces §5.2) — EXACT never binds them. */
|
|
528
|
+
static const char* dp_attr_value(LeptrisElement elem,
|
|
529
|
+
const leptris_attr_plan* ap) {
|
|
530
|
+
if (!ap->ns_form)
|
|
531
|
+
return leptris_element_attribute(elem, ap->wire_name);
|
|
532
|
+
for (LeptrisAttribute at = leptris_element_first_attribute(elem);
|
|
533
|
+
at; at = leptris_attribute_next(at)) {
|
|
534
|
+
const char* qn = leptris_attribute_get_name(at);
|
|
535
|
+
if (!qn) continue;
|
|
536
|
+
const char* colon = strchr(qn, ':');
|
|
537
|
+
const char* local = colon ? colon + 1 : qn;
|
|
538
|
+
if (strcmp(local, ap->wire_name) != 0) continue;
|
|
539
|
+
const char* uri = NULL;
|
|
540
|
+
if (colon) {
|
|
541
|
+
char prefix[128];
|
|
542
|
+
size_t plen = (size_t)(colon - qn);
|
|
543
|
+
if (plen >= sizeof(prefix)) continue;
|
|
544
|
+
memcpy(prefix, qn, plen);
|
|
545
|
+
prefix[plen] = 0;
|
|
546
|
+
uri = leptris_element_namespace_for_prefix(elem, prefix);
|
|
547
|
+
}
|
|
548
|
+
switch (ap->ns_form) {
|
|
549
|
+
case LEPTRIS_PLAN_NS_NONE:
|
|
550
|
+
if (uri) continue;
|
|
551
|
+
break;
|
|
552
|
+
case LEPTRIS_PLAN_NS_EXACT:
|
|
553
|
+
if (!uri || !ap->ns_uri ||
|
|
554
|
+
strcmp(uri, ap->ns_uri) != 0)
|
|
555
|
+
continue;
|
|
556
|
+
break;
|
|
557
|
+
default: /* ANY */
|
|
558
|
+
break;
|
|
559
|
+
}
|
|
560
|
+
return leptris_attribute_get_value(elem, at);
|
|
561
|
+
}
|
|
562
|
+
return NULL;
|
|
563
|
+
}
|
|
564
|
+
|
|
494
565
|
static struct leptris_plan_result* dp_walk_element(LeptrisElement elem,
|
|
495
566
|
const dp_plan* plan,
|
|
496
567
|
const LeptrisPlan pool) {
|
|
@@ -510,7 +581,7 @@ static struct leptris_plan_result* dp_walk_element(LeptrisElement elem,
|
|
|
510
581
|
for (uint32_t a = 0; a < plan->attribute_count; a++) {
|
|
511
582
|
const leptris_attr_plan* ap = &plan->attribute_plans[a];
|
|
512
583
|
if (!ap->wire_name) continue;
|
|
513
|
-
const char* val =
|
|
584
|
+
const char* val = dp_attr_value(elem, ap);
|
|
514
585
|
if (!val) continue;
|
|
515
586
|
v->attr_names[v->attr_count] = dp_strdup(ap->wire_name);
|
|
516
587
|
v->attr_values[v->attr_count] = dp_strdup(val);
|