Skip to content

Commit 48a11f8

Browse files
committed
Report errors from Functions
1 parent 97047be commit 48a11f8

File tree

3 files changed

+145
-73
lines changed

3 files changed

+145
-73
lines changed

fluent/src/builtins.js

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
* `FluentType`. Functions must return `FluentType` objects as well.
1212
*/
1313

14-
import { FluentNone, FluentNumber, FluentDateTime } from "./types.js";
14+
import { FluentNumber, FluentDateTime } from "./types.js";
1515

1616
function merge(argopts, opts) {
1717
return Object.assign({}, argopts, values(opts));
@@ -27,22 +27,18 @@ function values(opts) {
2727

2828
export
2929
function NUMBER([arg], opts) {
30-
if (arg instanceof FluentNone) {
31-
return arg;
32-
}
3330
if (arg instanceof FluentNumber) {
3431
return new FluentNumber(arg.valueOf(), merge(arg.opts, opts));
3532
}
36-
return new FluentNone("NUMBER()");
33+
34+
throw new TypeError("Invalid argument type to NUMBER");
3735
}
3836

3937
export
4038
function DATETIME([arg], opts) {
41-
if (arg instanceof FluentNone) {
42-
return arg;
43-
}
4439
if (arg instanceof FluentDateTime) {
4540
return new FluentDateTime(arg.valueOf(), merge(arg.opts, opts));
4641
}
47-
return new FluentNone("DATETIME()");
42+
43+
throw new TypeError("Invalid argument type to DATETIME");
4844
}

fluent/src/resolver.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ function resolveExpression(scope, expr) {
127127
function VariableReference(scope, {name}) {
128128
if (!scope.args || !scope.args.hasOwnProperty(name)) {
129129
if (scope.insideTermReference === false) {
130-
scope.reportError(new ReferenceError(`Unknown variable: ${name}`));
130+
scope.reportError(new ReferenceError(`Unknown variable: $${name}`));
131131
}
132132
return new FluentNone(`$${name}`);
133133
}
@@ -151,7 +151,7 @@ function VariableReference(scope, {name}) {
151151
}
152152
default:
153153
scope.reportError(
154-
new TypeError(`Unsupported variable type: ${name}, ${typeof arg}`)
154+
new TypeError(`Variable type not supported: $${name}, ${typeof arg}`)
155155
);
156156
return new FluentNone(`$${name}`);
157157
}
@@ -224,8 +224,8 @@ function FunctionReference(scope, {name, args}) {
224224

225225
try {
226226
return func(...getArguments(scope, args));
227-
} catch (e) {
228-
// XXX Report errors.
227+
} catch (err) {
228+
scope.reportError(err);
229229
return new FluentNone(`${name}()`);
230230
}
231231
}

fluent/test/functions_builtin_test.js

Lines changed: 136 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,32 @@ suite('Built-in functions', function() {
2525
test('missing argument', function() {
2626
let msg;
2727

28+
errors = [];
2829
msg = bundle.getMessage('num-decimal');
29-
assert.strictEqual(bundle.formatPattern(msg.value, {}, errors), '{$arg}');
30-
assert.strictEqual(errors.length, 1);
31-
assert.ok(errors.pop() instanceof ReferenceError);
32-
30+
assert.strictEqual(bundle.formatPattern(msg.value, {}, errors), '{NUMBER()}');
31+
assert.strictEqual(errors.length, 2);
32+
assert.ok(errors[0] instanceof ReferenceError);
33+
assert.strictEqual(errors[0].message, "Unknown variable: $arg");
34+
assert.ok(errors[1] instanceof TypeError);
35+
assert.strictEqual(errors[1].message, "Invalid argument type to NUMBER");
36+
37+
errors = [];
3338
msg = bundle.getMessage('num-percent');
34-
assert.strictEqual(bundle.formatPattern(msg.value, {}, errors), '{$arg}');
35-
assert.strictEqual(errors.length, 1);
36-
assert.ok(errors.pop() instanceof ReferenceError);
37-
39+
assert.strictEqual(bundle.formatPattern(msg.value, {}, errors), '{NUMBER()}');
40+
assert.strictEqual(errors.length, 2);
41+
assert.ok(errors[0] instanceof ReferenceError);
42+
assert.strictEqual(errors[0].message, "Unknown variable: $arg");
43+
assert.ok(errors[1] instanceof TypeError);
44+
assert.strictEqual(errors[1].message, "Invalid argument type to NUMBER");
45+
46+
errors = [];
3847
msg = bundle.getMessage('num-bad-opt');
39-
assert.strictEqual(bundle.formatPattern(msg.value, {}, errors), '{$arg}');
40-
assert.strictEqual(errors.length, 1);
41-
assert.ok(errors.pop() instanceof ReferenceError);
48+
assert.strictEqual(bundle.formatPattern(msg.value, {}, errors), '{NUMBER()}');
49+
assert.strictEqual(errors.length, 2);
50+
assert.ok(errors[0] instanceof ReferenceError);
51+
assert.strictEqual(errors[0].message, "Unknown variable: $arg");
52+
assert.ok(errors[1] instanceof TypeError);
53+
assert.strictEqual(errors[1].message, "Invalid argument type to NUMBER");
4254
});
4355

4456
test('number argument', function() {
@@ -58,63 +70,89 @@ suite('Built-in functions', function() {
5870
assert.strictEqual(errors.length, 0);
5971
});
6072

61-
// XXX Functions should report errors.
62-
// https://github.com/projectfluent/fluent.js/issues/106
6373
test('string argument', function() {
6474
const args = {arg: "Foo"};
6575
let msg;
6676

77+
errors = [];
6778
msg = bundle.getMessage('num-decimal');
6879
assert.strictEqual(bundle.formatPattern(msg.value, args, errors), '{NUMBER()}');
69-
assert.strictEqual(errors.length, 0);
80+
assert.strictEqual(errors.length, 1);
81+
assert.ok(errors[0] instanceof TypeError);
82+
assert.strictEqual(errors[0].message, "Invalid argument type to NUMBER");
7083

84+
errors = [];
7185
msg = bundle.getMessage('num-percent');
7286
assert.strictEqual(bundle.formatPattern(msg.value, args, errors), '{NUMBER()}');
73-
assert.strictEqual(errors.length, 0);
87+
assert.strictEqual(errors.length, 1);
88+
assert.ok(errors[0] instanceof TypeError);
89+
assert.strictEqual(errors[0].message, "Invalid argument type to NUMBER");
7490

91+
errors = [];
7592
msg = bundle.getMessage('num-bad-opt');
7693
assert.strictEqual(bundle.formatPattern(msg.value, args, errors), '{NUMBER()}');
77-
assert.strictEqual(errors.length, 0);
94+
assert.strictEqual(errors.length, 1);
95+
assert.ok(errors[0] instanceof TypeError);
96+
assert.strictEqual(errors[0].message, "Invalid argument type to NUMBER");
7897
});
7998

80-
// XXX Functions should report errors.
81-
// https://github.com/projectfluent/fluent.js/issues/106
8299
test('date argument', function() {
83100
const date = new Date('2016-09-29');
84101
const args = {arg: date};
85102
let msg;
86103

104+
errors = [];
87105
msg = bundle.getMessage('num-decimal');
88106
assert.strictEqual(bundle.formatPattern(msg.value, args, errors), '{NUMBER()}');
89-
assert.strictEqual(errors.length, 0);
107+
assert.strictEqual(errors.length, 1);
108+
assert.ok(errors[0] instanceof TypeError);
109+
assert.strictEqual(errors[0].message, "Invalid argument type to NUMBER");
90110

111+
errors = [];
91112
msg = bundle.getMessage('num-percent');
92113
assert.strictEqual(bundle.formatPattern(msg.value, args, errors), '{NUMBER()}');
93-
assert.strictEqual(errors.length, 0);
114+
assert.strictEqual(errors.length, 1);
115+
assert.ok(errors[0] instanceof TypeError);
116+
assert.strictEqual(errors[0].message, "Invalid argument type to NUMBER");
94117

118+
errors = [];
95119
msg = bundle.getMessage('num-bad-opt');
96120
assert.strictEqual(bundle.formatPattern(msg.value, args, errors), '{NUMBER()}');
97-
assert.strictEqual(errors.length, 0);
121+
assert.strictEqual(errors.length, 1);
122+
assert.ok(errors[0] instanceof TypeError);
123+
assert.strictEqual(errors[0].message, "Invalid argument type to NUMBER");
98124
});
99125

100126
test('invalid argument', function() {
101127
const args = {arg: []};
102128
let msg;
103129

130+
errors = [];
104131
msg = bundle.getMessage('num-decimal');
105-
assert.strictEqual(bundle.formatPattern(msg.value, args, errors), '{$arg}');
106-
assert.strictEqual(errors.length, 1);
107-
assert.ok(errors.pop() instanceof TypeError);
132+
assert.strictEqual(bundle.formatPattern(msg.value, args, errors), '{NUMBER()}');
133+
assert.strictEqual(errors.length, 2);
134+
assert.ok(errors[0] instanceof TypeError);
135+
assert.strictEqual(errors[0].message, "Variable type not supported: $arg, object");
136+
assert.ok(errors[1] instanceof TypeError);
137+
assert.strictEqual(errors[1].message, "Invalid argument type to NUMBER");
108138

139+
errors = [];
109140
msg = bundle.getMessage('num-percent');
110-
assert.strictEqual(bundle.formatPattern(msg.value, args, errors), '{$arg}');
111-
assert.strictEqual(errors.length, 1);
112-
assert.ok(errors.pop() instanceof TypeError);
141+
assert.strictEqual(bundle.formatPattern(msg.value, args, errors), '{NUMBER()}');
142+
assert.strictEqual(errors.length, 2);
143+
assert.ok(errors[0] instanceof TypeError);
144+
assert.strictEqual(errors[0].message, "Variable type not supported: $arg, object");
145+
assert.ok(errors[1] instanceof TypeError);
146+
assert.strictEqual(errors[1].message, "Invalid argument type to NUMBER");
113147

148+
errors = [];
114149
msg = bundle.getMessage('num-bad-opt');
115-
assert.strictEqual(bundle.formatPattern(msg.value, args, errors), '{$arg}');
116-
assert.strictEqual(errors.length, 1);
117-
assert.ok(errors.pop() instanceof TypeError);
150+
assert.strictEqual(bundle.formatPattern(msg.value, args, errors), '{NUMBER()}');
151+
assert.strictEqual(errors.length, 2);
152+
assert.ok(errors[0] instanceof TypeError);
153+
assert.strictEqual(errors[0].message, "Variable type not supported: $arg, object");
154+
assert.ok(errors[1] instanceof TypeError);
155+
assert.strictEqual(errors[1].message, "Invalid argument type to NUMBER");
118156
});
119157
});
120158

@@ -131,20 +169,32 @@ suite('Built-in functions', function() {
131169
test('missing argument', function() {
132170
let msg;
133171

172+
errors = [];
134173
msg = bundle.getMessage('dt-default');
135-
assert.strictEqual(bundle.formatPattern(msg.value, {}, errors), '{$arg}');
136-
assert.strictEqual(errors.length, 1);
137-
assert.ok(errors.pop() instanceof ReferenceError);
138-
174+
assert.strictEqual(bundle.formatPattern(msg.value, {}, errors), '{DATETIME()}');
175+
assert.strictEqual(errors.length, 2);
176+
assert.ok(errors[0] instanceof ReferenceError);
177+
assert.strictEqual(errors[0].message, "Unknown variable: $arg");
178+
assert.ok(errors[1] instanceof TypeError);
179+
assert.strictEqual(errors[1].message, "Invalid argument type to DATETIME");
180+
181+
errors = [];
139182
msg = bundle.getMessage('dt-month');
140-
assert.strictEqual(bundle.formatPattern(msg.value, {}, errors), '{$arg}');
141-
assert.strictEqual(errors.length, 1);
142-
assert.ok(errors.pop() instanceof ReferenceError);
143-
183+
assert.strictEqual(bundle.formatPattern(msg.value, {}, errors), '{DATETIME()}');
184+
assert.strictEqual(errors.length, 2);
185+
assert.ok(errors[0] instanceof ReferenceError);
186+
assert.strictEqual(errors[0].message, "Unknown variable: $arg");
187+
assert.ok(errors[1] instanceof TypeError);
188+
assert.strictEqual(errors[1].message, "Invalid argument type to DATETIME");
189+
190+
errors = [];
144191
msg = bundle.getMessage('dt-bad-opt');
145-
assert.strictEqual(bundle.formatPattern(msg.value, {}, errors), '{$arg}');
146-
assert.strictEqual(errors.length, 1);
147-
assert.ok(errors.pop() instanceof ReferenceError);
192+
assert.strictEqual(bundle.formatPattern(msg.value, {}, errors), '{DATETIME()}');
193+
assert.strictEqual(errors.length, 2);
194+
assert.ok(errors[0] instanceof ReferenceError);
195+
assert.strictEqual(errors[0].message, "Unknown variable: $arg");
196+
assert.ok(errors[1] instanceof TypeError);
197+
assert.strictEqual(errors[1].message, "Invalid argument type to DATETIME");
148198
});
149199

150200
test('Date argument', function () {
@@ -175,62 +225,88 @@ suite('Built-in functions', function() {
175225
assert.strictEqual(errors.length, 0);
176226
});
177227

178-
// XXX Functions should report errors.
179-
// https://github.com/projectfluent/fluent.js/issues/106
180228
test('number argument', function() {
181229
let args = {arg: 1};
182230
let msg;
183231

232+
errors = [];
184233
msg = bundle.getMessage('dt-default');
185234
assert.strictEqual(bundle.formatPattern(msg.value, args, errors), '{DATETIME()}');
186-
assert.strictEqual(errors.length, 0);
235+
assert.strictEqual(errors.length, 1);
236+
assert.ok(errors[0] instanceof TypeError);
237+
assert.strictEqual(errors[0].message, "Invalid argument type to DATETIME");
187238

239+
errors = [];
188240
msg = bundle.getMessage('dt-month');
189241
assert.strictEqual(bundle.formatPattern(msg.value, args, errors), '{DATETIME()}');
190-
assert.strictEqual(errors.length, 0);
242+
assert.strictEqual(errors.length, 1);
243+
assert.ok(errors[0] instanceof TypeError);
244+
assert.strictEqual(errors[0].message, "Invalid argument type to DATETIME");
191245

246+
errors = [];
192247
msg = bundle.getMessage('dt-bad-opt');
193248
assert.strictEqual(bundle.formatPattern(msg.value, args, errors), '{DATETIME()}');
194-
assert.strictEqual(errors.length, 0);
249+
assert.strictEqual(errors.length, 1);
250+
assert.ok(errors[0] instanceof TypeError);
251+
assert.strictEqual(errors[0].message, "Invalid argument type to DATETIME");
195252
});
196253

197-
// XXX Functions should report errors.
198-
// https://github.com/projectfluent/fluent.js/issues/106
199254
test('string argument', function() {
200255
let args = {arg: 'Foo'};
201256
let msg;
202257

258+
errors = [];
203259
msg = bundle.getMessage('dt-default');
204260
assert.strictEqual(bundle.formatPattern(msg.value, args, errors), '{DATETIME()}');
205-
assert.strictEqual(errors.length, 0);
261+
assert.strictEqual(errors.length, 1);
262+
assert.ok(errors[0] instanceof TypeError);
263+
assert.strictEqual(errors[0].message, "Invalid argument type to DATETIME");
206264

265+
errors = [];
207266
msg = bundle.getMessage('dt-month');
208267
assert.strictEqual(bundle.formatPattern(msg.value, args, errors), '{DATETIME()}');
209-
assert.strictEqual(errors.length, 0);
268+
assert.strictEqual(errors.length, 1);
269+
assert.ok(errors[0] instanceof TypeError);
270+
assert.strictEqual(errors[0].message, "Invalid argument type to DATETIME");
210271

272+
errors = [];
211273
msg = bundle.getMessage('dt-bad-opt');
212274
assert.strictEqual(bundle.formatPattern(msg.value, args, errors), '{DATETIME()}');
213-
assert.strictEqual(errors.length, 0);
275+
assert.strictEqual(errors.length, 1);
276+
assert.ok(errors[0] instanceof TypeError);
277+
assert.strictEqual(errors[0].message, "Invalid argument type to DATETIME");
214278
});
215279

216280
test('invalid argument', function() {
217281
let args = {arg: []};
218282
let msg;
219283

284+
errors = [];
220285
msg = bundle.getMessage('dt-default');
221-
assert.strictEqual(bundle.formatPattern(msg.value, args, errors), '{$arg}');
222-
assert.strictEqual(errors.length, 1);
223-
assert.ok(errors.pop() instanceof TypeError);
286+
assert.strictEqual(bundle.formatPattern(msg.value, args, errors), '{DATETIME()}');
287+
assert.strictEqual(errors.length, 2);
288+
assert.ok(errors[0] instanceof TypeError);
289+
assert.strictEqual(errors[0].message, "Variable type not supported: $arg, object");
290+
assert.ok(errors[1] instanceof TypeError);
291+
assert.strictEqual(errors[1].message, "Invalid argument type to DATETIME");
224292

293+
errors = [];
225294
msg = bundle.getMessage('dt-month');
226-
assert.strictEqual(bundle.formatPattern(msg.value, args, errors), '{$arg}');
227-
assert.strictEqual(errors.length, 1);
228-
assert.ok(errors.pop() instanceof TypeError);
295+
assert.strictEqual(bundle.formatPattern(msg.value, args, errors), '{DATETIME()}');
296+
assert.strictEqual(errors.length, 2);
297+
assert.ok(errors[0] instanceof TypeError);
298+
assert.strictEqual(errors[0].message, "Variable type not supported: $arg, object");
299+
assert.ok(errors[1] instanceof TypeError);
300+
assert.strictEqual(errors[1].message, "Invalid argument type to DATETIME");
229301

302+
errors = [];
230303
msg = bundle.getMessage('dt-bad-opt');
231-
assert.strictEqual(bundle.formatPattern(msg.value, args, errors), '{$arg}');
232-
assert.strictEqual(errors.length, 1);
233-
assert.ok(errors.pop() instanceof TypeError);
304+
assert.strictEqual(bundle.formatPattern(msg.value, args, errors), '{DATETIME()}');
305+
assert.strictEqual(errors.length, 2);
306+
assert.ok(errors[0] instanceof TypeError);
307+
assert.strictEqual(errors[0].message, "Variable type not supported: $arg, object");
308+
assert.ok(errors[1] instanceof TypeError);
309+
assert.strictEqual(errors[1].message, "Invalid argument type to DATETIME");
234310
});
235311
});
236312
});

0 commit comments

Comments
 (0)