Skip to content

Commit 4312437

Browse files
committed
Enforce restrictions on selector expression per spec, fixes #416
This uplifts the tests from the spec PR, projectfluent/fluent#280 and implements the selector validation to follow what `abstract.js` does in the spec. In @fluent/bundle, the invalid selectors are just accepted. Might be worth revisiting.
1 parent 7cec8b9 commit 4312437

File tree

5 files changed

+114
-10
lines changed

5 files changed

+114
-10
lines changed

fluent-bundle/test/fixtures_reference/select_expressions.json

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,66 @@
122122
],
123123
"attributes": {}
124124
},
125+
{
126+
"id": "invalid-selector-select-expression",
127+
"value": [
128+
{
129+
"type": "select",
130+
"selector": {
131+
"type": "num",
132+
"value": 3,
133+
"precision": 0
134+
},
135+
"variants": [
136+
{
137+
"key": {
138+
"type": "str",
139+
"value": "key"
140+
},
141+
"value": "default"
142+
}
143+
],
144+
"star": 0
145+
}
146+
],
147+
"attributes": {}
148+
},
149+
{
150+
"id": "invalid-selector-nested-expression",
151+
"value": [
152+
{
153+
"type": "select",
154+
"selector": {
155+
"type": "select",
156+
"selector": {
157+
"type": "var",
158+
"name": "sel"
159+
},
160+
"variants": [
161+
{
162+
"key": {
163+
"type": "str",
164+
"value": "key"
165+
},
166+
"value": "value"
167+
}
168+
],
169+
"star": 0
170+
},
171+
"variants": [
172+
{
173+
"key": {
174+
"type": "str",
175+
"value": "key"
176+
},
177+
"value": "default"
178+
}
179+
],
180+
"star": 0
181+
}
182+
],
183+
"attributes": {}
184+
},
125185
{
126186
"id": "empty-variant",
127187
"value": [

fluent-syntax/src/errors.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ function getErrorMessage(code, args) {
7676
return "Unbalanced closing brace in TextElement.";
7777
case "E0028":
7878
return "Expected an inline expression";
79+
case "E0029":
80+
return "Expected simple expression as selector";
7981
default:
8082
return code;
8183
}

fluent-syntax/src/parser.js

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -607,16 +607,26 @@ class FluentParser {
607607
return selector;
608608
}
609609

610-
if (selector.type === "MessageReference") {
611-
if (selector.attribute === null) {
612-
throw new ParseError("E0016");
613-
} else {
614-
throw new ParseError("E0018");
615-
}
616-
}
617-
618-
if (selector.type === "TermReference" && selector.attribute === null) {
619-
throw new ParseError("E0017");
610+
// Validate selector expression according to
611+
// abstract.js in the Fluent specification
612+
switch (selector.type) {
613+
case "MessageReference":
614+
if (selector.attribute === null) {
615+
throw new ParseError("E0016");
616+
} else {
617+
throw new ParseError("E0018");
618+
}
619+
case "TermReference":
620+
if (selector.attribute === null) {
621+
throw new ParseError("E0017");
622+
}
623+
case "StringLiteral":
624+
case "NumberLiteral":
625+
case "VariableReference":
626+
case "FunctionReference":
627+
break;
628+
default:
629+
throw new ParseError("E0029");
620630
}
621631

622632
ps.next();

fluent-syntax/test/fixtures_reference/select_expressions.ftl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,20 @@ invalid-selector-term-variant =
2121
*[key] value
2222
}
2323
24+
# ERROR Nested expressions are not valid selectors
25+
invalid-selector-select-expression =
26+
{ { 3 } ->
27+
*[key] default
28+
}
29+
30+
# ERROR Select expressions are not valid selectors
31+
invalid-selector-nested-expression =
32+
{ { $sel ->
33+
*[key] value
34+
} ->
35+
*[key] default
36+
}
37+
2438
empty-variant =
2539
{ $sel ->
2640
*[key] {""}

fluent-syntax/test/fixtures_reference/select_expressions.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,24 @@
145145
"annotations": [],
146146
"content": "invalid-selector-term-variant =\n { -term(case: \"nominative\") ->\n *[key] value\n }\n\n"
147147
},
148+
{
149+
"type": "Comment",
150+
"content": "ERROR Nested expressions are not valid selectors"
151+
},
152+
{
153+
"type": "Junk",
154+
"annotations": [],
155+
"content": "invalid-selector-select-expression =\n { { 3 } ->\n *[key] default\n }\n\n"
156+
},
157+
{
158+
"type": "Comment",
159+
"content": "ERROR Select expressions are not valid selectors"
160+
},
161+
{
162+
"type": "Junk",
163+
"annotations": [],
164+
"content": "invalid-selector-nested-expression =\n { { $sel ->\n *[key] value\n } ->\n *[key] default\n }\n\n"
165+
},
148166
{
149167
"type": "Message",
150168
"id": {

0 commit comments

Comments
 (0)