Skip to content

Commit 287f6ce

Browse files
committed
Stabilize remap collisions and empty regex matches
1 parent 10f34ea commit 287f6ce

3 files changed

Lines changed: 32 additions & 15 deletions

File tree

vibes/builtins.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -410,11 +410,11 @@ func builtinRegexMatch(exec *Execution, receiver Value, args []Value, kwargs map
410410
if err != nil {
411411
return NewNil(), fmt.Errorf("Regex.match invalid regex: %v", err)
412412
}
413-
match := re.FindString(text)
414-
if match == "" {
413+
indices := re.FindStringIndex(text)
414+
if indices == nil {
415415
return NewNil(), nil
416416
}
417-
return NewString(match), nil
417+
return NewString(text[indices[0]:indices[1]]), nil
418418
}
419419

420420
func builtinRegexReplace(exec *Execution, receiver Value, args []Value, kwargs map[string]Value, block Value) (Value, error) {

vibes/execution.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1986,7 +1986,8 @@ func hashMember(obj Value, property string) (Value, error) {
19861986
entries := receiver.Hash()
19871987
mapping := args[0].Hash()
19881988
out := make(map[string]Value, len(entries))
1989-
for key, value := range entries {
1989+
for _, key := range sortedHashKeys(entries) {
1990+
value := entries[key]
19901991
if mapped, ok := mapping[key]; ok {
19911992
nextKey, err := valueToHashKey(mapped)
19921993
if err != nil {

vibes/runtime_test.go

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1897,14 +1897,15 @@ func TestJSONBuiltins(t *testing.T) {
18971897

18981898
func TestRegexBuiltins(t *testing.T) {
18991899
script := compileScript(t, `
1900-
def helpers()
1901-
{
1902-
match_hit: Regex.match("ID-[0-9]+", "ID-12 ID-34"),
1903-
match_miss: Regex.match("Z+", "ID-12"),
1904-
replace_one: Regex.replace("ID-12 ID-34", "ID-[0-9]+", "X"),
1905-
replace_all: Regex.replace_all("ID-12 ID-34", "ID-[0-9]+", "X"),
1906-
replace_capture: Regex.replace("ID-12 ID-34", "ID-([0-9]+)", "X-$1")
1907-
}
1900+
def helpers()
1901+
{
1902+
match_hit: Regex.match("ID-[0-9]+", "ID-12 ID-34"),
1903+
match_miss: Regex.match("Z+", "ID-12"),
1904+
match_empty: Regex.match("^", "ID-12"),
1905+
replace_one: Regex.replace("ID-12 ID-34", "ID-[0-9]+", "X"),
1906+
replace_all: Regex.replace_all("ID-12 ID-34", "ID-[0-9]+", "X"),
1907+
replace_capture: Regex.replace("ID-12 ID-34", "ID-([0-9]+)", "X-$1")
1908+
}
19081909
end
19091910
19101911
def invalid_regex()
@@ -1923,6 +1924,9 @@ func TestRegexBuiltins(t *testing.T) {
19231924
if out["match_miss"].Kind() != KindNil {
19241925
t.Fatalf("expected match_miss nil, got %v", out["match_miss"])
19251926
}
1927+
if !out["match_empty"].Equal(NewString("")) {
1928+
t.Fatalf("match_empty mismatch: %#v", out["match_empty"])
1929+
}
19261930
if !out["replace_one"].Equal(NewString("X ID-34")) {
19271931
t.Fatalf("replace_one mismatch: %v", out["replace_one"])
19281932
}
@@ -2719,9 +2723,13 @@ func TestArrayAndHashHelpers(t *testing.T) {
27192723
{ a: 1, b: nil, c: 3 }.compact()
27202724
end
27212725
2722-
def hash_remap()
2723-
{ first_name: "Alex", total_raised: 10 }.remap_keys({ first_name: :name, total_raised: :raised })
2724-
end
2726+
def hash_remap()
2727+
{ first_name: "Alex", total_raised: 10 }.remap_keys({ first_name: :name, total_raised: :raised })
2728+
end
2729+
2730+
def hash_remap_collision()
2731+
{ a: 1, b: 2 }.remap_keys({ a: :x, b: :x })
2732+
end
27252733
27262734
def hash_deep_transform()
27272735
payload = {
@@ -2802,6 +2810,14 @@ func TestArrayAndHashHelpers(t *testing.T) {
28022810
"raised": NewInt(10),
28032811
})
28042812

2813+
colliding := callFunc(t, script, "hash_remap_collision", nil)
2814+
if colliding.Kind() != KindHash {
2815+
t.Fatalf("expected colliding remap hash, got %v", colliding.Kind())
2816+
}
2817+
if got := colliding.Hash()["x"]; got.Kind() != KindInt || got.Int() != 2 {
2818+
t.Fatalf("expected deterministic collision winner x=2, got %#v", got)
2819+
}
2820+
28052821
deepTransformed := callFunc(t, script, "hash_deep_transform", nil)
28062822
if deepTransformed.Kind() != KindHash {
28072823
t.Fatalf("expected deep transformed hash, got %v", deepTransformed.Kind())

0 commit comments

Comments
 (0)