1.5.1 GetMessageData ( source )
The implementation-defined abstract operation GetMessageData takes argument source (a String or an Object) and returns an Object conforming to the JSON Schema definition of a message according to the Unicode MessageFormat 2.0 specification.
If source is a String, it returns the message data representation corresponding to the input source according to the
Unicode MessageFormat 2.0 syntax.
If source is an Object, it checks that source holds a valid message data representation,
and returns an equivalent Object that is not affected by any further changes to source.
If source contains a syntax or data model error, this operation throws a SyntaxError.
1.5.4 GetMessageFunctions ( userFunctions )
The abstract operation GetMessageFunctions takes argument userFunctions (an Object or undefined) and returns an Object. It determines the functions available during message formatting. It performs the following steps when called:
- Let numberSteps be the algorithm steps defined in 1.5.4.1.
- Let number be CreateBuiltinFunction(numberSteps, 3, "number", « »).
- Let stringSteps be the algorithm steps defined in 1.5.4.2.
- Let string be CreateBuiltinFunction(stringSteps, 3, "string", « »).
- Let dateTimeSteps be the algorithm steps defined in 1.5.4.3.
- Let dateTime be CreateBuiltinFunction(dateTimeSteps, 3, "datetime", « »).
- Let dateSteps be the algorithm steps defined in 1.5.4.4.
- Let date be CreateBuiltinFunction(dateSteps, 3, "date", « »).
- Let timeSteps be the algorithm steps defined in 1.5.4.5.
- Let time be CreateBuiltinFunction(timeSteps, 3, "time", « »).
- Let functions be OrdinaryObjectCreate(%Object.prototype%).
- Perform ! CreateDataPropertyOrThrow(functions, "number", number).
- Perform ! CreateDataPropertyOrThrow(functions, "string", string).
- Perform ! CreateDataPropertyOrThrow(functions, "datetime", dateTime).
- Perform ! CreateDataPropertyOrThrow(functions, "date", date).
- Perform ! CreateDataPropertyOrThrow(functions, "time", time).
- For each String name of ? EnumerableOwnProperties(userFunctions, key),
- Let func be ? Get(userFunctions, name).
- If IsCallable(func) is true, then
- Perform ! CreateDataPropertyOrThrow(functions, name, func).
- Else,
- Throw a TypeError exception.
- Return functions.
1.5.4.1 MessageFormat Number Functions
A MessageFormat number function is an anonymous built-in function.
When a MessageFormat number function is called with arguments funcCtx (an Object), options (an Object), and input (an ECMAScript language value), the following steps are taken:
- Let locale be ! Get(funcCtx, "locale").
- Let localeMatcher be ! Get(funcCtx, "localeMatcher").
- Let source be ! Get(funcCtx, "source").
- Let opts be OrdinaryObjectCreate(%Object.prototype%).
- Perform ! CreateDataPropertyOrThrow(opt, "localeMatcher", localeMatcher).
- If Type(input) is Object, then
- Let valueOf be ? Get(input, "valueOf").
- If IsCallable(valueOf) is true, then
- Let inputOptions be ? Get(input, "options").
- Perform ? Call(Object.assign, undefined, « opts, inputOptions »).
- Set input to ? Call(valueOf, input).
- If Type(input) is String, then
- Set input to ? Call(JSON.parse, %JSON%, « input »).
- If Type(input) is not Number or BigInt, throw a TypeError exception.
- Let numberOptions be « "minimumIntegerDigits", "minimumFractionDigits", "maximumFractionDigits", "minimumSignificantDigits", "maximumSignificantDigits", "roundingIncrement" ».
- Let booleanOptions be « "useGrouping" ».
- Let select be "cardinal".
- For each String optName of ? EnumerableOwnProperties(options, key),
- If optName is not "localeMatcher" and optName is not "type", then
- Let optValue be ? Get(options, optName).
- If Type(optValue) is Object, then
- Let optValueOf be ? Get(optValue, "valueOf").
- If IsCallable(optValueOf) is true, then
- Set optValue to ? Call(optValueOf, optValue).
- If optName is "select", then
- If optValue is "ordinal" or optValue is "exact", then
- Set select to optValue
- Else if optValue is not "plural", then
- Throw a RangeError exception.
- Else,
- If Type(optValue) is String, then
- If numberOptions contains optName, then
- Set optValue to ToNumber(optValue).
- Else if booleanOptions contains optName, then
- If optValue is "true", then
- Set optValue to true.
- Else if optValue is "false", then
- Set optValue to false.
- Perform ? Set(opts, optName, optValue, true).
- Let numberFormat be ? Construct(%Intl.NumberFormat%, « locale, opts »).
- If select is "exact", then
- Perform ? opts.[[Delete]]("type").
- Let pluralRules be undefined.
- Else,
- Perform ? Set(opts, "type", select, true).
- Let pluralRules be ? Construct(%Intl.PluralRules%, « locale, opts »).
- Let selectKeyClosure be a new Abstract Closure with parameters (keys) that captures input and pluralRules and performs the following steps when called:
- Let keyList be ? CreateListFromArrayLike(keys, « String »).
- Let str be ? ToString(input).
- If keyList contains str, return str.
- If pluralRules is not undefined, then
- Let category be ? Call(Intl.PluralRules.prototype.select, pluralRules, « input »).
- If keyList contains category, return category.
- Return null.
- Let selectKey be CreateBuiltinFunction(selectKeyClosure, 1, "selectKey", « »).
- Let toPartsClosure be a new Abstract Closure with no parameters that captures input, source, and numberFormat and performs the following steps when called:
- Let parts be ? Call(Intl.NumberFormat.prototype.formatToParts, numberFormat, « input »).
- Let result be OrdinaryObjectCreate(%Object.prototype%).
- Perform ! CreateDataPropertyOrThrow(result, "type", "number").
- Perform ! CreateDataPropertyOrThrow(result, "source", source).
- Perform ! CreateDataPropertyOrThrow(result, "locale", numberFormat.[[Locale]]).
- Perform ! CreateDataPropertyOrThrow(result, "parts", parts).
- Return CreateArrayFromList(« result »).
- Let toParts be CreateBuiltinFunction(toPartsClosure, 0, "toParts", « »).
- Let toStringClosure be a new Abstract Closure with no parameters that captures input and numberFormat and performs the following steps when called:
- Return ? Call(Intl.NumberFormat.prototype.format, numberFormat, « input »).
- Let toString be CreateBuiltinFunction(toStringClosure, 0, "toString", « »).
- Let valueOfClosure be a new Abstract Closure with no parameters that captures input and performs the following steps when called:
- Return input.
- Let valueOf be CreateBuiltinFunction(valueOfClosure, 0, "valueOf", « »).
- Let mv be OrdinaryObjectCreate(%Object.prototype%).
- Perform ! CreateDataPropertyOrThrow(mv, "type", "number").
- Perform ! CreateDataPropertyOrThrow(mv, "source", source).
- Perform ! CreateDataPropertyOrThrow(mv, "locale", numberFormat.[[Locale]]).
- Perform ! CreateDataPropertyOrThrow(mv, "options", opts).
- Perform ! CreateDataPropertyOrThrow(mv, "selectKey", selectKey).
- Perform ! CreateDataPropertyOrThrow(mv, "toParts", toParts).
- Perform ! CreateDataPropertyOrThrow(mv, "toString", toString).
- Perform ! CreateDataPropertyOrThrow(mv, "valueOf", valueOf).
- Return mv.
The "length" property of a MessageFormat number function is 3.
1.5.4.2 MessageFormat String Functions
A MessageFormat string function is an anonymous built-in function.
When a MessageFormat string function is called with arguments funcCtx (an Object), options (an Object), and input (an ECMAScript language value), the following steps are taken:
- Let str be ? ToString(input).
- Let selectKeyClosure be a new Abstract Closure with parameters (keys) that captures str and performs the following steps when called:
- Let keyList be ? CreateListFromArrayLike(keys, « String »).
- If keyList contains str, return str.
- Else, return null.
- Let selectKey be CreateBuiltinFunction(selectKeyClosure, 1, "selectKey", « »).
- Let toPartsClosure be a new Abstract Closure with no parameters that captures funcCtx and str and performs the following steps when called:
- Let source be ! Get(funcCtx, "source").
- Let locale be ! Get(funcCtx, "locale").
- Let locale0 be ! Get(locale, "0").
- Let result be OrdinaryObjectCreate(%Object.prototype%).
- Perform ! CreateDataPropertyOrThrow(result, "type", "string").
- Perform ! CreateDataPropertyOrThrow(result, "source", source).
- Perform ! CreateDataPropertyOrThrow(result, "locale", locale0).
- Perform ! CreateDataPropertyOrThrow(result, "value", str).
- Return CreateArrayFromList(« result »).
- Let toParts be CreateBuiltinFunction(toPartsClosure, 0, "toParts", « »).
- Let toStringClosure be a new Abstract Closure with no parameters that captures str and performs the following steps when called:
- Return str.
- Let toString be CreateBuiltinFunction(toStringClosure, 0, "toString", « »).
- Let valueOf be CreateBuiltinFunction(toStringClosure, 0, "valueOf", « »).
- Let mv be OrdinaryObjectCreate(%Object.prototype%).
- Perform ! CreateDataPropertyOrThrow(mv, "type", "number").
- Perform ! CreateDataPropertyOrThrow(mv, "source", source).
- Perform ! CreateDataPropertyOrThrow(mv, "locale", numberFormat.[[Locale]]).
- Perform ! CreateDataPropertyOrThrow(mv, "options", opts).
- Perform ! CreateDataPropertyOrThrow(mv, "selectKey", selectKey).
- Perform ! CreateDataPropertyOrThrow(mv, "toParts", toParts).
- Perform ! CreateDataPropertyOrThrow(mv, "toString", toString).
- Perform ! CreateDataPropertyOrThrow(mv, "valueOf", valueOf).
- Return mv.
The "length" property of a MessageFormat string function is 3.
1.5.4.3 MessageFormat DateTime Functions
A MessageFormat dateTime function is an anonymous built-in function.
When a MessageFormat dateTime function is called with arguments funcCtx (an Object), options (an Object), and input (an ECMAScript language value), the following steps are taken:
- Let opts be OrdinaryObjectCreate(%Object.prototype%).
- Let localeMatcher be ! Get(funcCtx, "localeMatcher").
- Perform ! CreateDataPropertyOrThrow(opts, "localeMatcher", localeMatcher).
- Let value be ? HandleDateTimeInput(input, opts).
- For each String optName of ? EnumerableOwnProperties(options, key),
- If optName is not "locale", then
- Let optValue be ? Get(options, optName).
- If Type(optValue) is Object, then
- Let optValueOf be ? Get(optValue, "valueOf").
- If IsCallable(optValueOf) is true, then
- Set optValue_ to ? Call(optValueOf, optValue).
- If optName is "fractionalSecondDigits", set optValue to ToNumber(optValue).
- Else if optName is "hour12", then
- If optValue is "true", then
- Set optValue to true.
- Else if optValue is "false", then
- Set optValue to false.
- Else, set optValue to ToString(optValue).
- Perform ? Set(opts, optName, optValue, "true").
- Return ? DateTimeMessageValue(value, opts, funcCtx).
The "length" property of a MessageFormat dateTime function is 3.
1.5.4.4 MessageFormat Date Functions
A MessageFormat date function is an anonymous built-in function.
When a MessageFormat date function is called with arguments funcCtx (an Object), options (an Object), and input (an ECMAScript language value), the following steps are taken:
- Let opts be OrdinaryObjectCreate(%Object.prototype%).
- Let localeMatcher be ! Get(funcCtx, "localeMatcher").
- Perform ! CreateDataPropertyOrThrow(opts, "localeMatcher", localeMatcher).
- Let value be ? HandleDateTimeInput(input, opts).
- Let dateStyle be ! Get(options, "style").
- If dateStyle is null or undefined, then
- Set dateStyle to ! Get(opts, "dateStyle").
- If dateStyle is null or undefined, then
- Set dateStyle to "short".
- For each String optName of ? EnumerableOwnProperties(opts, key),
- If optName is not "calendar", "localeMatcher", "hour12", "hourCycle", "numberingSystem", or "timeZone", then
- Perform ? DeletePropertyOrThrow(opts, optName).
- Perform ? Set(opts, "dateStyle", ToString(dateStyle)).
- Return ? DateTimeMessageValue(value, opts, funcCtx).
The "length" property of a MessageFormat date function is 3.
1.5.4.5 MessageFormat Time Functions
A MessageFormat time function is an anonymous built-in function.
When a MessageFormat time function is called with arguments funcCtx (an Object), options (an Object), and input (an ECMAScript language value), the following steps are taken:
- Let opts be OrdinaryObjectCreate(%Object.prototype%).
- Let localeMatcher be ! Get(funcCtx, "localeMatcher").
- Perform ! CreateDataPropertyOrThrow(opts, "localeMatcher", localeMatcher).
- Let value be ? HandleDateTimeInput(input, opts).
- Let timeStyle be ! Get(options, "style").
- If timeStyle is null or undefined, then
- Set timeStyle to ! Get(opts, "timeStyle").
- If timeStyle is null or undefined, then
- Set timeStyle to "short".
- For each String optName of ? EnumerableOwnProperties(opts, key),
- If optName is not "calendar", "localeMatcher", "hour12", "hourCycle", "numberingSystem", or "timeZone", then
- Perform ? DeletePropertyOrThrow(opts, optName).
- Perform ? Set(opts, "timeStyle", ToString(timeStyle)).
- Return ? DateTimeMessageValue(value, opts, funcCtx).
The "length" property of a MessageFormat time function is 3.
1.5.6 ResolveMessage ( ctx )
The abstract operation ResolveMessage takes argument ctx (a MessageFormatContext Record) and returns a List of Strings and Objects. It resolves a message into a List of Strings and Objects with either [[MessageMarkup]] or [[MessageValue]] internal slots. It performs the following steps when called:
- Let result be an empty List.
- Let pattern be ? SelectPattern(ctx).
- For each element el of pattern,
- If Type(el) is String, then
- Append el to result.
- Else,
- Assert: Type(el) is Object.
- Let elType be ? Get(el, "type").
- If elType is "markup", then
- Let res be OrdinaryObjectCreate(null, « [[MessageMarkup]] »).
- Set res.[[MessageMarkup]] to el.
- Else,
- Assert: elType is "expression".
- Let res be ResolveExpression(ctx, el).
- Append res to result.
- Return result.
1.5.6.1 SelectPattern ( ctx )
The abstract operation SelectPattern takes argument ctx (a MessageFormatContext Record) and returns a List of Strings and Objects with an internal slot [[MessageValue]]. It selects the pattern to format from the message data model. It performs the following steps when called:
- Let msgData be ctx.[[MessageFormat]].[[MessageData]].
- Let msgType be ? Get(msgData, "type").
- If msgType is "message", then
- Let pattern be ? Get(msgData, "pattern").
- Else,
- Assert: msgType is "select".
- Let selectorsData be ? Get(msgData, "selectors").
- Let selectorExpressions be ? CreateListFromArrayLike(selectorsData, « Object »).
- Let selectors be an empty List.
- For each element selExp of selectorExpressions,
- Let sel be ResolveExpression(ctx, selExp).
- Let selectKey be ? Get(sel.[[MessageValue]], "selectKey").
- If IsCallable(selectKey) is true, then
- Append sel.[[MessageValue]] to selectors.
- Else,
- Let error be ThrowCompletion(TypeError).
- Perform ? HandleMessageFormatError(ctx, error).
- Append null to selectors.
- Let variantsArray be ? Get(msgData, "variants").
- Let variants be ? CreateListFromArrayLike(variantsArray, « Object »).
- Let selectedVariant be ? SelectVariant(ctx, selectors, variants).
- Return ? CreateListFromArrayLike(pattern, « String, Object »).
1.5.6.2 SelectVariant ( ctx, selectors, variants )
The implementation-defined abstract operation SelectVariant takes arguments ctx (a MessageFormatContext Record), selectors (a List of Object and Null values), and variants (a List of Objects) and returns an Object.
It applies the variant selection method defined by
the "Resolve Preferences", "Filter Variants", and "Sort Variants" steps of the
Pattern Selection
section of the Unicode MessageFormat 2.0 specification.
For the selection, Null values in selectors indicate selectors for which selection will always fail.
If any errors are encountered during the selection,
the HandleMessageFormatError abstract operation must be called
with ctx and an abrupt Completion Record containing an Error.
The value returned by this operation must be an Object matching the JSON Schema definition of a message pattern:
https://github.com/unicode-org/message-format-wg/blob/main/spec/data-model/message.json#/$defs/pattern
.
1.5.7 ResolveExpression ( ctx, expression )
The abstract operation ResolveExpression takes arguments ctx (a MessageFormatContext Record) and expression (an Object) and returns an Object with an internal slot [[MessageValue]]. It resolves the value of an expression for selection and formatting. It performs the following steps when called:
- Let source be ? GetSource(ctx, expression).
- Let arg be ? Get(expression, "arg").
- If arg is undefined, then
- Let resArg be undefined.
- Else,
- Let resArg be ResolveValue(ctx, arg).
- If resArg has a [[MessageFallback]] internal slot, return resArg.
- Let annotation be ? Get(expression, "annotation").
- If annotation is undefined, then
- Assert: resArg is not undefined.
- If Type(resArg) is Object and resArg has a [[MessageValue]] internal slot, then
- Return resArg.
- Else if Type(resArg) is Number or BigInt, then
- Set annotation to OrdinaryObjectCreate(null).
- Perform ! CreateDataPropertyOrThrow(annotation, "type", "function").
- Perform ! CreateDataPropertyOrThrow(annotation, "name", "number").
- Else if Type(resArg) is String, then
- Set annotation to OrdinaryObjectCreate(null).
- Perform ! CreateDataPropertyOrThrow(annotation, "type", "function").
- Perform ! CreateDataPropertyOrThrow(annotation, "name", "string").
- Else,
- Return ResolveUnknown(source, resArg).
- If ? Get(annotation, "type") is not "function", then
- Let error be ThrowCompletion(ReferenceError).
- Perform ? HandleMessageFormatError(ctx, error).
- Return ResolveFallback(source).
- Return ResolveFunction(ctx, source, resArg, annotation).
1.5.7.1 ResolveFunction ( ctx, source, resArg, annotation )
The abstract operation ResolveFunction takes arguments ctx (a MessageFormatContext Record), source (a String), resArg (an Object or undefined), and annotation (an Object) and returns an Object with an internal slot [[MessageValue]]. It resolves the value of an expression with a function annotation. It performs the following steps when called:
- Let name be ? Get(annotation, "name").
- Let function be ? Get(ctx.[[MessageFormat]].[[Functions]], name).
- If IsCallable(function) is false, then
- Let error be ThrowCompletion(ReferenceError).
- Perform ? HandleMessageFormatError(ctx, error).
- Return ResolveFallback(source).
- Let funcCtx be OrdinaryObjectCreate(%Object.prototype%).
- Let locales be CreateArrayFromList(ctx.[[MessageFormat]].[[RequestedLocales]]).
- Perform ! CreateDataPropertyOrThrow(funcCtx, "locale", locales).
- Perform ! CreateDataPropertyOrThrow(funcCtx, "localeMatcher", ctx.[[MessageFormat]].[[LocaleMatcher]]).
- Perform ! CreateDataPropertyOrThrow(funcCtx, "source", source).
- Let options be OrdinaryObjectCreate(%Object.prototype%).
- Let optArray be ? Get(annotation, "options").
- If optArray is not undefined, then
- Let optList be ? CreateListFromArrayLike(optArray).
- For each element opt of optList,
- Let optName be ? Get(opt, "name").
- Let optValue be ? Get(opt, "value").
- Let resValue be ResolveValue(ctx, optValue).
- If Type(resValue) is Object, then
- If resValue has a [[MessageFallback]] internal slot, then
- Set resValue to undefined.
- Else if resValue has a [[MessageValue]] internal slot, then
- Set resValue to resValue.[[MessageValue]].
- Perform ? CreateDataPropertyOrThrow(options, optName, resValue).
- Perform ! CreateDataPropertyOrThrow(part, "options", resOptions).
- Let funcArgs be « funcCtx, options ».
- If Type(resArg) is Object and resArg has a [[MessageValue]] internal slot, then
- Set resArg to resArg.[[MessageValue]].
- If resArg is not undefined, then
- Append resArg to funcArgs.
- Let funcRes be Completion(Call(function, undefined, funcArgs)).
- If funcRes is a normal completion, then
- Let mv be funcRes.[[Value]].
- If Type(mv) is Object and Type(? Get(mv, "type")) is String and Type(? Get(mv, "source")) is String, then
- Let result be OrdinaryObjectCreate(null, « [[MessageValue]] »).
- Set result.[[MessageValue]] to mv.
- Return result.
- Else,
- Let error be ThrowCompletion(TypeError).
- Perform ? HandleMessageFormatError(ctx, error).
- Return ResolveFallback(source).
- Else,
- Perform ? HandleMessageFormatError(ctx, funcRes).
- Return ResolveFallback(source).
1.5.7.2 ResolveUnknown ( source, value )
The abstract operation ResolveUnknown takes arguments source (a String) and value (an ECMAScript language value) and returns an Object with an internal slot [[MessageValue]]. It resolves an unknown value. It performs the following steps when called:
- Let toPartsClosure be a new Abstract Closure with no parameters that captures source and value and performs the following steps when called:
- Let part be OrdinaryObjectCreate(%Object.prototype%).
- Perform ! CreateDataPropertyOrThrow(part, "type", "unknown").
- Perform ! CreateDataPropertyOrThrow(part, "source", source).
- Perform ! CreateDataPropertyOrThrow(part, "value", value).
- Return CreateArrayFromList(« part »).
- Let toParts be CreateBuiltinFunction(toPartsClosure, 0, "toParts", « »).
- Let toStringClosure be a new Abstract Closure with no parameters that captures value and performs the following steps when called:
- Return ? ToString(value).
- Let toString be CreateBuiltinFunction(toStringClosure, 0, "toString", « »).
- Let valueOfClosure be a new Abstract Closure with no parameters that captures value and performs the following steps when called:
- Return value.
- Let valueOf be CreateBuiltinFunction(valueOfClosure, 0, "valueOf", « »).
- Let mv be OrdinaryObjectCreate(%Object.prototype%).
- Perform ! CreateDataPropertyOrThrow(mv, "type", "unknown").
- Perform ! CreateDataPropertyOrThrow(mv, "source", source).
- Perform ! CreateDataPropertyOrThrow(mv, "locale", "und").
- Perform ! CreateDataPropertyOrThrow(mv, "toParts", toParts).
- Perform ! CreateDataPropertyOrThrow(mv, "toString", toString).
- Perform ! CreateDataPropertyOrThrow(mv, "valueOf", valueOf).
- Let unknown be OrdinaryObjectCreate(null, « [[MessageValue]] »).
- Set unknown.[[MessageValue]] to mv.
- Return unknown.