Skip to content

Commit 9e80c8b

Browse files
committed
Represent nodes partially if their tags allow it
1 parent 5717297 commit 9e80c8b

File tree

2 files changed

+31
-10
lines changed

2 files changed

+31
-10
lines changed

pkgs/yaml/lib/src/loader.dart

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import 'equality.dart';
1212
import 'error_listener.dart';
1313
import 'event.dart';
1414
import 'parser.dart';
15+
import 'utils.dart';
1516
import 'yaml_document.dart';
1617
import 'yaml_exception.dart';
1718
import 'yaml_node.dart';
@@ -125,9 +126,7 @@ class Loader {
125126

126127
/// Composes a sequence node.
127128
YamlNode _loadSequence(SequenceStartEvent firstEvent) {
128-
if (firstEvent.tag != '!' &&
129-
firstEvent.tag != null &&
130-
firstEvent.tag != 'tag:yaml.org,2002:seq') {
129+
if (!isResolvedYamlTag(firstEvent.tag, 'seq')) {
131130
throw YamlException('Invalid tag for sequence.', firstEvent.span);
132131
}
133132

@@ -147,9 +146,7 @@ class Loader {
147146

148147
/// Composes a mapping node.
149148
YamlNode _loadMapping(MappingStartEvent firstEvent) {
150-
if (firstEvent.tag != '!' &&
151-
firstEvent.tag != null &&
152-
firstEvent.tag != 'tag:yaml.org,2002:map') {
149+
if (!isResolvedYamlTag(firstEvent.tag, 'map')) {
153150
throw YamlException('Invalid tag for mapping.', firstEvent.span);
154151
}
155152

@@ -192,10 +189,22 @@ class Loader {
192189
var result = _parseNumber(scalar, allowInt: false);
193190
if (result != null) return result;
194191
throw YamlException('Invalid float scalar.', scalar.span);
195-
case 'tag:yaml.org,2002:str':
196-
return YamlScalar.internal(scalar.value, scalar);
197-
default:
198-
throw YamlException('Undefined tag: ${scalar.tag}.', scalar.span);
192+
193+
/// Represent partially as a string when custom tags are present. Any
194+
/// other yaml tag must be `!!str`.
195+
///
196+
/// See: https://yaml.org/spec/1.2/spec.html#id2768011
197+
/// (PS: This is the YAML version this parser is based on)
198+
case String? tag:
199+
{
200+
// Intentionally (quirky and) verbose. We want this condition to leak
201+
// for non-schema tags.
202+
if (!isResolvedYamlTag(tag, 'str')) {
203+
throw YamlException('Undefined tag: ${scalar.tag}.', scalar.span);
204+
}
205+
206+
return YamlScalar.internal(scalar.value, scalar);
207+
}
199208
}
200209
}
201210

pkgs/yaml/lib/src/utils.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,15 @@ bool isHighSurrogate(int codeUnit) => codeUnit >>> 10 == 0x36;
3838

3939
/// Whether [codeUnit] is a UTF-16 low surrogate.
4040
bool isLowSurrogate(int codeUnit) => codeUnit >>> 10 == 0x37;
41+
42+
/// Whether a tag is a valid tag based on its [canonicalSuffix] as defined in
43+
/// the yaml spec. Always returns `true` if the caller has a custom tag and can
44+
/// be partially composed/represented (synthetic node).
45+
///
46+
/// - `seq` - for sequence
47+
/// - `map` - for map
48+
/// - `str` - for scalar
49+
bool isResolvedYamlTag(String? tag, String canonicalSuffix) =>
50+
tag == null ||
51+
!tag.startsWith('tag:yaml.org,2002:') || // Leaky prefix condition.
52+
!tag.endsWith(canonicalSuffix);

0 commit comments

Comments
 (0)