@barefootjs/perl 0.16.0 → 0.17.1
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/lib/BarefootJS/DevReload.pm +1 -1
- package/lib/BarefootJS/Evaluator.pm +635 -0
- package/lib/BarefootJS.pm +120 -8
- package/package.json +1 -1
- package/t/eval_vectors.t +113 -0
- package/t/evaluator.t +333 -0
- package/t/helper_vectors.t +15 -5
- package/t/query.t +49 -0
- package/t/template_primitives.t +15 -4
package/t/helper_vectors.t
CHANGED
|
@@ -9,6 +9,12 @@ use Scalar::Util qw(looks_like_number);
|
|
|
9
9
|
use lib "$FindBin::Bin/../lib";
|
|
10
10
|
use BarefootJS;
|
|
11
11
|
|
|
12
|
+
# vectors.json is UTF-8 (string args like "café"; `≡` in some notes). Decode it
|
|
13
|
+
# as UTF-8 (below) and route TAP through a UTF-8 layer so wide test names don't
|
|
14
|
+
# trigger "Wide character in print".
|
|
15
|
+
binmode Test::More->builder->$_, ':encoding(UTF-8)'
|
|
16
|
+
for qw(output failure_output todo_output);
|
|
17
|
+
|
|
12
18
|
# Pure-Perl backend (core JSON::PP only) so this test runs with zero
|
|
13
19
|
# Mojo present — same pattern as t/template_primitives.t.
|
|
14
20
|
{
|
|
@@ -37,7 +43,10 @@ plan skip_all => 'golden vectors not available outside the monorepo checkout'
|
|
|
37
43
|
my $doc = do {
|
|
38
44
|
open my $fh, '<:raw', $vectors_path or die "open $vectors_path: $!";
|
|
39
45
|
local $/;
|
|
40
|
-
|
|
46
|
+
# ->utf8 decodes the file's UTF-8 bytes into Perl characters, so a value
|
|
47
|
+
# like "café" round-trips to a single é (U+00E9) instead of its two raw
|
|
48
|
+
# bytes — otherwise _form_escape would re-encode them and double-escape.
|
|
49
|
+
JSON::PP->new->utf8->decode(scalar <$fh>);
|
|
41
50
|
};
|
|
42
51
|
|
|
43
52
|
# One binding per canonical helper id in the spec catalogue, bound to
|
|
@@ -99,6 +108,11 @@ my %bindings = (
|
|
|
99
108
|
# and '' for present-but-empty, so the Perl backend matches JS exactly.
|
|
100
109
|
search_params_get => sub { BarefootJS->search_params($_[0])->get($_[1]) },
|
|
101
110
|
|
|
111
|
+
# queryHref SSR builder (#2042): (base, include, key, value, …) → URL. The
|
|
112
|
+
# include flags arrive as JSON booleans (JSON::PP::Boolean, truthy/falsy
|
|
113
|
+
# under `next unless`); the helper form-encodes to match URLSearchParams.
|
|
114
|
+
query => sub { $bf->query(@_) },
|
|
115
|
+
|
|
102
116
|
# Higher-order entries arrive in the canonical projection form
|
|
103
117
|
# (spec: items + field [+ value]); the closures below rebuild the
|
|
104
118
|
# predicate the adapters compile (`i => i.field === value`,
|
|
@@ -210,10 +224,6 @@ my %DIVERGENCES = (
|
|
|
210
224
|
expect => '0.3',
|
|
211
225
|
reason => 'Perl stringifies doubles via %.15g',
|
|
212
226
|
},
|
|
213
|
-
'includes/cross-type probe is strict-equality false' => {
|
|
214
|
-
expect => 1,
|
|
215
|
-
reason => 'bf->includes scans with eq (string equality), so 2 eq "2" matches',
|
|
216
|
-
},
|
|
217
227
|
'filter_truthy/the string "0" is truthy' => {
|
|
218
228
|
expect => ['x'],
|
|
219
229
|
reason => 'Perl truthiness treats the string "0" as false',
|
package/t/query.t
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
use Test2::V0;
|
|
2
|
+
use utf8;
|
|
3
|
+
|
|
4
|
+
# BarefootJS->query — the `queryHref(base, { … })` URL-query builder helper
|
|
5
|
+
# (#2042).
|
|
6
|
+
#
|
|
7
|
+
# The full CROSS-BACKEND behaviour (control flow + form-encoding parity with the
|
|
8
|
+
# browser's URLSearchParams) is defined ONCE in the shared golden helper vectors
|
|
9
|
+
# — packages/adapter-tests/helper-vectors/vectors.json, fn "query" — and run
|
|
10
|
+
# here by t/helper_vectors.t and by the Go runtime's TestHelperVectors, so the
|
|
11
|
+
# Perl and Go expectations can't drift apart.
|
|
12
|
+
#
|
|
13
|
+
# This file keeps a few representative cases for always-on coverage (the golden
|
|
14
|
+
# file is monorepo-only, absent from the CPAN dist) plus the Perl-runtime-
|
|
15
|
+
# SPECIFIC defensive behaviour the golden vectors can't express: an `undef`
|
|
16
|
+
# value. JSON has no `undefined`, and a JSON `null` stringifies to "null" under
|
|
17
|
+
# JS `String()`, so it can't be a shared vector; Perl coerces `undef` to '' and
|
|
18
|
+
# omits the empty pair.
|
|
19
|
+
|
|
20
|
+
use FindBin qw($Bin);
|
|
21
|
+
use lib "$Bin/../lib";
|
|
22
|
+
|
|
23
|
+
use BarefootJS;
|
|
24
|
+
|
|
25
|
+
# `query` is a pure helper (no backend / controller), so a bare blessed stub is
|
|
26
|
+
# enough — mirroring t/helper_vectors.t. Triples are (include, key, value).
|
|
27
|
+
my $bf = bless {}, 'BarefootJS';
|
|
28
|
+
|
|
29
|
+
# Representative control flow: a repeated key overwrites at its first position
|
|
30
|
+
# (URLSearchParams.set), surrounding order preserved.
|
|
31
|
+
is $bf->query('/blog', 1, 'sort', 'title', 1, 'tag', 'go', 1, 'sort', 'date'),
|
|
32
|
+
'/blog?sort=date&tag=go', 'order preserved, repeated key overwrites at first position';
|
|
33
|
+
|
|
34
|
+
# Representative form-encoding: space → '+', '~' → %7E, '*' kept (URLSearchParams,
|
|
35
|
+
# not Go's url.QueryEscape).
|
|
36
|
+
is $bf->query('/s', 1, 't', 'a~b *c'), '/s?t=a%7Eb+*c', 'form-encode: ~ → %7E, * kept, space → +';
|
|
37
|
+
|
|
38
|
+
# Representative array value: an array ref appends one pair per non-empty member
|
|
39
|
+
# (#2048), skipping empties.
|
|
40
|
+
is $bf->query('/list', 1, 'tag', ['a', '', 'b']), '/list?tag=a&tag=b',
|
|
41
|
+
'array value appends a pair per non-empty member';
|
|
42
|
+
|
|
43
|
+
# Perl-specific: an `undef` value is coerced to '' and then omitted, without
|
|
44
|
+
# disturbing the surrounding pairs.
|
|
45
|
+
is $bf->query('/list', 1, 'tag', undef), '/list', 'undef value coerced to empty → omitted';
|
|
46
|
+
is $bf->query('/list', 1, 'tag', undef, 1, 'keep', 'me'), '/list?keep=me',
|
|
47
|
+
'undef value dropped, surrounding pairs intact';
|
|
48
|
+
|
|
49
|
+
done_testing;
|
package/t/template_primitives.t
CHANGED
|
@@ -81,11 +81,16 @@ subtest 'floor / ceil / round — Math.* mirrors; propagate NaN' => sub {
|
|
|
81
81
|
# `Array.prototype.includes(x)` + `String.prototype.includes(sub)` lower
|
|
82
82
|
# to the same `$bf->includes($recv, $elem)` shape — see #1448 Tier A.
|
|
83
83
|
# The Perl helper dispatches on `ref()`: ARRAY ref scans elements with
|
|
84
|
-
# `
|
|
85
|
-
#
|
|
86
|
-
# `.includes`
|
|
84
|
+
# `BarefootJS::Evaluator::_same_value_zero` (SameValueZero — no cross-type
|
|
85
|
+
# coercion, NaN matches NaN), matching the evaluator's serialized-callback
|
|
86
|
+
# `.includes` path so both positions agree; scalar falls back to
|
|
87
|
+
# `index(..., ...) != -1`. Anything else (HASH ref, code ref) returns
|
|
88
|
+
# false to match the JS semantic that `.includes` is only defined on
|
|
89
|
+
# Array / TypedArray / String.
|
|
87
90
|
subtest 'includes — array + string + non-array/string dispatch' => sub {
|
|
88
|
-
# Array receiver: element
|
|
91
|
+
# Array receiver: SameValueZero element search (handles defined/undef
|
|
92
|
+
# parity, and no numeric/string coercion — see the cross-type cases
|
|
93
|
+
# below).
|
|
89
94
|
ok $bf->includes(['a', 'b', 'c'], 'b'), 'array contains element → 1';
|
|
90
95
|
ok !$bf->includes(['a', 'b', 'c'], 'z'), 'array does not contain → 0';
|
|
91
96
|
ok $bf->includes([1, 2, 3], 2), 'numeric element';
|
|
@@ -93,6 +98,12 @@ subtest 'includes — array + string + non-array/string dispatch' => sub {
|
|
|
93
98
|
ok $bf->includes([undef, 'a'], undef), 'undef element matches undef needle';
|
|
94
99
|
ok !$bf->includes(['a', 'b'], undef), 'undef needle, no undef element → 0';
|
|
95
100
|
|
|
101
|
+
# SameValueZero never coerces across types — pins the divergence from
|
|
102
|
+
# the old stringy `eq` scan (where `[2].includes("2")` was true).
|
|
103
|
+
ok !$bf->includes([2], '2'), '[2].includes("2") → 0 (no numeric→string coercion)';
|
|
104
|
+
ok $bf->includes([2], 2), '[2].includes(2) → 1';
|
|
105
|
+
ok $bf->includes(['2'], '2'), '["2"].includes("2") → 1 (string vs string still matches)';
|
|
106
|
+
|
|
96
107
|
# String receiver: substring search.
|
|
97
108
|
ok $bf->includes('hello world', 'world'), 'substring present → 1';
|
|
98
109
|
ok !$bf->includes('hello world', 'earth'), 'substring absent → 0';
|