Bring Bun.YAML to 90% passing yaml-test-suite (#23265)

### What does this PR do?
Fixes bugs in the parser bringing it to 90% passing the official
[yaml-test-suite](https://github.com/yaml/yaml-test-suite) (362/400
passing tests)

Still missing from our parser: |- and |+ (about 5%), and cyclic
references.

Translates the yaml-test-suite to our tests.

fixes #22659
fixes #22392
fixes #22286
### How did you verify your code works?
Added tests for yaml-test-suite and each of the linked issues

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
Dylan Conway
2025-10-05 17:23:59 -07:00
committed by GitHub
parent f0295ce0a5
commit fcbd57ac48
7 changed files with 8438 additions and 245 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -313,7 +313,7 @@ test("jsonc", async () => {
},
"yaml": {
"default": {
"// my json ": null,
"// my json": null,
"key": "👩👧👧value",
},
"key": "👩👧👧value",

View File

@@ -0,0 +1,171 @@
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
exports[`Bun.YAML parse issue 22286 2`] = `
{
"A Hat in Time": {
"ActPlando": {
"Dead Bird Studio Basement": "The Big Parade",
},
"ActRandomizer": "insanity",
"BabyTrapWeight": 0,
"BadgeSellerMaxItems": 8,
"BadgeSellerMinItems": 5,
"BaseballBat": true,
"CTRLogic": {
"nothing": 0,
"scooter": 1,
"sprint": 0,
"time_stop_only": 0,
},
"ChapterCostIncrement": 5,
"ChapterCostMinDifference": 5,
"CompassBadgeMode": "closest",
"DWAutoCompleteBonuses": true,
"DWEnableBonus": false,
"DWExcludeAnnoyingBonuses": true,
"DWExcludeAnnoyingContracts": true,
"DWExcludeCandles": true,
"DWShuffle": false,
"DWShuffleCountMax": 25,
"DWShuffleCountMin": 18,
"DWTimePieceRequirement": 15,
"DeathWishOnly": false,
"EnableDLC1": false,
"EnableDLC2": true,
"EnableDeathWish": false,
"EndGoal": {
"finale": 1,
"rush_hour": 0,
"seal_the_deal": 0,
},
"ExcludeTour": false,
"FinalChapterMaxCost": 35,
"FinalChapterMinCost": 30,
"FinaleShuffle": false,
"HatItems": true,
"HighestChapterCost": 25,
"LaserTrapWeight": 0,
"LogicDifficulty": "moderate",
"LowestChapterCost": 5,
"MaxExtraTimePieces": "random-range-high-5-8",
"MaxPonCost": 80,
"MetroMaxPonCost": 50,
"MetroMinPonCost": 10,
"MinExtraYarn": "random-range-middle-5-15",
"MinPonCost": 20,
"NoPaintingSkips": true,
"NoTicketSkips": "rush_hour",
"NyakuzaThugMaxShopItems": 4,
"NyakuzaThugMinShopItems": 1,
"ParadeTrapWeight": 0,
"RandomizeHatOrder": "time_stop_last",
"ShipShapeCustomTaskGoal": 0,
"ShuffleActContracts": true,
"ShuffleAlpineZiplines": true,
"ShuffleStorybookPages": true,
"ShuffleSubconPaintings": true,
"StartWithCompassBadge": true,
"StartingChapter": {
"1": 1,
"2": 1,
"3": 1,
},
"Tasksanity": false,
"TasksanityCheckCount": 18,
"TasksanityTaskStep": 1,
"TimePieceBalancePercent": "random-range-low-20-35",
"TrapChance": 0,
"UmbrellaLogic": true,
"YarnAvailable": "random-range-middle-40-50",
"YarnBalancePercent": 25,
"YarnCostMax": 8,
"YarnCostMin": 5,
"accessibility": {
"full": 1,
"minimal": 0,
},
"death_link": false,
"exclude_locations": [
"Queen Vanessa's Manor - Bedroom Chest",
"Queen Vanessa's Manor - Hall Chest",
"Act Completion (The Big Parade)",
],
"non_local_items": [
"Hookshot Badge",
"Umbrella",
"Dweller Mask",
],
"priority_locations": [
"Act Completion (Award Ceremony)",
"Badge Seller - Item 1",
"Badge Seller - Item 2",
"Mafia Boss Shop Item",
"Bluefin Tunnel Thug - Item 1",
"Green Clean Station Thug A - Item 1",
"Green Clean Station Thug B - Item 1",
"Main Station Thug A - Item 1",
"Main Station Thug B - Item 1",
"Main Station Thug C - Item 1",
"Pink Paw Station Thug - Item 1",
"Yellow Overpass Thug A - Item 1",
"Yellow Overpass Thug B - Item 1",
"Yellow Overpass Thug C - Item 1",
],
"progression_balancing": "random-range-middle-40-50",
"start_inventory_from_pool": {
"Sprint Hat": 1,
},
},
"game": "A Hat in Time",
"name": "niyrme-AHiT{NUMBER}",
"requires": {
"version": "0.6.2",
},
"x-options-async": {
"A Hat in Time": {
"+non_local_items": [
"Brewing Hat",
"Ice Hat",
],
"ChapterCostIncrement": 7,
"ChapterCostMinDifference": 7,
"EndGoal": {
"finale": 9,
"rush_hour": 1,
"seal_the_deal": 0,
},
"FinalChapterMaxCost": 50,
"FinalChapterMinCost": 40,
"HighestChapterCost": 40,
"LowestChapterCost": 10,
"NoPaintingSkips": false,
"death_link": false,
"priority_locations": [],
"progression_balancing": "random-range-low-10-30",
},
},
"x-options-sync": {
"A Hat in Time": {
"+start_inventory_from_pool": {
"Badge Pin": 1,
},
"+triggers": [
{
"option_category": "A Hat in Time",
"option_name": "EndGoal",
"option_result": "finale",
"options": {
"A Hat in Time": {
"EnableDLC2": false,
"FinalChapterMaxCost": 35,
"FinalChapterMinCost": 25,
"MaxPonCost": 100,
"MinPonCost": 30,
},
},
},
],
},
},
}
`;

View File

@@ -0,0 +1,167 @@
game: &AHiT "A Hat in Time"
name: "niyrme-AHiT{NUMBER}"
requires:
version: 0.6.2
*AHiT :
# game
progression_balancing: "random-range-middle-40-50"
accessibility:
"full": 1
"minimal": 0
death_link: false
# general
&EndGoal EndGoal:
&EndGoal_Finale finale: 1
&EndGoal_Rush rush_hour: 0
&EndGoal_Seal seal_the_deal: 0
ShuffleStorybookPages: true
ShuffleAlpineZiplines: true
ShuffleSubconPaintings: true
ShuffleActContracts: true
MinPonCost: 20
MaxPonCost: 80
BadgeSellerMinItems: 5
BadgeSellerMaxItems: 8
# https://docs.google.com/document/d/1x9VLSQ5davfx1KGamR9T0mD5h69_lDXJ6H7Gq7knJRI
LogicDifficulty: "moderate"
NoPaintingSkips: true
CTRLogic:
"time_stop_only": 0
"scooter": 1
"sprint": 0
"nothing": 0
# acts
ActRandomizer: "insanity"
StartingChapter:
1: 1
2: 1
3: 1
LowestChapterCost: 5
HighestChapterCost: 25
ChapterCostIncrement: 5
ChapterCostMinDifference: 5
&GoalMinCost FinalChapterMinCost: 30
&GoalMaxCost FinalChapterMaxCost: 35
FinaleShuffle: false
# items
StartWithCompassBadge: true
CompassBadgeMode: "closest"
RandomizeHatOrder: "time_stop_last"
YarnAvailable: "random-range-middle-40-50"
YarnCostMin: 5
YarnCostMax: 8
MinExtraYarn: "random-range-middle-5-15"
HatItems: true
UmbrellaLogic: true
MaxExtraTimePieces: "random-range-high-5-8"
YarnBalancePercent: 25
TimePieceBalancePercent: "random-range-low-20-35"
# DLC: Seal the Deal
EnableDLC1: false
Tasksanity: false
TasksanityTaskStep: 1
TasksanityCheckCount: 18
ShipShapeCustomTaskGoal: 0
ExcludeTour: false
# DLC: Nyakuza Metro
&DLCNyakuza EnableDLC2: true
MetroMinPonCost: 10
MetroMaxPonCost: 50
NyakuzaThugMinShopItems: 1
NyakuzaThugMaxShopItems: 4
BaseballBat: true
NoTicketSkips: "rush_hour"
# Death Wish
EnableDeathWish: false
DWTimePieceRequirement: 15
DWShuffle: false
DWShuffleCountMin: 18
DWShuffleCountMax: 25
DWEnableBonus: false
DWAutoCompleteBonuses: true
DWExcludeAnnoyingContracts: true
DWExcludeAnnoyingBonuses: true
DWExcludeCandles: true
DeathWishOnly: false
# traps
TrapChance: 0
BabyTrapWeight: 0
LaserTrapWeight: 0
ParadeTrapWeight: 0
# plando, item & location options
non_local_items:
- "Hookshot Badge"
- "Umbrella"
- "Dweller Mask"
start_inventory_from_pool:
"Sprint Hat": 1
exclude_locations:
- "Queen Vanessa's Manor - Bedroom Chest"
- "Queen Vanessa's Manor - Hall Chest"
- "Act Completion (The Big Parade)"
priority_locations:
- "Act Completion (Award Ceremony)"
- "Badge Seller - Item 1"
- "Badge Seller - Item 2"
- "Mafia Boss Shop Item"
# Nyakuza DLC
- "Bluefin Tunnel Thug - Item 1"
- "Green Clean Station Thug A - Item 1"
- "Green Clean Station Thug B - Item 1"
- "Main Station Thug A - Item 1"
- "Main Station Thug B - Item 1"
- "Main Station Thug C - Item 1"
- "Pink Paw Station Thug - Item 1"
- "Yellow Overpass Thug A - Item 1"
- "Yellow Overpass Thug B - Item 1"
- "Yellow Overpass Thug C - Item 1"
ActPlando:
"Dead Bird Studio Basement": "The Big Parade"
x-options-sync:
*AHiT :
+start_inventory_from_pool:
"Badge Pin": 1
+triggers:
- option_category: *AHiT
option_name: *EndGoal
option_result: *EndGoal_Finale
options:
*AHiT :
MinPonCost: 30
MaxPonCost: 100
*GoalMinCost : 25
*GoalMaxCost : 35
*DLCNyakuza : false
x-options-async:
*AHiT :
progression_balancing: "random-range-low-10-30"
death_link: false
LowestChapterCost: 10
HighestChapterCost: 40
ChapterCostIncrement: 7
ChapterCostMinDifference: 7
*EndGoal :
*EndGoal_Finale : 9
*EndGoal_Rush : 1
*EndGoal_Seal : 0
NoPaintingSkips: false
*GoalMinCost : 40
*GoalMaxCost : 50
+non_local_items:
- "Brewing Hat"
- "Ice Hat"
priority_locations: []

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,6 @@
import { YAML } from "bun";
import { YAML, file } from "bun";
import { describe, expect, test } from "bun:test";
import { join } from "path";
describe("Bun.YAML", () => {
describe("parse", () => {
@@ -702,6 +703,64 @@ production:
},
});
});
test("issue 22659", () => {
const input1 = `- test2: next
test1: +`;
expect(YAML.parse(input1)).toMatchInlineSnapshot(`
[
{
"test1": "+",
"test2": "next",
},
]
`);
const input2 = `- test1: +
test2: next`;
expect(YAML.parse(input2)).toMatchInlineSnapshot(`
[
{
"test1": "+",
"test2": "next",
},
]
`);
});
test("issue 22392", () => {
const input = `
foo: "some
...
string"
`;
expect(YAML.parse(input)).toMatchInlineSnapshot(`
{
"foo": "some ... string",
}
`);
});
test("issue 22286", async () => {
const input1 = `
my_anchor: &MyAnchor "MyAnchor"
my_config:
*MyAnchor :
some_key: "some_value"
`;
expect(YAML.parse(input1)).toMatchInlineSnapshot(`
{
"my_anchor": "MyAnchor",
"my_config": {
"MyAnchor": {
"some_key": "some_value",
},
},
}
`);
const input2 = await file(join(import.meta.dir, "fixtures", "AHatInTime.yaml")).text();
expect(YAML.parse(input2)).toMatchSnapshot();
});
});
describe("stringify", () => {