forked from facebook/hermes
-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds in default Intl.DateTimeFormat (#127)
* adds default Intl.DateTimeFormat * adds supportedLocales * simple PR feedback * format * more simple PR feedback * change to nullptr * use std:optional * Create shared code file and more PR feedback * free datetimeformat * store std::string globally * add more error checking * Update IntlAPIs.md * fix camelCase * remove old comment
- Loading branch information
1 parent
1e01740
commit f5d4942
Showing
5 changed files
with
1,383 additions
and
50 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
/* | ||
* Copyright (c) Meta Platforms, Inc. and affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
// This file includes shared code between Apple and Windows implementation of Intl APIs | ||
#include "hermes/Platform/Intl/PlatformIntl.h" | ||
|
||
using namespace ::hermes; | ||
|
||
namespace hermes { | ||
namespace platform_intl { | ||
|
||
// https://402.ecma-international.org/8.0/#sec-bestavailablelocale | ||
std::optional<std::u16string> bestAvailableLocale( | ||
const std::vector<std::u16string> &availableLocales, | ||
const std::u16string &locale) { | ||
// 1. Let candidate be locale | ||
std::u16string candidate = locale; | ||
|
||
// 2. Repeat | ||
while (true) { | ||
// a. If availableLocales contains an element equal to candidate, return | ||
// candidate. | ||
if (llvh::find(availableLocales, candidate) != availableLocales.end()) | ||
return candidate; | ||
// b. Let pos be the character index of the last occurrence of "-" (U+002D) | ||
// within candidate. | ||
size_t pos = candidate.rfind(u'-'); | ||
|
||
// ...If that character does not occur, return undefined. | ||
if (pos == std::u16string::npos) | ||
return std::nullopt; | ||
|
||
// c. If pos ≥ 2 and the character "-" occurs at index pos-2 of candidate, | ||
// decrease pos by 2. | ||
if (pos >= 2 && candidate[pos - 2] == '-') | ||
pos -= 2; | ||
|
||
// d. Let candidate be the substring of candidate from position 0, | ||
// inclusive, to position pos, exclusive. | ||
candidate.resize(pos); | ||
} | ||
} | ||
|
||
// https://402.ecma-international.org/8.0/#sec-lookupsupportedlocales | ||
std::vector<std::u16string> lookupSupportedLocales( | ||
const std::vector<std::u16string> &availableLocales, | ||
const std::vector<std::u16string> &requestedLocales) { | ||
// 1. Let subset be a new empty List. | ||
std::vector<std::u16string> subset; | ||
// 2. For each element locale of requestedLocales in List order, do | ||
for (const std::u16string &locale : requestedLocales) { | ||
// a. Let noExtensionsLocale be the String value that is locale with all | ||
// Unicode locale extension sequences removed. | ||
// We can skip this step, see the comment in lookupMatcher. | ||
// b. Let availableLocale be BestAvailableLocale(availableLocales, | ||
// noExtensionsLocale). | ||
std::optional<std::u16string> availableLocale = | ||
bestAvailableLocale(availableLocales, locale); | ||
// c. If availableLocale is not undefined, append locale to the end of | ||
// subset. | ||
if (availableLocale) { | ||
subset.push_back(locale); | ||
} | ||
} | ||
// 3. Return subset. | ||
return subset; | ||
} | ||
|
||
std::optional<bool> getOptionBool( | ||
vm::Runtime &runtime, | ||
const Options &options, | ||
const std::u16string &property, | ||
std::optional<bool> fallback) { | ||
// 1. Assert: Type(options) is Object. | ||
// 2. Let value be ? Get(options, property). | ||
auto value = options.find(property); | ||
// 3. If value is undefined, return fallback. | ||
if (value == options.end()) { | ||
return fallback; | ||
} | ||
// 8. Return value. | ||
return value->second.getBool(); | ||
} | ||
|
||
// Implementation of | ||
// https://402.ecma-international.org/8.0/#sec-todatetimeoptions | ||
vm::CallResult<Options> toDateTimeOptions( | ||
vm::Runtime &runtime, | ||
Options options, | ||
std::u16string_view required, | ||
std::u16string_view defaults) { | ||
// 1. If options is undefined, let options be null; otherwise let options be ? | ||
// ToObject(options). | ||
// 2. Let options be OrdinaryObjectCreate(options). | ||
// 3. Let needDefaults be true. | ||
bool needDefaults = true; | ||
// 4. If required is "date" or "any", then | ||
if (required == u"date" || required == u"any") { | ||
// a. For each property name prop of « "weekday", "year", "month", "day" », | ||
// do | ||
// TODO(T116352920): Make this a std::u16string props[] once we have | ||
// constexpr std::u16string. | ||
static constexpr std::u16string_view props[] = { | ||
u"weekday", u"year", u"month", u"day"}; | ||
for (const auto &prop : props) { | ||
// i. Let value be ? Get(options, prop). | ||
if (options.find(std::u16string(prop)) != options.end()) { | ||
// ii. If value is not undefined, let needDefaults be false. | ||
needDefaults = false; | ||
} | ||
} | ||
} | ||
// 5. If required is "time" or "any", then | ||
if (required == u"time" || required == u"any") { | ||
// a. For each property name prop of « "dayPeriod", "hour", "minute", | ||
// "second", "fractionalSecondDigits" », do | ||
static constexpr std::u16string_view props[] = { | ||
u"dayPeriod", u"hour", u"minute", u"second", u"fractionalSecondDigits"}; | ||
for (const auto &prop : props) { | ||
// i. Let value be ? Get(options, prop). | ||
if (options.find(std::u16string(prop)) != options.end()) { | ||
// ii. If value is not undefined, let needDefaults be false. | ||
needDefaults = false; | ||
} | ||
} | ||
} | ||
// 6. Let dateStyle be ? Get(options, "dateStyle"). | ||
auto dateStyle = options.find(u"dateStyle"); | ||
// 7. Let timeStyle be ? Get(options, "timeStyle"). | ||
auto timeStyle = options.find(u"timeStyle"); | ||
// 8. If dateStyle is not undefined or timeStyle is not undefined, let | ||
// needDefaults be false. | ||
if (dateStyle != options.end() || timeStyle != options.end()) { | ||
needDefaults = false; | ||
} | ||
// 9. If required is "date" and timeStyle is not undefined, then | ||
if (required == u"date" && timeStyle != options.end()) { | ||
// a. Throw a TypeError exception. | ||
return runtime.raiseTypeError( | ||
"Unexpectedly found timeStyle option for \"date\" property"); | ||
} | ||
// 10. If required is "time" and dateStyle is not undefined, then | ||
if (required == u"time" && dateStyle != options.end()) { | ||
// a. Throw a TypeError exception. | ||
return runtime.raiseTypeError( | ||
"Unexpectedly found dateStyle option for \"time\" property"); | ||
} | ||
// 11. If needDefaults is true and defaults is either "date" or "all", then | ||
if (needDefaults && (defaults == u"date" || defaults == u"all")) { | ||
// a. For each property name prop of « "year", "month", "day" », do | ||
static constexpr std::u16string_view props[] = {u"year", u"month", u"day"}; | ||
for (const auto &prop : props) { | ||
// i. Perform ? CreateDataPropertyOrThrow(options, prop, "numeric"). | ||
options.emplace(prop, Option(std::u16string(u"numeric"))); | ||
} | ||
} | ||
// 12. If needDefaults is true and defaults is either "time" or "all", then | ||
if (needDefaults && (defaults == u"time" || defaults == u"all")) { | ||
// a. For each property name prop of « "hour", "minute", "second" », do | ||
static constexpr std::u16string_view props[] = { | ||
u"hour", u"minute", u"second"}; | ||
for (const auto &prop : props) { | ||
// i. Perform ? CreateDataPropertyOrThrow(options, prop, "numeric"). | ||
options.emplace(prop, Option(std::u16string(u"numeric"))); | ||
} | ||
} | ||
// 13. return options | ||
return options; | ||
} | ||
|
||
} // namespace platform_intl | ||
} // namespace hermes |
Oops, something went wrong.