Skip to content

Commit c50801d

Browse files
ptomatojustingrant
authored andcommitted
Editorial: Rewrite duration grammar to avoid extra fraction checks
Suggested by Anba, this is an editorial improvement to make Duration strings like PT3.5H40M (where a component with a fractional part is followed by another component) invalid according to the ISO 8601 grammar. Previously, such strings were valid according to the grammar, but weeded out with an extra check. In order to test the new grammar productions, brings validStrings.mjs up to date. Previously, support for minute and hour fractional parts had been left out of validStrings.mjs altogether. There are already tests for the invalid strings in test262. Closes: #2282 UPSTREAM_COMMIT=2b21aa1b26da178b2fe179ec4c0379945c9edd61
1 parent 4d73bab commit c50801d

File tree

1 file changed

+21
-6
lines changed

1 file changed

+21
-6
lines changed

test/validStrings.mjs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -341,31 +341,46 @@ const annotatedMonthDay = withSyntaxConstraints(
341341
}
342342
);
343343

344-
const durationFraction = withCode(fraction, (data, result) => {
344+
const durationSecondsFraction = withCode(fraction, (data, result) => {
345345
result = result.slice(1);
346346
const fraction = result.padEnd(9, '0');
347347
data.milliseconds = +fraction.slice(0, 3) * data.factor;
348348
data.microseconds = +fraction.slice(3, 6) * data.factor;
349349
data.nanoseconds = +fraction.slice(6, 9) * data.factor;
350350
});
351+
const durationMinutesFraction = withCode(fraction, (data, result) => {
352+
result = result.slice(1);
353+
const ns = +result.padEnd(9, '0') * 60;
354+
data.seconds = Math.trunc(ns / 1e9) * data.factor;
355+
data.milliseconds = Math.trunc((ns % 1e9) / 1e6) * data.factor;
356+
data.microseconds = Math.trunc((ns % 1e6) / 1e3) * data.factor;
357+
data.nanoseconds = Math.trunc(ns % 1e3) * data.factor;
358+
});
359+
const durationHoursFraction = withCode(fraction, (data, result) => {
360+
result = result.slice(1);
361+
const ns = +result.padEnd(9, '0') * 3600;
362+
data.minutes = Math.trunc(ns / 6e10) * data.factor;
363+
data.seconds = Math.trunc((ns % 6e10) / 1e9) * data.factor;
364+
data.milliseconds = Math.trunc((ns % 1e9) / 1e6) * data.factor;
365+
data.microseconds = Math.trunc((ns % 1e6) / 1e3) * data.factor;
366+
data.nanoseconds = Math.trunc(ns % 1e3) * data.factor;
367+
});
351368

352369
const digitsNotInfinite = withSyntaxConstraints(oneOrMore(digit()), (result) => {
353370
if (!Number.isFinite(+result)) throw new SyntaxError('try again on infinity');
354371
});
355372
const durationSeconds = seq(
356373
withCode(digitsNotInfinite, (data, result) => (data.seconds = +result * data.factor)),
357-
[durationFraction],
374+
[durationSecondsFraction],
358375
secondsDesignator
359376
);
360377
const durationMinutes = seq(
361378
withCode(digitsNotInfinite, (data, result) => (data.minutes = +result * data.factor)),
362-
minutesDesignator,
363-
[durationSeconds]
379+
choice(seq(minutesDesignator, [durationSeconds]), seq(durationMinutesFraction, minutesDesignator))
364380
);
365381
const durationHours = seq(
366382
withCode(digitsNotInfinite, (data, result) => (data.hours = +result * data.factor)),
367-
hoursDesignator,
368-
[choice(durationMinutes, durationSeconds)]
383+
choice(seq(hoursDesignator, [choice(durationMinutes, durationSeconds)]), seq(durationHoursFraction, hoursDesignator))
369384
);
370385
const durationTime = seq(timeDesignator, choice(durationHours, durationMinutes, durationSeconds));
371386
const durationDays = seq(

0 commit comments

Comments
 (0)