1- import {
2- IntegerLiteral ,
3- Message ,
4- Parameter ,
5- PatternElement ,
6- Selector ,
7- StringLiteral ,
8- Variant ,
9- } from "./model.js" ;
1+ import { Message , Parameter , PatternElement , Selector , StringLiteral , Variant } from "./model.js" ;
102import { REGISTRY } from "./registry.js" ;
11- import { BooleanValue , NumberValue , PluralValue , RuntimeValue , StringValue } from "./runtime.js" ;
3+ import { BooleanValue , NumberValue , RuntimeValue , StringValue } from "./runtime.js" ;
124
135// Resolution context for a single formatMessage() call.
146
@@ -64,27 +56,22 @@ export class FormattingContext {
6456 }
6557
6658 selectVariant ( variants : Array < Variant > , selectors : Array < Selector > ) : Variant {
67- interface ResolvedSelector {
68- value : RuntimeValue < unknown > ;
69- default : string ;
70- }
59+ let selector_values : Array < RuntimeValue < unknown > > = [ ] ;
60+ let selector_defaults : Array < StringLiteral > = [ ] ;
7161
72- let resolved_selectors : Array < ResolvedSelector > = [ ] ;
7362 for ( let selector of selectors ) {
7463 switch ( selector . expr . type ) {
7564 case "VariableReference" : {
76- resolved_selectors . push ( {
77- value : this . vars [ selector . expr . name ] ,
78- default : selector . default . value ,
79- } ) ;
65+ let value = this . vars [ selector . expr . name ] ;
66+ selector_values . push ( value ) ;
67+ selector_defaults . push ( selector . default ) ;
8068 break ;
8169 }
8270 case "FunctionCall" : {
8371 let callable = REGISTRY [ selector . expr . name ] ;
84- resolved_selectors . push ( {
85- value : callable ( this , selector . expr . args , selector . expr . opts ) ,
86- default : selector . default . value ,
87- } ) ;
72+ let value = callable ( this , selector . expr . args , selector . expr . opts ) ;
73+ selector_values . push ( value ) ;
74+ selector_defaults . push ( selector . default ) ;
8875 break ;
8976 }
9077 default :
@@ -93,37 +80,18 @@ export class FormattingContext {
9380 }
9481 }
9582
96- function matches_corresponding_selector ( key : StringLiteral | IntegerLiteral , idx : number ) {
97- let selector = resolved_selectors [ idx ] ;
98- switch ( key . type ) {
99- case "StringLiteral" : {
100- if ( key . value === selector . value . value ) {
101- return true ;
102- }
103- break ;
104- }
105- case "IntegerLiteral" : {
106- let num = parseInt ( key . value ) ;
107- if ( selector . value instanceof NumberValue ) {
108- if ( num === selector . value . value ) {
109- return true ;
110- }
111- } else if ( selector . value instanceof PluralValue ) {
112- if ( key . value === selector . value . value || num === selector . value . count ) {
113- return true ;
114- }
115- }
116- break ;
117- }
118- }
119-
120- return key . value === selector . default ;
121- }
122-
12383 for ( let variant of variants ) {
12484 // When keys is an empty array, every() always returns true. This is
12585 // used single-variant messages to return their only variant.
126- if ( variant . keys . every ( matches_corresponding_selector ) ) {
86+ if (
87+ variant . keys . every (
88+ ( key , idx ) =>
89+ // Key matches corresponding selector value…
90+ selector_values [ idx ] . match ( this , key ) ||
91+ // … or the corresponding default.
92+ key . value === selector_defaults [ idx ] . value
93+ )
94+ ) {
12795 return variant ;
12896 }
12997 }
0 commit comments