mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 10:28:47 +00:00
Fix YAML parsing of '+' and '-' as scalar values (#22659)
Previously, YAML parser incorrectly handled '+' and '-' characters when they appeared as standalone scalar values: - In block context after mapping value (:), '-' was treated as sequence entry instead of scalar - In flow collections, '-' was incorrectly parsed as sequence entry marker - '+' alone was sometimes misinterpreted as number prefix This fix ensures '+' and '-' are properly parsed as plain scalar strings when they appear alone as values. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1918,6 +1918,26 @@ pub fn Parser(comptime enc: Encoding) type {
|
||||
|
||||
const start = parser.pos;
|
||||
|
||||
// Check if we're at the end of the scalar for + or - alone
|
||||
if (first_char == .positive or first_char == .negative) {
|
||||
switch (parser.next()) {
|
||||
' ', '\t', 0, '\n', '\r', ':' => {
|
||||
// Just a '+' or '-' alone, not a number
|
||||
return;
|
||||
},
|
||||
',' , ']', '}' => {
|
||||
switch (parser.context.get()) {
|
||||
.flow_in, .flow_key => {
|
||||
// Just a '+' or '-' alone in flow context
|
||||
return;
|
||||
},
|
||||
.block_in, .block_out => {},
|
||||
}
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
|
||||
var decimal = parser.next() == '.';
|
||||
var x = false;
|
||||
var o = false;
|
||||
@@ -3434,6 +3454,7 @@ pub fn Parser(comptime enc: Encoding) type {
|
||||
};
|
||||
|
||||
const previous_token_line = self.token.line;
|
||||
const previous_token_data = self.token.data;
|
||||
|
||||
self.token = next: switch (self.next()) {
|
||||
0 => {
|
||||
@@ -3467,6 +3488,12 @@ pub fn Parser(comptime enc: Encoding) type {
|
||||
' ',
|
||||
'\t',
|
||||
=> {
|
||||
// Check if previous token was a mapping value (':')
|
||||
// If so, treat '-' as a plain scalar, not a sequence entry
|
||||
if (previous_token_data == .mapping_value) {
|
||||
break :next try self.scanPlainScalar(opts);
|
||||
}
|
||||
|
||||
self.inc(1);
|
||||
|
||||
switch (self.context.get()) {
|
||||
@@ -3499,15 +3526,9 @@ pub fn Parser(comptime enc: Encoding) type {
|
||||
.flow_in,
|
||||
.flow_key,
|
||||
=> {
|
||||
self.inc(1);
|
||||
|
||||
self.token = .sequenceEntry(.{
|
||||
.start = start,
|
||||
.indent = self.line_indent,
|
||||
.line = self.line,
|
||||
});
|
||||
|
||||
return error.UnexpectedToken;
|
||||
// In flow context, '-' should be treated as a plain scalar
|
||||
// not as a sequence entry marker
|
||||
break :next try self.scanPlainScalar(opts);
|
||||
},
|
||||
.block_in,
|
||||
.block_out,
|
||||
|
||||
59
test/regression/issue/22659.test.ts
Normal file
59
test/regression/issue/22659.test.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import { test, expect } from "bun:test";
|
||||
import { YAML } from "bun";
|
||||
|
||||
// https://github.com/oven-sh/bun/issues/22659
|
||||
test("YAML parsing handles '+' character as scalar value", () => {
|
||||
// Test case 1: test2 first, test1 second
|
||||
const yaml1 = `- test2: next
|
||||
test1: +`;
|
||||
|
||||
const result1 = YAML.parse(yaml1);
|
||||
expect(result1).toEqual([{ test2: "next", test1: "+" }]);
|
||||
|
||||
// Test case 2: test1 first, test2 second (this was throwing an error)
|
||||
const yaml2 = `- test1: +
|
||||
test2: next`;
|
||||
|
||||
const result2 = YAML.parse(yaml2);
|
||||
expect(result2).toEqual([{ test1: "+", test2: "next" }]);
|
||||
|
||||
// Test case 3: '-' character as scalar value
|
||||
const yaml3 = `- test1: -
|
||||
test2: value`;
|
||||
|
||||
const result3 = YAML.parse(yaml3);
|
||||
expect(result3).toEqual([{ test1: "-", test2: "value" }]);
|
||||
|
||||
// Test case 4: Simple object with + and - values
|
||||
const yaml4 = `plus: +
|
||||
minus: -`;
|
||||
|
||||
const result4 = YAML.parse(yaml4);
|
||||
expect(result4).toEqual({ plus: "+", minus: "-" });
|
||||
|
||||
// Test case 5: '+' and '-' in flow collections
|
||||
const yaml5 = `[+, -, test]`;
|
||||
const result5 = YAML.parse(yaml5);
|
||||
expect(result5).toEqual(["+", "-", "test"]);
|
||||
|
||||
const yaml6 = `{a: +, b: -, c: test}`;
|
||||
const result6 = YAML.parse(yaml6);
|
||||
expect(result6).toEqual({ a: "+", b: "-", c: "test" });
|
||||
});
|
||||
|
||||
// TODO: This is a separate issue with nested lists under object properties
|
||||
// test.skip("YAML parsing handles nested lists correctly", () => {
|
||||
// const yaml = `items:
|
||||
// - name: plus
|
||||
// value: +
|
||||
// - name: minus
|
||||
// value: -`;
|
||||
//
|
||||
// const result = YAML.parse(yaml);
|
||||
// expect(result).toEqual({
|
||||
// items: [
|
||||
// { name: "plus", value: "+" },
|
||||
// { name: "minus", value: "-" }
|
||||
// ]
|
||||
// });
|
||||
// });
|
||||
Reference in New Issue
Block a user