[Intl] Implement Intl.ListFromat format() and formatToParts().
Spec: http://tc39.github.io/proposal-intl-list-format/ Design Doc: go/add-intl.listformat-to-v8 Test: intl/list-format/* R=gsathya@chromium.org, mvstanton@chromium.org Bug: v8:7871 Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng Change-Id: I820c205ca842c228ffe37f7e1648667f30f80bd8 Reviewed-on: https://chromium-review.googlesource.com/1126683 Commit-Queue: Frank Tang <ftang@chromium.org> Reviewed-by: Adam Klein <adamk@chromium.org> Cr-Commit-Position: refs/heads/master@{#54991}
This commit is contained in:
parent
684d085640
commit
b27c3736c1
@ -4541,6 +4541,10 @@ void Genesis::InitializeGlobal_harmony_intl_list_format() {
|
||||
SimpleInstallFunction(isolate(), prototype, "resolvedOptions",
|
||||
Builtins::kListFormatPrototypeResolvedOptions, 0,
|
||||
false);
|
||||
SimpleInstallFunction(isolate(), prototype, "format",
|
||||
Builtins::kListFormatPrototypeFormat, 1, false);
|
||||
SimpleInstallFunction(isolate(), prototype, "formatToParts",
|
||||
Builtins::kListFormatPrototypeFormatToParts, 1, false);
|
||||
}
|
||||
|
||||
void Genesis::InitializeGlobal_harmony_locale() {
|
||||
|
@ -1340,6 +1340,12 @@ namespace internal {
|
||||
CPP(ListFormatConstructor) \
|
||||
/* ecma402 #sec-intl.listformat.prototype.resolvedoptions */ \
|
||||
CPP(ListFormatPrototypeResolvedOptions) \
|
||||
/* ecma402 #sec-intl-list-format.prototype.format */ \
|
||||
TFJ(ListFormatPrototypeFormat, \
|
||||
SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
|
||||
/* ecma402 #sec-intl-list-format.prototype.formattoparts */ \
|
||||
TFJ(ListFormatPrototypeFormatToParts, \
|
||||
SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
|
||||
/* ecma402 #sec-intl-locale-constructor */ \
|
||||
CPP(LocaleConstructor) \
|
||||
CPP(LocalePrototypeLanguage) \
|
||||
|
@ -6,8 +6,13 @@
|
||||
#error Internationalization is expected to be enabled.
|
||||
#endif // V8_INTL_SUPPORT
|
||||
|
||||
#include "src/builtins/builtins-iterator-gen.h"
|
||||
#include "src/builtins/builtins-utils-gen.h"
|
||||
#include "src/code-stub-assembler.h"
|
||||
#include "src/objects-inl.h"
|
||||
#include "src/objects.h"
|
||||
#include "src/objects/js-list-format-inl.h"
|
||||
#include "src/objects/js-list-format.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -16,6 +21,12 @@ class IntlBuiltinsAssembler : public CodeStubAssembler {
|
||||
public:
|
||||
explicit IntlBuiltinsAssembler(compiler::CodeAssemblerState* state)
|
||||
: CodeStubAssembler(state) {}
|
||||
|
||||
void ListFormatCommon(TNode<Context> context, TNode<Int32T> argc,
|
||||
Runtime::FunctionId format_func_id,
|
||||
const char* method_name);
|
||||
|
||||
Node* AllocateEmptyJSArray(TNode<Context> context);
|
||||
};
|
||||
|
||||
TF_BUILTIN(StringToLowerCaseIntl, IntlBuiltinsAssembler) {
|
||||
@ -129,5 +140,73 @@ TF_BUILTIN(StringPrototypeToLowerCaseIntl, IntlBuiltinsAssembler) {
|
||||
Return(CallBuiltin(Builtins::kStringToLowerCaseIntl, context, string));
|
||||
}
|
||||
|
||||
void IntlBuiltinsAssembler::ListFormatCommon(TNode<Context> context,
|
||||
TNode<Int32T> argc,
|
||||
Runtime::FunctionId format_func_id,
|
||||
const char* method_name) {
|
||||
CodeStubArguments args(this, ChangeInt32ToIntPtr(argc));
|
||||
|
||||
// Label has_list(this);
|
||||
// 1. Let lf be this value.
|
||||
// 2. If Type(lf) is not Object, throw a TypeError exception.
|
||||
TNode<Object> receiver = args.GetReceiver();
|
||||
|
||||
// 3. If lf does not have an [[InitializedListFormat]] internal slot, throw a
|
||||
// TypeError exception.
|
||||
ThrowIfNotInstanceType(context, receiver, JS_INTL_LIST_FORMAT_TYPE,
|
||||
method_name);
|
||||
TNode<JSListFormat> list_format = CAST(receiver);
|
||||
|
||||
// 4. If list is not provided or is undefined, then
|
||||
TNode<Object> list = args.GetOptionalArgumentValue(0);
|
||||
Label has_list(this);
|
||||
{
|
||||
GotoIfNot(IsUndefined(list), &has_list);
|
||||
if (format_func_id == Runtime::kFormatList) {
|
||||
// a. Return an empty String.
|
||||
args.PopAndReturn(EmptyStringConstant());
|
||||
} else {
|
||||
DCHECK_EQ(format_func_id, Runtime::kFormatListToParts);
|
||||
// a. Return an empty Array.
|
||||
args.PopAndReturn(AllocateEmptyJSArray(context));
|
||||
}
|
||||
}
|
||||
BIND(&has_list);
|
||||
{
|
||||
// 5. Let x be ? IterableToList(list).
|
||||
IteratorBuiltinsAssembler iterator_assembler(state());
|
||||
// TODO(adamk): Consider exposing IterableToList as a buitin and calling
|
||||
// it from here instead of inlining the operation.
|
||||
TNode<JSArray> x = iterator_assembler.IterableToList(context, list);
|
||||
|
||||
// 6. Return ? FormatList(lf, x).
|
||||
args.PopAndReturn(CallRuntime(format_func_id, context, list_format, x));
|
||||
}
|
||||
}
|
||||
|
||||
Node* IntlBuiltinsAssembler::AllocateEmptyJSArray(TNode<Context> context) {
|
||||
Node* array = CodeStubAssembler::AllocateJSArray(
|
||||
PACKED_ELEMENTS,
|
||||
LoadJSArrayElementsMap(PACKED_ELEMENTS, LoadNativeContext(context)),
|
||||
SmiConstant(0), SmiConstant(0));
|
||||
StoreObjectFieldNoWriteBarrier(array, JSArray::kElementsOffset,
|
||||
EmptyFixedArrayConstant());
|
||||
return array;
|
||||
}
|
||||
|
||||
TF_BUILTIN(ListFormatPrototypeFormat, IntlBuiltinsAssembler) {
|
||||
ListFormatCommon(
|
||||
CAST(Parameter(Descriptor::kContext)),
|
||||
UncheckedCast<Int32T>(Parameter(Descriptor::kJSActualArgumentsCount)),
|
||||
Runtime::kFormatList, "Intl.ListFormat.prototype.format");
|
||||
}
|
||||
|
||||
TF_BUILTIN(ListFormatPrototypeFormatToParts, IntlBuiltinsAssembler) {
|
||||
ListFormatCommon(
|
||||
CAST(Parameter(Descriptor::kContext)),
|
||||
UncheckedCast<Int32T>(Parameter(Descriptor::kJSActualArgumentsCount)),
|
||||
Runtime::kFormatListToParts, "Intl.ListFormat.prototype.formatToParts");
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -7,14 +7,18 @@
|
||||
#endif // V8_INTL_SUPPORT
|
||||
|
||||
#include <cmath>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
|
||||
#include "src/builtins/builtins-intl.h"
|
||||
#include "src/builtins/builtins-utils-inl.h"
|
||||
#include "src/builtins/builtins.h"
|
||||
#include "src/date.h"
|
||||
#include "src/elements.h"
|
||||
#include "src/intl.h"
|
||||
#include "src/objects-inl.h"
|
||||
#include "src/objects/intl-objects.h"
|
||||
#include "src/objects/js-array-inl.h"
|
||||
#include "src/objects/js-collator-inl.h"
|
||||
#include "src/objects/js-list-format-inl.h"
|
||||
#include "src/objects/js-locale-inl.h"
|
||||
@ -25,6 +29,7 @@
|
||||
#include "unicode/decimfmt.h"
|
||||
#include "unicode/fieldpos.h"
|
||||
#include "unicode/fpositer.h"
|
||||
#include "unicode/listformatter.h"
|
||||
#include "unicode/normalizer2.h"
|
||||
#include "unicode/numfmt.h"
|
||||
#include "unicode/reldatefmt.h"
|
||||
@ -220,56 +225,6 @@ Handle<String> IcuDateFieldIdToDateType(int32_t field_id, Isolate* isolate) {
|
||||
}
|
||||
}
|
||||
|
||||
MaybeHandle<JSObject> InnerAddElement(Isolate* isolate, Handle<JSArray> array,
|
||||
int index,
|
||||
Handle<String> field_type_string,
|
||||
const icu::UnicodeString& formatted,
|
||||
int32_t begin, int32_t end) {
|
||||
Factory* factory = isolate->factory();
|
||||
Handle<JSObject> element = factory->NewJSObject(isolate->object_function());
|
||||
Handle<String> value;
|
||||
JSObject::AddProperty(isolate, element, factory->type_string(),
|
||||
field_type_string, NONE);
|
||||
|
||||
icu::UnicodeString field(formatted.tempSubStringBetween(begin, end));
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, value,
|
||||
factory->NewStringFromTwoByte(Vector<const uint16_t>(
|
||||
reinterpret_cast<const uint16_t*>(field.getBuffer()),
|
||||
field.length())),
|
||||
JSObject);
|
||||
|
||||
JSObject::AddProperty(isolate, element, factory->value_string(), value, NONE);
|
||||
JSObject::AddDataElement(array, index, element, NONE);
|
||||
return element;
|
||||
}
|
||||
|
||||
Maybe<bool> AddElement(Isolate* isolate, Handle<JSArray> array, int index,
|
||||
Handle<String> field_type_string,
|
||||
const icu::UnicodeString& formatted, int32_t begin,
|
||||
int32_t end) {
|
||||
RETURN_ON_EXCEPTION_VALUE(
|
||||
isolate,
|
||||
InnerAddElement(isolate, array, index, field_type_string, formatted,
|
||||
begin, end),
|
||||
Nothing<bool>());
|
||||
return Just(true);
|
||||
}
|
||||
|
||||
Maybe<bool> AddElement(Isolate* isolate, Handle<JSArray> array, int index,
|
||||
Handle<String> field_type_string,
|
||||
const icu::UnicodeString& formatted, int32_t begin,
|
||||
int32_t end, Handle<String> name, Handle<String> value) {
|
||||
Handle<JSObject> element;
|
||||
ASSIGN_RETURN_ON_EXCEPTION_VALUE(
|
||||
isolate, element,
|
||||
InnerAddElement(isolate, array, index, field_type_string, formatted,
|
||||
begin, end),
|
||||
Nothing<bool>());
|
||||
JSObject::AddProperty(isolate, element, name, value, NONE);
|
||||
return Just(true);
|
||||
}
|
||||
|
||||
bool cmp_NumberFormatSpan(const NumberFormatSpan& a,
|
||||
const NumberFormatSpan& b) {
|
||||
// Regions that start earlier should be encountered earlier.
|
||||
@ -325,10 +280,12 @@ MaybeHandle<Object> FormatNumberToParts(Isolate* isolate,
|
||||
part.field_id == -1
|
||||
? isolate->factory()->literal_string()
|
||||
: IcuNumberFieldIdToNumberType(part.field_id, number, isolate);
|
||||
Maybe<bool> maybe_added_element =
|
||||
AddElement(isolate, result, index, field_type_string, formatted,
|
||||
part.begin_pos, part.end_pos);
|
||||
MAYBE_RETURN(maybe_added_element, MaybeHandle<Object>());
|
||||
Handle<String> substring;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, substring,
|
||||
Intl::ToString(isolate, formatted, part.begin_pos, part.end_pos),
|
||||
Object);
|
||||
Intl::AddElement(isolate, result, index, field_type_string, substring);
|
||||
++index;
|
||||
}
|
||||
JSObject::ValidateElements(*result);
|
||||
@ -355,30 +312,35 @@ MaybeHandle<Object> FormatDateToParts(Isolate* isolate, icu::DateFormat* format,
|
||||
|
||||
int index = 0;
|
||||
int32_t previous_end_pos = 0;
|
||||
Handle<String> substring;
|
||||
while (fp_iter.next(fp)) {
|
||||
int32_t begin_pos = fp.getBeginIndex();
|
||||
int32_t end_pos = fp.getEndIndex();
|
||||
|
||||
if (previous_end_pos < begin_pos) {
|
||||
Maybe<bool> maybe_added_element = AddElement(
|
||||
isolate, result, index, IcuDateFieldIdToDateType(-1, isolate),
|
||||
formatted, previous_end_pos, begin_pos);
|
||||
MAYBE_RETURN(maybe_added_element, MaybeHandle<Object>());
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, substring,
|
||||
Intl::ToString(isolate, formatted, previous_end_pos, begin_pos),
|
||||
Object);
|
||||
Intl::AddElement(isolate, result, index,
|
||||
IcuDateFieldIdToDateType(-1, isolate), substring);
|
||||
++index;
|
||||
}
|
||||
Maybe<bool> maybe_added_element =
|
||||
AddElement(isolate, result, index,
|
||||
IcuDateFieldIdToDateType(fp.getField(), isolate), formatted,
|
||||
begin_pos, end_pos);
|
||||
MAYBE_RETURN(maybe_added_element, MaybeHandle<Object>());
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, substring,
|
||||
Intl::ToString(isolate, formatted, begin_pos, end_pos), Object);
|
||||
Intl::AddElement(isolate, result, index,
|
||||
IcuDateFieldIdToDateType(fp.getField(), isolate),
|
||||
substring);
|
||||
previous_end_pos = end_pos;
|
||||
++index;
|
||||
}
|
||||
if (previous_end_pos < length) {
|
||||
Maybe<bool> maybe_added_element = AddElement(
|
||||
isolate, result, index, IcuDateFieldIdToDateType(-1, isolate),
|
||||
formatted, previous_end_pos, length);
|
||||
MAYBE_RETURN(maybe_added_element, MaybeHandle<Object>());
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, substring,
|
||||
Intl::ToString(isolate, formatted, previous_end_pos, length), Object);
|
||||
Intl::AddElement(isolate, result, index,
|
||||
IcuDateFieldIdToDateType(-1, isolate), substring);
|
||||
}
|
||||
JSObject::ValidateElements(*result);
|
||||
return result;
|
||||
@ -761,18 +723,16 @@ MaybeHandle<JSArray> GenerateRelativeTimeFormatParts(
|
||||
Handle<JSArray> array = factory->NewJSArray(0);
|
||||
int32_t found = formatted.indexOf(integer_part);
|
||||
|
||||
Handle<String> substring;
|
||||
if (found < 0) {
|
||||
// Cannot find the integer_part in the formatted.
|
||||
// Return [{'type': 'literal', 'value': formatted}]
|
||||
Maybe<bool> maybe_added_element =
|
||||
AddElement(isolate, array,
|
||||
0, // index
|
||||
factory->literal_string(), // field_type_string
|
||||
formatted,
|
||||
0, // begin
|
||||
formatted.length()); // end
|
||||
MAYBE_RETURN(maybe_added_element, MaybeHandle<JSArray>());
|
||||
|
||||
ASSIGN_RETURN_ON_EXCEPTION(isolate, substring,
|
||||
Intl::ToString(isolate, formatted), JSArray);
|
||||
Intl::AddElement(isolate, array,
|
||||
0, // index
|
||||
factory->literal_string(), // field_type_string
|
||||
substring);
|
||||
} else {
|
||||
// Found the formatted integer in the result.
|
||||
int index = 0;
|
||||
@ -781,40 +741,39 @@ MaybeHandle<JSArray> GenerateRelativeTimeFormatParts(
|
||||
// 'type': 'literal',
|
||||
// 'value': formatted.substring(0, found)})
|
||||
if (found > 0) {
|
||||
Maybe<bool> maybe_added_element =
|
||||
AddElement(isolate, array, index++,
|
||||
factory->literal_string(), // field_type_string
|
||||
formatted,
|
||||
0, // begin
|
||||
found); // end
|
||||
MAYBE_RETURN(maybe_added_element, MaybeHandle<JSArray>());
|
||||
ASSIGN_RETURN_ON_EXCEPTION(isolate, substring,
|
||||
Intl::ToString(isolate, formatted, 0, found),
|
||||
JSArray);
|
||||
Intl::AddElement(isolate, array, index++,
|
||||
factory->literal_string(), // field_type_string
|
||||
substring);
|
||||
}
|
||||
|
||||
// array.push({
|
||||
// 'type': 'integer',
|
||||
// 'value': formatted.substring(found, found + integer_part.length),
|
||||
// 'unit': unit})
|
||||
Maybe<bool> maybe_added_element =
|
||||
AddElement(isolate, array, index++,
|
||||
factory->integer_string(), // field_type_string
|
||||
formatted,
|
||||
found, // begin
|
||||
found + integer_part.length(), // end
|
||||
factory->unit_string(), unit);
|
||||
MAYBE_RETURN(maybe_added_element, MaybeHandle<JSArray>());
|
||||
ASSIGN_RETURN_ON_EXCEPTION(isolate, substring,
|
||||
Intl::ToString(isolate, formatted, found,
|
||||
found + integer_part.length()),
|
||||
JSArray);
|
||||
Intl::AddElement(isolate, array, index++,
|
||||
factory->integer_string(), // field_type_string
|
||||
substring, factory->unit_string(), unit);
|
||||
|
||||
// array.push({
|
||||
// 'type': 'literal',
|
||||
// 'value': formatted.substring(
|
||||
// found + integer_part.length, formatted.length)})
|
||||
if (found + integer_part.length() < formatted.length()) {
|
||||
Maybe<bool> maybe_added_element =
|
||||
AddElement(isolate, array, index,
|
||||
factory->literal_string(), // field_type_string
|
||||
formatted,
|
||||
found + integer_part.length(), // begin
|
||||
formatted.length()); // end
|
||||
MAYBE_RETURN(maybe_added_element, MaybeHandle<JSArray>());
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, substring,
|
||||
Intl::ToString(isolate, formatted, found + integer_part.length(),
|
||||
formatted.length()),
|
||||
JSArray);
|
||||
Intl::AddElement(isolate, array, index,
|
||||
factory->literal_string(), // field_type_string
|
||||
substring);
|
||||
}
|
||||
}
|
||||
return array;
|
||||
|
@ -73,6 +73,7 @@
|
||||
V(enqueue_string, "enqueue") \
|
||||
V(entries_string, "entries") \
|
||||
V(enumerable_string, "enumerable") \
|
||||
V(element_string, "element") \
|
||||
V(era_string, "era") \
|
||||
V(Error_string, "Error") \
|
||||
V(error_to_string, "[object Error]") \
|
||||
|
@ -274,6 +274,7 @@ class ErrorUtils : public AllStatic {
|
||||
"Derived ArrayBuffer constructor created a buffer which was too small") \
|
||||
T(ArrayBufferSpeciesThis, \
|
||||
"ArrayBuffer subclass returned this from species constructor") \
|
||||
T(ArrayItemNotType, "array %[%] is not type %") \
|
||||
T(AwaitNotInAsyncFunction, "await is only valid in async function") \
|
||||
T(AtomicsWaitNotAllowed, "Atomics.wait cannot be called in this context") \
|
||||
T(BadSortComparisonFunction, \
|
||||
@ -346,6 +347,7 @@ class ErrorUtils : public AllStatic {
|
||||
T(LocaleNotEmpty, \
|
||||
"First argument to Intl.Locale constructor can't be empty or missing") \
|
||||
T(LocaleBadParameters, "Incorrect locale information provided") \
|
||||
T(ListFormatBadParameters, "Incorrect ListFormat information provided") \
|
||||
T(MapperFunctionNonCallable, "flatMap mapper function is not callable") \
|
||||
T(MethodCalledOnWrongObject, \
|
||||
"Method % called on a non-object or on a wrong type of object.") \
|
||||
|
@ -700,6 +700,59 @@ void V8BreakIterator::DeleteBreakIterator(
|
||||
GlobalHandles::Destroy(reinterpret_cast<Object**>(data.GetParameter()));
|
||||
}
|
||||
|
||||
MaybeHandle<String> Intl::ToString(Isolate* isolate,
|
||||
const icu::UnicodeString& string) {
|
||||
return isolate->factory()->NewStringFromTwoByte(Vector<const uint16_t>(
|
||||
reinterpret_cast<const uint16_t*>(string.getBuffer()), string.length()));
|
||||
}
|
||||
|
||||
MaybeHandle<String> Intl::ToString(Isolate* isolate,
|
||||
const icu::UnicodeString& string,
|
||||
int32_t begin, int32_t end) {
|
||||
return Intl::ToString(isolate, string.tempSubStringBetween(begin, end));
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
Handle<JSObject> InnerAddElement(Isolate* isolate, Handle<JSArray> array,
|
||||
int index, Handle<String> field_type_string,
|
||||
Handle<String> value) {
|
||||
// let element = $array[$index] = {
|
||||
// type: $field_type_string,
|
||||
// value: $value
|
||||
// }
|
||||
// return element;
|
||||
Factory* factory = isolate->factory();
|
||||
Handle<JSObject> element = factory->NewJSObject(isolate->object_function());
|
||||
JSObject::AddProperty(isolate, element, factory->type_string(),
|
||||
field_type_string, NONE);
|
||||
|
||||
JSObject::AddProperty(isolate, element, factory->value_string(), value, NONE);
|
||||
JSObject::AddDataElement(array, index, element, NONE);
|
||||
return element;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void Intl::AddElement(Isolate* isolate, Handle<JSArray> array, int index,
|
||||
Handle<String> field_type_string, Handle<String> value) {
|
||||
// Same as $array[$index] = {type: $field_type_string, value: $value};
|
||||
InnerAddElement(isolate, array, index, field_type_string, value);
|
||||
}
|
||||
|
||||
void Intl::AddElement(Isolate* isolate, Handle<JSArray> array, int index,
|
||||
Handle<String> field_type_string, Handle<String> value,
|
||||
Handle<String> additional_property_name,
|
||||
Handle<String> additional_property_value) {
|
||||
// Same as $array[$index] = {
|
||||
// type: $field_type_string, value: $value,
|
||||
// $additional_property_name: $additional_property_value
|
||||
// }
|
||||
Handle<JSObject> element =
|
||||
InnerAddElement(isolate, array, index, field_type_string, value);
|
||||
JSObject::AddProperty(isolate, element, additional_property_name,
|
||||
additional_property_value, NONE);
|
||||
}
|
||||
// Build the shortened locale; eg, convert xx_Yyyy_ZZ to xx_ZZ.
|
||||
bool Intl::RemoveLocaleScriptTag(const std::string& icu_locale,
|
||||
std::string* locale_less_script) {
|
||||
|
@ -24,6 +24,7 @@ class Collator;
|
||||
class DecimalFormat;
|
||||
class PluralRules;
|
||||
class SimpleDateFormat;
|
||||
class UnicodeString;
|
||||
}
|
||||
|
||||
namespace v8 {
|
||||
@ -321,6 +322,31 @@ class Intl {
|
||||
|
||||
icu::Locale static CreateICULocale(Isolate* isolate,
|
||||
Handle<String> bcp47_locale_str);
|
||||
|
||||
// Helper funciton to convert a UnicodeString to a Handle<String>
|
||||
V8_WARN_UNUSED_RESULT static MaybeHandle<String> ToString(
|
||||
Isolate* isolate, const icu::UnicodeString& string);
|
||||
|
||||
// Helper function to convert a substring of UnicodeString to a Handle<String>
|
||||
V8_WARN_UNUSED_RESULT static MaybeHandle<String> ToString(
|
||||
Isolate* isolate, const icu::UnicodeString& string, int32_t begin,
|
||||
int32_t end);
|
||||
|
||||
// A helper function to implement formatToParts which add element to array as
|
||||
// $array[$index] = { type: $field_type_string, value: $value }
|
||||
static void AddElement(Isolate* isolate, Handle<JSArray> array, int index,
|
||||
Handle<String> field_type_string,
|
||||
Handle<String> value);
|
||||
|
||||
// A helper function to implement formatToParts which add element to array as
|
||||
// $array[$index] = {
|
||||
// type: $field_type_string, value: $value,
|
||||
// $additional_property_name: $additional_property_value
|
||||
// }
|
||||
static void AddElement(Isolate* isolate, Handle<JSArray> array, int index,
|
||||
Handle<String> field_type_string, Handle<String> value,
|
||||
Handle<String> additional_property_name,
|
||||
Handle<String> additional_property_value);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
@ -11,10 +11,12 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "src/elements.h"
|
||||
#include "src/heap/factory.h"
|
||||
#include "src/isolate.h"
|
||||
#include "src/objects-inl.h"
|
||||
#include "src/objects/intl-objects.h"
|
||||
#include "src/objects/js-array-inl.h"
|
||||
#include "src/objects/js-list-format-inl.h"
|
||||
#include "src/objects/managed.h"
|
||||
#include "unicode/listformatter.h"
|
||||
@ -246,5 +248,154 @@ Handle<String> JSListFormat::TypeAsString() const {
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// TODO(ftang) remove the following hack after icu::ListFormat support
|
||||
// FieldPosition.
|
||||
// This is a temporary workaround until icu::ListFormat support FieldPosition
|
||||
// It is inefficient and won't work correctly on the edge case that the input
|
||||
// contains fraction of the list pattern.
|
||||
// For example the following under English will mark the "an" incorrectly
|
||||
// since the formatted is "a, b, and an".
|
||||
// listFormat.formatToParts(["a", "b", "an"])
|
||||
// https://ssl.icu-project.org/trac/ticket/13754
|
||||
MaybeHandle<JSArray> GenerateListFormatParts(
|
||||
Isolate* isolate, const icu::UnicodeString& formatted,
|
||||
const icu::UnicodeString items[], int length) {
|
||||
Factory* factory = isolate->factory();
|
||||
int estimate_size = length * 2 + 1;
|
||||
Handle<JSArray> array = factory->NewJSArray(estimate_size);
|
||||
int index = 0;
|
||||
int last_pos = 0;
|
||||
for (int i = 0; i < length; i++) {
|
||||
int found = formatted.indexOf(items[i], last_pos);
|
||||
DCHECK_GE(found, 0);
|
||||
if (found > last_pos) {
|
||||
Handle<String> substring;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, substring,
|
||||
Intl::ToString(isolate, formatted, last_pos, found), JSArray);
|
||||
Intl::AddElement(isolate, array, index++, factory->literal_string(),
|
||||
substring);
|
||||
}
|
||||
last_pos = found + items[i].length();
|
||||
Handle<String> substring;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, substring, Intl::ToString(isolate, formatted, found, last_pos),
|
||||
JSArray);
|
||||
Intl::AddElement(isolate, array, index++, factory->element_string(),
|
||||
substring);
|
||||
}
|
||||
if (last_pos < formatted.length()) {
|
||||
Handle<String> substring;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
isolate, substring,
|
||||
Intl::ToString(isolate, formatted, last_pos, formatted.length()),
|
||||
JSArray);
|
||||
Intl::AddElement(isolate, array, index++, factory->literal_string(),
|
||||
substring);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
// Extract String from JSArray into array of UnicodeString
|
||||
Maybe<bool> ToUnicodeStringArray(Isolate* isolate, Handle<JSArray> array,
|
||||
icu::UnicodeString items[], uint32_t length) {
|
||||
Factory* factory = isolate->factory();
|
||||
// In general, ElementsAccessor::Get actually isn't guaranteed to give us the
|
||||
// elements in order. But given that it was created by a builtin we control,
|
||||
// it shouldn't be possible for it to be problematic. Add DCHECK to ensure
|
||||
// that.
|
||||
DCHECK(array->HasFastPackedElements());
|
||||
auto* accessor = array->GetElementsAccessor();
|
||||
DCHECK(length == accessor->NumberOfElements(*array));
|
||||
// ecma402 #sec-createpartsfromlist
|
||||
// 2. If list contains any element value such that Type(value) is not String,
|
||||
// throw a TypeError exception.
|
||||
//
|
||||
// Per spec it looks like we're supposed to throw a TypeError exception if the
|
||||
// item isn't already a string, rather than coercing to a string. Moreover,
|
||||
// the way the spec's written it looks like we're supposed to run through the
|
||||
// whole list to check that they're all strings before going further.
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
Handle<Object> item = accessor->Get(array, i);
|
||||
DCHECK(!item.is_null());
|
||||
if (!item->IsString()) {
|
||||
THROW_NEW_ERROR_RETURN_VALUE(
|
||||
isolate,
|
||||
NewTypeError(MessageTemplate::kArrayItemNotType,
|
||||
factory->NewStringFromStaticChars("list"),
|
||||
factory->NewNumber(i),
|
||||
factory->NewStringFromStaticChars("String")),
|
||||
Nothing<bool>());
|
||||
}
|
||||
}
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
Handle<String> string = Handle<String>::cast(accessor->Get(array, i));
|
||||
DisallowHeapAllocation no_gc;
|
||||
string = String::Flatten(isolate, string);
|
||||
std::unique_ptr<uc16[]> sap;
|
||||
items[i] =
|
||||
icu::UnicodeString(GetUCharBufferFromFlat(string->GetFlatContent(),
|
||||
&sap, string->length()),
|
||||
string->length());
|
||||
}
|
||||
return Just(true);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Maybe<bool> FormatListCommon(Isolate* isolate,
|
||||
Handle<JSListFormat> format_holder,
|
||||
Handle<JSArray> list,
|
||||
icu::UnicodeString& formatted, uint32_t* length,
|
||||
std::unique_ptr<icu::UnicodeString[]>& array) {
|
||||
DCHECK(!list->IsUndefined());
|
||||
|
||||
icu::ListFormatter* formatter =
|
||||
JSListFormat::UnpackFormatter(isolate, format_holder);
|
||||
CHECK_NOT_NULL(formatter);
|
||||
|
||||
*length = list->GetElementsAccessor()->NumberOfElements(*list);
|
||||
array.reset(new icu::UnicodeString[*length]);
|
||||
|
||||
// ecma402 #sec-createpartsfromlist
|
||||
// 2. If list contains any element value such that Type(value) is not String,
|
||||
// throw a TypeError exception.
|
||||
MAYBE_RETURN(ToUnicodeStringArray(isolate, list, array.get(), *length),
|
||||
Nothing<bool>());
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
formatter->format(array.get(), *length, formatted, status);
|
||||
DCHECK(U_SUCCESS(status));
|
||||
return Just(true);
|
||||
}
|
||||
|
||||
// ecma402 #sec-formatlist
|
||||
MaybeHandle<String> JSListFormat::FormatList(Isolate* isolate,
|
||||
Handle<JSListFormat> format_holder,
|
||||
Handle<JSArray> list) {
|
||||
icu::UnicodeString formatted;
|
||||
uint32_t length;
|
||||
std::unique_ptr<icu::UnicodeString[]> array;
|
||||
MAYBE_RETURN(
|
||||
FormatListCommon(isolate, format_holder, list, formatted, &length, array),
|
||||
Handle<String>());
|
||||
return Intl::ToString(isolate, formatted);
|
||||
}
|
||||
|
||||
// ecma42 #sec-formatlisttoparts
|
||||
MaybeHandle<JSArray> JSListFormat::FormatListToParts(
|
||||
Isolate* isolate, Handle<JSListFormat> format_holder,
|
||||
Handle<JSArray> list) {
|
||||
icu::UnicodeString formatted;
|
||||
uint32_t length;
|
||||
std::unique_ptr<icu::UnicodeString[]> array;
|
||||
MAYBE_RETURN(
|
||||
FormatListCommon(isolate, format_holder, list, formatted, &length, array),
|
||||
Handle<JSArray>());
|
||||
return GenerateListFormatParts(isolate, formatted, array.get(), length);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -39,6 +39,16 @@ class JSListFormat : public JSObject {
|
||||
static icu::ListFormatter* UnpackFormatter(
|
||||
Isolate* isolate, Handle<JSListFormat> list_format_holder);
|
||||
|
||||
// ecma402 #sec-formatlist
|
||||
V8_WARN_UNUSED_RESULT static MaybeHandle<String> FormatList(
|
||||
Isolate* isolate, Handle<JSListFormat> format_holder,
|
||||
Handle<JSArray> list);
|
||||
|
||||
// ecma42 #sec-formatlisttoparts
|
||||
V8_WARN_UNUSED_RESULT static MaybeHandle<JSArray> FormatListToParts(
|
||||
Isolate* isolate, Handle<JSListFormat> format_holder,
|
||||
Handle<JSArray> list);
|
||||
|
||||
Handle<String> StyleAsString() const;
|
||||
Handle<String> TypeAsString() const;
|
||||
|
||||
|
@ -20,7 +20,10 @@
|
||||
#include "src/messages.h"
|
||||
#include "src/objects/intl-objects-inl.h"
|
||||
#include "src/objects/intl-objects.h"
|
||||
#include "src/objects/js-array-inl.h"
|
||||
#include "src/objects/js-collator-inl.h"
|
||||
#include "src/objects/js-list-format-inl.h"
|
||||
#include "src/objects/js-list-format.h"
|
||||
#include "src/objects/js-plural-rules-inl.h"
|
||||
#include "src/objects/managed.h"
|
||||
#include "src/runtime/runtime-utils.h"
|
||||
@ -54,6 +57,26 @@
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
// ecma402 #sec-formatlist
|
||||
RUNTIME_FUNCTION(Runtime_FormatList) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(2, args.length());
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSListFormat, list_format, 0);
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSArray, list, 1);
|
||||
RETURN_RESULT_OR_FAILURE(
|
||||
isolate, JSListFormat::FormatList(isolate, list_format, list));
|
||||
}
|
||||
|
||||
// ecma402 #sec-formatlisttoparts
|
||||
RUNTIME_FUNCTION(Runtime_FormatListToParts) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(2, args.length());
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSListFormat, list_format, 0);
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSArray, list, 1);
|
||||
RETURN_RESULT_OR_FAILURE(
|
||||
isolate, JSListFormat::FormatListToParts(isolate, list_format, list));
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_GetNumberOption) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(5, args.length());
|
||||
|
@ -218,6 +218,8 @@ namespace internal {
|
||||
F(CurrencyDigits, 1, 1) \
|
||||
F(DateCacheVersion, 0, 1) \
|
||||
F(DefaultNumberOption, 5, 1) \
|
||||
F(FormatList, 2, 1) \
|
||||
F(FormatListToParts, 2, 1) \
|
||||
F(GetDefaultICULocale, 0, 1) \
|
||||
F(GetNumberOption, 5, 1) \
|
||||
F(InternalCompare, 3, 1) \
|
||||
|
@ -362,7 +362,7 @@ bytecodes: [
|
||||
B(TestTypeOf), U8(6),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), I16(151),
|
||||
B(Wide), B(LdaSmi), I16(153),
|
||||
B(Star), R(18),
|
||||
B(LdaConstant), U8(14),
|
||||
B(Star), R(19),
|
||||
|
@ -123,7 +123,7 @@ bytecodes: [
|
||||
B(TestTypeOf), U8(6),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), I16(151),
|
||||
B(Wide), B(LdaSmi), I16(153),
|
||||
B(Star), R(19),
|
||||
B(LdaConstant), U8(11),
|
||||
B(Star), R(20),
|
||||
@ -377,7 +377,7 @@ bytecodes: [
|
||||
B(TestTypeOf), U8(6),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), I16(151),
|
||||
B(Wide), B(LdaSmi), I16(153),
|
||||
B(Star), R(19),
|
||||
B(LdaConstant), U8(11),
|
||||
B(Star), R(20),
|
||||
@ -653,7 +653,7 @@ bytecodes: [
|
||||
B(TestTypeOf), U8(6),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), I16(151),
|
||||
B(Wide), B(LdaSmi), I16(153),
|
||||
B(Star), R(19),
|
||||
B(LdaConstant), U8(11),
|
||||
B(Star), R(20),
|
||||
@ -885,7 +885,7 @@ bytecodes: [
|
||||
B(TestTypeOf), U8(6),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), I16(151),
|
||||
B(Wide), B(LdaSmi), I16(153),
|
||||
B(Star), R(17),
|
||||
B(LdaConstant), U8(9),
|
||||
B(Star), R(18),
|
||||
|
@ -85,7 +85,7 @@ bytecodes: [
|
||||
B(TestTypeOf), U8(6),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), I16(151),
|
||||
B(Wide), B(LdaSmi), I16(153),
|
||||
B(Star), R(12),
|
||||
B(LdaConstant), U8(7),
|
||||
B(Star), R(13),
|
||||
@ -217,7 +217,7 @@ bytecodes: [
|
||||
B(TestTypeOf), U8(6),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), I16(151),
|
||||
B(Wide), B(LdaSmi), I16(153),
|
||||
B(Star), R(13),
|
||||
B(LdaConstant), U8(7),
|
||||
B(Star), R(14),
|
||||
@ -361,7 +361,7 @@ bytecodes: [
|
||||
B(TestTypeOf), U8(6),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), I16(151),
|
||||
B(Wide), B(LdaSmi), I16(153),
|
||||
B(Star), R(12),
|
||||
B(LdaConstant), U8(7),
|
||||
B(Star), R(13),
|
||||
@ -495,7 +495,7 @@ bytecodes: [
|
||||
B(TestTypeOf), U8(6),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), I16(151),
|
||||
B(Wide), B(LdaSmi), I16(153),
|
||||
B(Star), R(11),
|
||||
B(LdaConstant), U8(9),
|
||||
B(Star), R(12),
|
||||
|
@ -89,7 +89,7 @@ bytecodes: [
|
||||
B(TestTypeOf), U8(6),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), I16(151),
|
||||
B(Wide), B(LdaSmi), I16(153),
|
||||
B(Star), R(14),
|
||||
B(LdaConstant), U8(6),
|
||||
B(Star), R(15),
|
||||
@ -256,7 +256,7 @@ bytecodes: [
|
||||
B(TestTypeOf), U8(6),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), I16(151),
|
||||
B(Wide), B(LdaSmi), I16(153),
|
||||
B(Star), R(14),
|
||||
B(LdaConstant), U8(11),
|
||||
B(Star), R(15),
|
||||
@ -401,7 +401,7 @@ bytecodes: [
|
||||
B(TestTypeOf), U8(6),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), I16(151),
|
||||
B(Wide), B(LdaSmi), I16(153),
|
||||
B(Star), R(12),
|
||||
B(LdaConstant), U8(8),
|
||||
B(Star), R(13),
|
||||
@ -495,7 +495,7 @@ bytecodes: [
|
||||
B(JumpIfUndefined), U8(6),
|
||||
B(Ldar), R(6),
|
||||
B(JumpIfNotNull), U8(16),
|
||||
B(LdaSmi), I8(79),
|
||||
B(LdaSmi), I8(81),
|
||||
B(Star), R(18),
|
||||
B(LdaConstant), U8(4),
|
||||
B(Star), R(19),
|
||||
@ -550,7 +550,7 @@ bytecodes: [
|
||||
B(TestTypeOf), U8(6),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), I16(151),
|
||||
B(Wide), B(LdaSmi), I16(153),
|
||||
B(Star), R(17),
|
||||
B(LdaConstant), U8(8),
|
||||
B(Star), R(18),
|
||||
@ -697,7 +697,7 @@ bytecodes: [
|
||||
B(TestTypeOf), U8(6),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), I16(151),
|
||||
B(Wide), B(LdaSmi), I16(153),
|
||||
B(Star), R(15),
|
||||
B(LdaConstant), U8(9),
|
||||
B(Star), R(16),
|
||||
@ -859,7 +859,7 @@ bytecodes: [
|
||||
B(TestTypeOf), U8(6),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), I16(151),
|
||||
B(Wide), B(LdaSmi), I16(153),
|
||||
B(Star), R(14),
|
||||
B(LdaConstant), U8(12),
|
||||
B(Star), R(15),
|
||||
@ -1007,7 +1007,7 @@ bytecodes: [
|
||||
B(TestTypeOf), U8(6),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), I16(151),
|
||||
B(Wide), B(LdaSmi), I16(153),
|
||||
B(Star), R(20),
|
||||
B(LdaConstant), U8(6),
|
||||
B(Star), R(21),
|
||||
@ -1218,7 +1218,7 @@ bytecodes: [
|
||||
B(TestTypeOf), U8(6),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), I16(151),
|
||||
B(Wide), B(LdaSmi), I16(153),
|
||||
B(Star), R(19),
|
||||
B(LdaConstant), U8(7),
|
||||
B(Star), R(20),
|
||||
|
@ -203,7 +203,7 @@ bytecodes: [
|
||||
B(TestTypeOf), U8(6),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(18),
|
||||
B(Wide), B(LdaSmi), I16(151),
|
||||
B(Wide), B(LdaSmi), I16(153),
|
||||
B(Star), R(14),
|
||||
B(LdaConstant), U8(13),
|
||||
B(Star), R(15),
|
||||
|
@ -229,7 +229,7 @@ bytecodes: [
|
||||
B(JumpIfUndefined), U8(6),
|
||||
B(Ldar), R(3),
|
||||
B(JumpIfNotNull), U8(16),
|
||||
B(LdaSmi), I8(79),
|
||||
B(LdaSmi), I8(81),
|
||||
B(Star), R(4),
|
||||
B(LdaConstant), U8(1),
|
||||
B(Star), R(5),
|
||||
|
119
test/intl/list-format/format-en.js
Normal file
119
test/intl/list-format/format-en.js
Normal file
@ -0,0 +1,119 @@
|
||||
// Copyright 2018 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --harmony-intl-list-format
|
||||
|
||||
// The following test are not part of the comformance. Just some output in
|
||||
// English to verify the format does return something reasonable for English.
|
||||
// It may be changed when we update the CLDR data.
|
||||
// NOTE: These are UNSPECIFIED behavior in
|
||||
// http://tc39.github.io/proposal-intl-list-time/
|
||||
|
||||
let enLongConjunction = new Intl.ListFormat(
|
||||
["en"], {style: "long", type: 'conjunction'});
|
||||
|
||||
assertEquals('', enLongConjunction.format());
|
||||
assertEquals('', enLongConjunction.format([]));
|
||||
assertEquals('a', enLongConjunction.format(['a']));
|
||||
assertEquals('b', enLongConjunction.format(['b']));
|
||||
assertEquals('a and b', enLongConjunction.format(['a', 'b']));
|
||||
assertEquals('a, b, and c', enLongConjunction.format(['a', 'b', 'c']));
|
||||
assertEquals('a, b, c, and d', enLongConjunction.format(['a', 'b', 'c', 'd']));
|
||||
assertEquals('a, b, c, d, and and', enLongConjunction.format(['a', 'b', 'c', 'd', 'and']));
|
||||
|
||||
let enLongDisjunction = new Intl.ListFormat(
|
||||
["en"], {style: "long", type: 'disjunction'});
|
||||
|
||||
assertEquals('', enLongDisjunction.format());
|
||||
assertEquals('', enLongDisjunction.format([]));
|
||||
assertEquals('a', enLongDisjunction.format(['a']));
|
||||
assertEquals('b', enLongDisjunction.format(['b']));
|
||||
assertEquals('a or b', enLongDisjunction.format(['a', 'b']));
|
||||
assertEquals('a, b, or c', enLongDisjunction.format(['a', 'b', 'c']));
|
||||
assertEquals('a, b, c, or d', enLongDisjunction.format(['a', 'b', 'c', 'd']));
|
||||
assertEquals('a, b, c, d, or or', enLongDisjunction.format(['a', 'b', 'c', 'd', 'or']));
|
||||
|
||||
let enLongUnit = new Intl.ListFormat(
|
||||
["en"], {style: "long", type: 'unit'});
|
||||
|
||||
assertEquals('', enLongUnit.format());
|
||||
assertEquals('', enLongUnit.format([]));
|
||||
assertEquals('a', enLongUnit.format(['a']));
|
||||
assertEquals('b', enLongUnit.format(['b']));
|
||||
assertEquals('a, b', enLongUnit.format(['a', 'b']));
|
||||
assertEquals('a, b, c', enLongUnit.format(['a', 'b', 'c']));
|
||||
assertEquals('a, b, c, d', enLongUnit.format(['a', 'b', 'c', 'd']));
|
||||
assertEquals('a, b, c, d, or', enLongUnit.format(['a', 'b', 'c', 'd', 'or']));
|
||||
|
||||
let enShortConjunction = new Intl.ListFormat(
|
||||
["en"], {style: "short", type: 'conjunction'});
|
||||
|
||||
assertEquals('', enShortConjunction.format());
|
||||
assertEquals('', enShortConjunction.format([]));
|
||||
assertEquals('a', enShortConjunction.format(['a']));
|
||||
assertEquals('b', enShortConjunction.format(['b']));
|
||||
assertEquals('a and b', enShortConjunction.format(['a', 'b']));
|
||||
assertEquals('a, b, and c', enShortConjunction.format(['a', 'b', 'c']));
|
||||
assertEquals('a, b, c, and d', enShortConjunction.format(['a', 'b', 'c', 'd']));
|
||||
assertEquals('a, b, c, d, and and', enShortConjunction.format(['a', 'b', 'c', 'd', 'and']));
|
||||
|
||||
let enShortDisjunction = new Intl.ListFormat(
|
||||
["en"], {style: "short", type: 'disjunction'});
|
||||
|
||||
assertEquals('', enShortDisjunction.format());
|
||||
assertEquals('', enShortDisjunction.format([]));
|
||||
assertEquals('a', enShortDisjunction.format(['a']));
|
||||
assertEquals('b', enShortDisjunction.format(['b']));
|
||||
assertEquals('a or b', enShortDisjunction.format(['a', 'b']));
|
||||
assertEquals('a, b, or c', enShortDisjunction.format(['a', 'b', 'c']));
|
||||
assertEquals('a, b, c, or d', enShortDisjunction.format(['a', 'b', 'c', 'd']));
|
||||
assertEquals('a, b, c, d, or or', enShortDisjunction.format(['a', 'b', 'c', 'd', 'or']));
|
||||
|
||||
let enShortUnit = new Intl.ListFormat(
|
||||
["en"], {style: "short", type: 'unit'});
|
||||
|
||||
assertEquals('', enShortUnit.format());
|
||||
assertEquals('', enShortUnit.format([]));
|
||||
assertEquals('a', enShortUnit.format(['a']));
|
||||
assertEquals('b', enShortUnit.format(['b']));
|
||||
assertEquals('a, b', enShortUnit.format(['a', 'b']));
|
||||
assertEquals('a, b, c', enShortUnit.format(['a', 'b', 'c']));
|
||||
assertEquals('a, b, c, d', enShortUnit.format(['a', 'b', 'c', 'd']));
|
||||
assertEquals('a, b, c, d, or', enShortUnit.format(['a', 'b', 'c', 'd', 'or']));
|
||||
|
||||
let enNarrowConjunction = new Intl.ListFormat(
|
||||
["en"], {style: "narrow", type: 'conjunction'});
|
||||
|
||||
assertEquals('', enNarrowConjunction.format());
|
||||
assertEquals('', enNarrowConjunction.format([]));
|
||||
assertEquals('a', enNarrowConjunction.format(['a']));
|
||||
assertEquals('b', enNarrowConjunction.format(['b']));
|
||||
assertEquals('a and b', enNarrowConjunction.format(['a', 'b']));
|
||||
assertEquals('a, b, and c', enNarrowConjunction.format(['a', 'b', 'c']));
|
||||
assertEquals('a, b, c, and d', enNarrowConjunction.format(['a', 'b', 'c', 'd']));
|
||||
assertEquals('a, b, c, d, and and', enNarrowConjunction.format(['a', 'b', 'c', 'd', 'and']));
|
||||
|
||||
let enNarrowDisjunction = new Intl.ListFormat(
|
||||
["en"], {style: "narrow", type: 'disjunction'});
|
||||
|
||||
assertEquals('', enNarrowDisjunction.format());
|
||||
assertEquals('', enNarrowDisjunction.format([]));
|
||||
assertEquals('a', enNarrowDisjunction.format(['a']));
|
||||
assertEquals('b', enNarrowDisjunction.format(['b']));
|
||||
assertEquals('a or b', enNarrowDisjunction.format(['a', 'b']));
|
||||
assertEquals('a, b, or c', enNarrowDisjunction.format(['a', 'b', 'c']));
|
||||
assertEquals('a, b, c, or d', enNarrowDisjunction.format(['a', 'b', 'c', 'd']));
|
||||
assertEquals('a, b, c, d, or or', enNarrowDisjunction.format(['a', 'b', 'c', 'd', 'or']));
|
||||
|
||||
let enNarrowUnit = new Intl.ListFormat(
|
||||
["en"], {style: "narrow", type: 'unit'});
|
||||
|
||||
assertEquals('', enNarrowUnit.format());
|
||||
assertEquals('', enNarrowUnit.format([]));
|
||||
assertEquals('a', enNarrowUnit.format(['a']));
|
||||
assertEquals('b', enNarrowUnit.format(['b']));
|
||||
assertEquals('a b', enNarrowUnit.format(['a', 'b']));
|
||||
assertEquals('a b c', enNarrowUnit.format(['a', 'b', 'c']));
|
||||
assertEquals('a b c d', enNarrowUnit.format(['a', 'b', 'c', 'd']));
|
||||
assertEquals('a b c d or', enNarrowUnit.format(['a', 'b', 'c', 'd', 'or']));
|
92
test/intl/list-format/format-to-parts.js
Normal file
92
test/intl/list-format/format-to-parts.js
Normal file
@ -0,0 +1,92 @@
|
||||
// Copyright 2018 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --harmony-intl-list-format
|
||||
|
||||
function assertListFormat(listFormat, input) {
|
||||
var result;
|
||||
try {
|
||||
result = listFormat.formatToParts(input);
|
||||
} catch (e) {
|
||||
fail('should not throw exception ' + e);
|
||||
}
|
||||
assertTrue(Array.isArray(result));
|
||||
if (input) {
|
||||
assertTrue(result.length >= input.length * 2 - 1);
|
||||
for (var i = 0, j = 0; i < result.length; i++) {
|
||||
assertEquals('string', typeof result[i].value);
|
||||
assertEquals('string', typeof result[i].type);
|
||||
assertTrue(result[i].type == 'literal' || result[i].type == 'element');
|
||||
if (result[i].type == 'element') {
|
||||
assertEquals(String(input[j++]), result[i].value);
|
||||
if (i - 1 >= 0) {
|
||||
assertEquals('literal', result[i - 1].type);
|
||||
}
|
||||
if (i + 1 < result.length) {
|
||||
assertEquals('literal', result[i + 1].type);
|
||||
}
|
||||
}
|
||||
if (result[i].type == 'literal') {
|
||||
assertTrue(result[i].value.length > 0);
|
||||
if (i - 1 >= 0) {
|
||||
assertEquals('element', result[i - 1].type);
|
||||
}
|
||||
if (i + 1 < result.length) {
|
||||
assertEquals('element', result[i + 1].type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function testFormatter(listFormat) {
|
||||
|
||||
assertListFormat(listFormat, []);
|
||||
assertListFormat(listFormat, undefined);
|
||||
assertListFormat(listFormat, ['1']);
|
||||
assertListFormat(listFormat, ['a']);
|
||||
assertListFormat(listFormat, ['1', 'b']);
|
||||
assertListFormat(listFormat, ['1', 'b', '3']);
|
||||
assertListFormat(listFormat, ['a', 'b']);
|
||||
assertListFormat(listFormat, ['a', 'b', 'c']);
|
||||
assertListFormat(listFormat, ['a', 'b', 'c', 'd']);
|
||||
assertListFormat(listFormat, ['作者', '譚永鋒', '1', (new Date()).toString()]);
|
||||
assertListFormat(listFormat, ['作者', '譚永鋒', '1', 'b', '3']);
|
||||
// Tricky cases
|
||||
assertListFormat(listFormat, [' ', 'b', 'c', 'and']);
|
||||
assertListFormat(listFormat, [' ', 'b', 'c', 'or']);
|
||||
assertListFormat(listFormat, ['and']);
|
||||
assertListFormat(listFormat, ['or']);
|
||||
|
||||
assertThrows(() => listFormat.formatToParts(null), TypeError);
|
||||
assertThrows(() => listFormat.formatToParts([new Date()]), TypeError);
|
||||
assertThrows(() => listFormat.formatToParts([1]), TypeError);
|
||||
assertThrows(() => listFormat.formatToParts([1, 'b']), TypeError);
|
||||
assertThrows(() => listFormat.formatToParts([1, 'b', 3]), TypeError);
|
||||
assertThrows(() => listFormat.formatToParts([[3, 4]]), TypeError);
|
||||
assertThrows(() => listFormat.formatToParts([undefined, 'world']), TypeError);
|
||||
assertThrows(() => listFormat.formatToParts(['hello', undefined]), TypeError);
|
||||
assertThrows(() => listFormat.formatToParts([undefined]), TypeError);
|
||||
assertThrows(() => listFormat.formatToParts([null, 'world']), TypeError);
|
||||
assertThrows(() => listFormat.formatToParts(['hello', null]), TypeError);
|
||||
assertThrows(() => listFormat.formatToParts([null]), TypeError);
|
||||
|
||||
}
|
||||
testFormatter(new Intl.ListFormat());
|
||||
testFormatter(new Intl.ListFormat(["en"]));
|
||||
testFormatter(new Intl.ListFormat(["en"], {style: 'long'}));
|
||||
testFormatter(new Intl.ListFormat(["en"], {style: 'short'}));
|
||||
testFormatter(new Intl.ListFormat(["en"], {style: 'narrow'}));
|
||||
testFormatter(new Intl.ListFormat(["en"], {type: 'conjunction'}));
|
||||
testFormatter(new Intl.ListFormat(["en"], {type: 'disjunction'}));
|
||||
testFormatter(new Intl.ListFormat(["en"], {type: 'unit'}));
|
||||
testFormatter(new Intl.ListFormat(["en"], {style: 'long', type: 'conjunction'}));
|
||||
testFormatter(new Intl.ListFormat(["en"], {style: 'short', type: 'conjunction'}));
|
||||
testFormatter(new Intl.ListFormat(["en"], {style: 'narrow', type: 'conjunction'}));
|
||||
testFormatter(new Intl.ListFormat(["en"], {style: 'long', type: 'disjunction'}));
|
||||
testFormatter(new Intl.ListFormat(["en"], {style: 'short', type: 'disjunction'}));
|
||||
testFormatter(new Intl.ListFormat(["en"], {style: 'narrow', type: 'disjunction'}));
|
||||
testFormatter(new Intl.ListFormat(["en"], {style: 'long', type: 'unit'}));
|
||||
testFormatter(new Intl.ListFormat(["en"], {style: 'short', type: 'unit'}));
|
||||
testFormatter(new Intl.ListFormat(["en"], {style: 'narrow', type: 'unit'}));
|
63
test/intl/list-format/format.js
Normal file
63
test/intl/list-format/format.js
Normal file
@ -0,0 +1,63 @@
|
||||
// Copyright 2018 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --harmony-intl-list-format
|
||||
|
||||
function assertListFormat(listFormat, input) {
|
||||
try {
|
||||
let result = listFormat.format(input);
|
||||
assertEquals('string', typeof result);
|
||||
if (input) {
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
assertTrue(result.indexOf(input[i]) >= 0);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
fail('should not throw exception ' + e);
|
||||
}
|
||||
}
|
||||
|
||||
function testFormatter(listFormat) {
|
||||
assertListFormat(listFormat, []);
|
||||
assertListFormat(listFormat, undefined);
|
||||
assertListFormat(listFormat, ['1']);
|
||||
assertListFormat(listFormat, ['a']);
|
||||
assertListFormat(listFormat, ['1', 'b']);
|
||||
assertListFormat(listFormat, ['1', 'b', '3']);
|
||||
assertListFormat(listFormat, ['a', 'b']);
|
||||
assertListFormat(listFormat, ['a', 'b', 'c']);
|
||||
assertListFormat(listFormat, ['a', 'b', 'c', 'd']);
|
||||
assertListFormat(listFormat, ['作者', '譚永鋒', '1', (new Date()).toString()]);
|
||||
assertListFormat(listFormat, ['作者', '譚永鋒', '1', 'b', '3']);
|
||||
|
||||
assertThrows(() => listFormat.format(null), TypeError);
|
||||
assertThrows(() => listFormat.format([new Date()]), TypeError);
|
||||
assertThrows(() => listFormat.format([1]), TypeError);
|
||||
assertThrows(() => listFormat.format([1, 'b']), TypeError);
|
||||
assertThrows(() => listFormat.format([1, 'b', 3]), TypeError);
|
||||
assertThrows(() => listFormat.format([[3, 4]]), TypeError);
|
||||
assertThrows(() => listFormat.format([undefined, 'world']), TypeError);
|
||||
assertThrows(() => listFormat.format(['hello', undefined]), TypeError);
|
||||
assertThrows(() => listFormat.format([undefined]), TypeError);
|
||||
assertThrows(() => listFormat.format([null, 'world']), TypeError);
|
||||
assertThrows(() => listFormat.format(['hello', null]), TypeError);
|
||||
assertThrows(() => listFormat.format([null]), TypeError);
|
||||
}
|
||||
testFormatter(new Intl.ListFormat());
|
||||
testFormatter(new Intl.ListFormat(["en"]));
|
||||
testFormatter(new Intl.ListFormat(["en"], {style: 'long'}));
|
||||
testFormatter(new Intl.ListFormat(["en"], {style: 'short'}));
|
||||
testFormatter(new Intl.ListFormat(["en"], {style: 'narrow'}));
|
||||
testFormatter(new Intl.ListFormat(["en"], {type: 'conjunction'}));
|
||||
testFormatter(new Intl.ListFormat(["en"], {type: 'disjunction'}));
|
||||
testFormatter(new Intl.ListFormat(["en"], {type: 'unit'}));
|
||||
testFormatter(new Intl.ListFormat(["en"], {style: 'long', type: 'conjunction'}));
|
||||
testFormatter(new Intl.ListFormat(["en"], {style: 'short', type: 'conjunction'}));
|
||||
testFormatter(new Intl.ListFormat(["en"], {style: 'narrow', type: 'conjunction'}));
|
||||
testFormatter(new Intl.ListFormat(["en"], {style: 'long', type: 'disjunction'}));
|
||||
testFormatter(new Intl.ListFormat(["en"], {style: 'short', type: 'disjunction'}));
|
||||
testFormatter(new Intl.ListFormat(["en"], {style: 'narrow', type: 'disjunction'}));
|
||||
testFormatter(new Intl.ListFormat(["en"], {style: 'long', type: 'unit'}));
|
||||
testFormatter(new Intl.ListFormat(["en"], {style: 'short', type: 'unit'}));
|
||||
testFormatter(new Intl.ListFormat(["en"], {style: 'narrow', type: 'unit'}));
|
157
test/intl/list-format/formatToParts-zh.js
Normal file
157
test/intl/list-format/formatToParts-zh.js
Normal file
@ -0,0 +1,157 @@
|
||||
// Copyright 2018 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --harmony-intl-list-format
|
||||
|
||||
// The following test are not part of the comformance. Just some output in
|
||||
// Chinese to verify the format does return something reasonable for Chinese.
|
||||
// It may be changed when we update the CLDR data.
|
||||
// NOTE: These are UNSPECIFIED behavior in
|
||||
// http://tc39.github.io/proposal-intl-list-time/
|
||||
|
||||
let zhLongConjunction = new Intl.ListFormat(
|
||||
["zh"], {style: "long", type: 'conjunction'});
|
||||
|
||||
var parts;
|
||||
parts = zhLongConjunction.formatToParts();
|
||||
assertEquals(0, parts.length);
|
||||
|
||||
parts = zhLongConjunction.formatToParts([]);
|
||||
assertEquals(0, parts.length);
|
||||
|
||||
parts = zhLongConjunction.formatToParts(['譚永鋒']);
|
||||
assertEquals(1, parts.length);
|
||||
assertEquals('譚永鋒', parts[0].value);
|
||||
assertEquals('element', parts[0].type);
|
||||
|
||||
parts = zhLongConjunction.formatToParts(['譚永鋒', '劉新宇']);
|
||||
assertEquals(3, parts.length);
|
||||
assertEquals('譚永鋒', parts[0].value);
|
||||
assertEquals('element', parts[0].type);
|
||||
assertEquals('和', parts[1].value);
|
||||
assertEquals('literal', parts[1].type);
|
||||
assertEquals('劉新宇', parts[2].value);
|
||||
assertEquals('element', parts[2].type);
|
||||
|
||||
parts = zhLongConjunction.formatToParts(['黄子容', '譚永鋒', '劉新宇']);
|
||||
assertEquals(5, parts.length);
|
||||
assertEquals('黄子容', parts[0].value);
|
||||
assertEquals('element', parts[0].type);
|
||||
assertEquals('、', parts[1].value);
|
||||
assertEquals('literal', parts[1].type);
|
||||
assertEquals('譚永鋒', parts[2].value);
|
||||
assertEquals('element', parts[2].type);
|
||||
assertEquals('和', parts[3].value);
|
||||
assertEquals('literal', parts[3].type);
|
||||
assertEquals('劉新宇', parts[4].value);
|
||||
assertEquals('element', parts[4].type);
|
||||
|
||||
parts = zhLongConjunction.formatToParts(['黄子容', '譚永鋒', '劉新宇', '朱君毅']);
|
||||
assertEquals(7, parts.length);
|
||||
assertEquals('黄子容', parts[0].value);
|
||||
assertEquals('element', parts[0].type);
|
||||
assertEquals('、', parts[1].value);
|
||||
assertEquals('literal', parts[1].type);
|
||||
assertEquals('譚永鋒', parts[2].value);
|
||||
assertEquals('element', parts[2].type);
|
||||
assertEquals('、', parts[3].value);
|
||||
assertEquals('literal', parts[3].type);
|
||||
assertEquals('劉新宇', parts[4].value);
|
||||
assertEquals('element', parts[4].type);
|
||||
assertEquals('和', parts[5].value);
|
||||
assertEquals('literal', parts[5].type);
|
||||
assertEquals('朱君毅', parts[6].value);
|
||||
assertEquals('element', parts[6].type);
|
||||
|
||||
let zhShortDisjunction = new Intl.ListFormat(
|
||||
["zh"], {style: "short", type: 'disjunction'});
|
||||
parts = zhShortDisjunction.formatToParts();
|
||||
assertEquals(0, parts.length);
|
||||
|
||||
parts = zhShortDisjunction.formatToParts([]);
|
||||
assertEquals(0, parts.length);
|
||||
|
||||
parts = zhShortDisjunction.formatToParts(['譚永鋒']);
|
||||
assertEquals(1, parts.length);
|
||||
assertEquals('譚永鋒', parts[0].value);
|
||||
assertEquals('element', parts[0].type);
|
||||
|
||||
parts = zhShortDisjunction.formatToParts(['譚永鋒', '劉新宇']);
|
||||
assertEquals(3, parts.length);
|
||||
assertEquals('譚永鋒', parts[0].value);
|
||||
assertEquals('element', parts[0].type);
|
||||
assertEquals('或', parts[1].value);
|
||||
assertEquals('literal', parts[1].type);
|
||||
assertEquals('劉新宇', parts[2].value);
|
||||
assertEquals('element', parts[2].type);
|
||||
|
||||
parts = zhShortDisjunction.formatToParts(['黄子容', '譚永鋒', '劉新宇']);
|
||||
assertEquals(5, parts.length);
|
||||
assertEquals('黄子容', parts[0].value);
|
||||
assertEquals('element', parts[0].type);
|
||||
assertEquals('、', parts[1].value);
|
||||
assertEquals('literal', parts[1].type);
|
||||
assertEquals('譚永鋒', parts[2].value);
|
||||
assertEquals('element', parts[2].type);
|
||||
assertEquals('或', parts[3].value);
|
||||
assertEquals('literal', parts[3].type);
|
||||
assertEquals('劉新宇', parts[4].value);
|
||||
assertEquals('element', parts[4].type);
|
||||
|
||||
parts = zhShortDisjunction.formatToParts(['黄子容', '譚永鋒', '劉新宇', '朱君毅']);
|
||||
assertEquals(7, parts.length);
|
||||
assertEquals('黄子容', parts[0].value);
|
||||
assertEquals('element', parts[0].type);
|
||||
assertEquals('、', parts[1].value);
|
||||
assertEquals('literal', parts[1].type);
|
||||
assertEquals('譚永鋒', parts[2].value);
|
||||
assertEquals('element', parts[2].type);
|
||||
assertEquals('、', parts[3].value);
|
||||
assertEquals('literal', parts[3].type);
|
||||
assertEquals('劉新宇', parts[4].value);
|
||||
assertEquals('element', parts[4].type);
|
||||
assertEquals('或', parts[5].value);
|
||||
assertEquals('literal', parts[5].type);
|
||||
assertEquals('朱君毅', parts[6].value);
|
||||
|
||||
let zhNarrowUnit = new Intl.ListFormat(
|
||||
["zh"], {style: "narrow", type: 'unit'});
|
||||
|
||||
parts = zhNarrowUnit.formatToParts();
|
||||
assertEquals(0, parts.length);
|
||||
|
||||
parts = zhNarrowUnit.formatToParts([]);
|
||||
assertEquals(0, parts.length);
|
||||
|
||||
parts = zhNarrowUnit.formatToParts(['3英哩']);
|
||||
assertEquals(1, parts.length);
|
||||
assertEquals('3英哩', parts[0].value);
|
||||
assertEquals('element', parts[0].type);
|
||||
|
||||
parts = zhNarrowUnit.formatToParts(['3英哩', '4碼']);
|
||||
assertEquals(2, parts.length);
|
||||
assertEquals('3英哩', parts[0].value);
|
||||
assertEquals('element', parts[0].type);
|
||||
assertEquals('4碼', parts[1].value);
|
||||
assertEquals('element', parts[1].type);
|
||||
|
||||
parts = zhNarrowUnit.formatToParts(['3英哩', '4碼', '5英尺']);
|
||||
assertEquals(3, parts.length);
|
||||
assertEquals('3英哩', parts[0].value);
|
||||
assertEquals('element', parts[0].type);
|
||||
assertEquals('4碼', parts[1].value);
|
||||
assertEquals('element', parts[1].type);
|
||||
assertEquals('5英尺', parts[2].value);
|
||||
assertEquals('element', parts[2].type);
|
||||
|
||||
parts = zhNarrowUnit.formatToParts(['3英哩', '4碼', '5英尺','7英吋']);
|
||||
assertEquals(4, parts.length);
|
||||
assertEquals('3英哩', parts[0].value);
|
||||
assertEquals('element', parts[0].type);
|
||||
assertEquals('4碼', parts[1].value);
|
||||
assertEquals('element', parts[1].type);
|
||||
assertEquals('5英尺', parts[2].value);
|
||||
assertEquals('element', parts[2].type);
|
||||
assertEquals('7英吋', parts[3].value);
|
||||
assertEquals('element', parts[3].type);
|
@ -285,33 +285,33 @@ KNOWN_MAPS = {
|
||||
("RO_SPACE", 0x047c1): (171, "Tuple2Map"),
|
||||
("RO_SPACE", 0x04af9): (161, "InterceptorInfoMap"),
|
||||
("RO_SPACE", 0x04bf1): (169, "ScriptMap"),
|
||||
("RO_SPACE", 0x09ae1): (154, "AccessorInfoMap"),
|
||||
("RO_SPACE", 0x09b31): (153, "AccessCheckInfoMap"),
|
||||
("RO_SPACE", 0x09b81): (155, "AccessorPairMap"),
|
||||
("RO_SPACE", 0x09bd1): (156, "AliasedArgumentsEntryMap"),
|
||||
("RO_SPACE", 0x09c21): (157, "AllocationMementoMap"),
|
||||
("RO_SPACE", 0x09c71): (158, "AsyncGeneratorRequestMap"),
|
||||
("RO_SPACE", 0x09cc1): (159, "DebugInfoMap"),
|
||||
("RO_SPACE", 0x09d11): (160, "FunctionTemplateInfoMap"),
|
||||
("RO_SPACE", 0x09d61): (162, "InterpreterDataMap"),
|
||||
("RO_SPACE", 0x09db1): (163, "ModuleInfoEntryMap"),
|
||||
("RO_SPACE", 0x09e01): (164, "ModuleMap"),
|
||||
("RO_SPACE", 0x09e51): (165, "ObjectTemplateInfoMap"),
|
||||
("RO_SPACE", 0x09ea1): (166, "PromiseCapabilityMap"),
|
||||
("RO_SPACE", 0x09ef1): (167, "PromiseReactionMap"),
|
||||
("RO_SPACE", 0x09f41): (168, "PrototypeInfoMap"),
|
||||
("RO_SPACE", 0x09f91): (170, "StackFrameInfoMap"),
|
||||
("RO_SPACE", 0x09fe1): (172, "Tuple3Map"),
|
||||
("RO_SPACE", 0x0a031): (173, "ArrayBoilerplateDescriptionMap"),
|
||||
("RO_SPACE", 0x0a081): (174, "WasmDebugInfoMap"),
|
||||
("RO_SPACE", 0x0a0d1): (175, "WasmExportedFunctionDataMap"),
|
||||
("RO_SPACE", 0x0a121): (176, "CallableTaskMap"),
|
||||
("RO_SPACE", 0x0a171): (177, "CallbackTaskMap"),
|
||||
("RO_SPACE", 0x0a1c1): (178, "PromiseFulfillReactionJobTaskMap"),
|
||||
("RO_SPACE", 0x0a211): (179, "PromiseRejectReactionJobTaskMap"),
|
||||
("RO_SPACE", 0x0a261): (180, "PromiseResolveThenableJobTaskMap"),
|
||||
("RO_SPACE", 0x0a2b1): (181, "AllocationSiteMap"),
|
||||
("RO_SPACE", 0x0a301): (181, "AllocationSiteMap"),
|
||||
("RO_SPACE", 0x09b79): (154, "AccessorInfoMap"),
|
||||
("RO_SPACE", 0x09bc9): (153, "AccessCheckInfoMap"),
|
||||
("RO_SPACE", 0x09c19): (155, "AccessorPairMap"),
|
||||
("RO_SPACE", 0x09c69): (156, "AliasedArgumentsEntryMap"),
|
||||
("RO_SPACE", 0x09cb9): (157, "AllocationMementoMap"),
|
||||
("RO_SPACE", 0x09d09): (158, "AsyncGeneratorRequestMap"),
|
||||
("RO_SPACE", 0x09d59): (159, "DebugInfoMap"),
|
||||
("RO_SPACE", 0x09da9): (160, "FunctionTemplateInfoMap"),
|
||||
("RO_SPACE", 0x09df9): (162, "InterpreterDataMap"),
|
||||
("RO_SPACE", 0x09e49): (163, "ModuleInfoEntryMap"),
|
||||
("RO_SPACE", 0x09e99): (164, "ModuleMap"),
|
||||
("RO_SPACE", 0x09ee9): (165, "ObjectTemplateInfoMap"),
|
||||
("RO_SPACE", 0x09f39): (166, "PromiseCapabilityMap"),
|
||||
("RO_SPACE", 0x09f89): (167, "PromiseReactionMap"),
|
||||
("RO_SPACE", 0x09fd9): (168, "PrototypeInfoMap"),
|
||||
("RO_SPACE", 0x0a029): (170, "StackFrameInfoMap"),
|
||||
("RO_SPACE", 0x0a079): (172, "Tuple3Map"),
|
||||
("RO_SPACE", 0x0a0c9): (173, "ArrayBoilerplateDescriptionMap"),
|
||||
("RO_SPACE", 0x0a119): (174, "WasmDebugInfoMap"),
|
||||
("RO_SPACE", 0x0a169): (175, "WasmExportedFunctionDataMap"),
|
||||
("RO_SPACE", 0x0a1b9): (176, "CallableTaskMap"),
|
||||
("RO_SPACE", 0x0a209): (177, "CallbackTaskMap"),
|
||||
("RO_SPACE", 0x0a259): (178, "PromiseFulfillReactionJobTaskMap"),
|
||||
("RO_SPACE", 0x0a2a9): (179, "PromiseRejectReactionJobTaskMap"),
|
||||
("RO_SPACE", 0x0a2f9): (180, "PromiseResolveThenableJobTaskMap"),
|
||||
("RO_SPACE", 0x0a349): (181, "AllocationSiteMap"),
|
||||
("RO_SPACE", 0x0a399): (181, "AllocationSiteMap"),
|
||||
("MAP_SPACE", 0x02201): (1057, "ExternalMap"),
|
||||
("MAP_SPACE", 0x02251): (1072, "JSMessageObjectMap"),
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user