[intl] Refactor instance type checks
Adds Intl::IsObjectOfType method to do type checks. This will make it easier to port the methods using the runtime type check calls as we won't have to create a v8::string for type checks. Bug: v8:5751 Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng Change-Id: I0babdc8709564be693ce808e2ef3ffef7b24ceec Reviewed-on: https://chromium-review.googlesource.com/1121943 Commit-Queue: Sathya Gunasekaran <gsathya@chromium.org> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Cr-Commit-Position: refs/heads/master@{#54143}
This commit is contained in:
parent
7da34b9650
commit
f03a754c25
2
BUILD.gn
2
BUILD.gn
@ -2122,6 +2122,7 @@ v8_source_set("v8_base") {
|
||||
"src/objects/frame-array.h",
|
||||
"src/objects/hash-table-inl.h",
|
||||
"src/objects/hash-table.h",
|
||||
"src/objects/intl-objects-inl.h",
|
||||
"src/objects/intl-objects.cc",
|
||||
"src/objects/intl-objects.h",
|
||||
"src/objects/js-array-inl.h",
|
||||
@ -2804,6 +2805,7 @@ v8_source_set("v8_base") {
|
||||
"src/char-predicates.cc",
|
||||
"src/intl.cc",
|
||||
"src/intl.h",
|
||||
"src/objects/intl-objects-inl.h",
|
||||
"src/objects/intl-objects.cc",
|
||||
"src/objects/intl-objects.h",
|
||||
"src/objects/js-locale-inl.h",
|
||||
|
@ -443,12 +443,8 @@ BUILTIN(NumberFormatPrototypeFormatToParts) {
|
||||
HandleScope handle_scope(isolate);
|
||||
CHECK_RECEIVER(JSObject, number_format_holder, method);
|
||||
|
||||
Handle<Symbol> marker = isolate->factory()->intl_initialized_marker_symbol();
|
||||
Handle<Object> tag =
|
||||
JSReceiver::GetDataProperty(number_format_holder, marker);
|
||||
Handle<String> expected_tag =
|
||||
isolate->factory()->NewStringFromStaticChars("numberformat");
|
||||
if (!(tag->IsString() && String::cast(*tag)->Equals(*expected_tag))) {
|
||||
if (!Intl::IsObjectOfType(isolate, number_format_holder,
|
||||
Intl::Type::kNumberFormat)) {
|
||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
||||
isolate,
|
||||
NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
|
||||
@ -478,10 +474,8 @@ BUILTIN(DateTimeFormatPrototypeFormatToParts) {
|
||||
CHECK_RECEIVER(JSObject, date_format_holder, method);
|
||||
Factory* factory = isolate->factory();
|
||||
|
||||
Handle<Symbol> marker = factory->intl_initialized_marker_symbol();
|
||||
Handle<Object> tag = JSReceiver::GetDataProperty(date_format_holder, marker);
|
||||
Handle<String> expected_tag = factory->NewStringFromStaticChars("dateformat");
|
||||
if (!(tag->IsString() && String::cast(*tag)->Equals(*expected_tag))) {
|
||||
if (!Intl::IsObjectOfType(isolate, date_format_holder,
|
||||
Intl::Type::kDateTimeFormat)) {
|
||||
THROW_NEW_ERROR_RETURN_FAILURE(
|
||||
isolate, NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
|
||||
factory->NewStringFromAsciiChecked(method),
|
||||
|
@ -67,7 +67,7 @@ endmacro
|
||||
/**
|
||||
* Adds bound method to the prototype of the given object.
|
||||
*/
|
||||
function AddBoundMethod(obj, methodName, implementation, length, typename,
|
||||
function AddBoundMethod(obj, methodName, implementation, length, type,
|
||||
compat) {
|
||||
%CheckIsBootstrapping();
|
||||
var internalName = %CreatePrivateSymbol(methodName);
|
||||
@ -75,7 +75,7 @@ function AddBoundMethod(obj, methodName, implementation, length, typename,
|
||||
DEFINE_METHOD(
|
||||
obj.prototype,
|
||||
get [methodName]() {
|
||||
var receiver = Unwrap(this, typename, obj, methodName, compat);
|
||||
var receiver = Unwrap(this, type, obj, methodName, compat);
|
||||
if (IS_UNDEFINED(receiver[internalName])) {
|
||||
var boundMethod;
|
||||
if (IS_UNDEFINED(length) || length === 2) {
|
||||
@ -120,11 +120,11 @@ function IntlConstruct(receiver, constructor, create, newTarget, args,
|
||||
|
||||
|
||||
|
||||
function Unwrap(receiver, typename, constructor, method, compat) {
|
||||
if (!%IsInitializedIntlObjectOfType(receiver, typename)) {
|
||||
function Unwrap(receiver, type, constructor, method, compat) {
|
||||
if (!%IsInitializedIntlObjectOfType(receiver, type)) {
|
||||
if (compat && receiver instanceof constructor) {
|
||||
let fallback = receiver[IntlFallbackSymbol];
|
||||
if (%IsInitializedIntlObjectOfType(fallback, typename)) {
|
||||
if (%IsInitializedIntlObjectOfType(fallback, type)) {
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
@ -1053,7 +1053,7 @@ function CreateCollator(locales, options) {
|
||||
|
||||
var collator = %CreateCollator(requestedLocale, internalOptions, resolved);
|
||||
|
||||
%MarkAsInitializedIntlObjectOfType(collator, 'collator');
|
||||
%MarkAsInitializedIntlObjectOfType(collator, COLLATOR_TYPE);
|
||||
collator[resolvedSymbol] = resolved;
|
||||
|
||||
return collator;
|
||||
@ -1079,8 +1079,8 @@ function CollatorConstructor() {
|
||||
DEFINE_METHOD(
|
||||
GlobalIntlCollator.prototype,
|
||||
resolvedOptions() {
|
||||
var coll = Unwrap(this, 'collator', GlobalIntlCollator, 'resolvedOptions',
|
||||
false);
|
||||
var coll = Unwrap(this, COLLATOR_TYPE, GlobalIntlCollator,
|
||||
'resolvedOptions', false);
|
||||
return {
|
||||
locale: coll[resolvedSymbol].locale,
|
||||
usage: coll[resolvedSymbol].usage,
|
||||
@ -1123,7 +1123,7 @@ function compare(collator, x, y) {
|
||||
};
|
||||
|
||||
|
||||
AddBoundMethod(GlobalIntlCollator, 'compare', compare, 2, 'collator', false);
|
||||
AddBoundMethod(GlobalIntlCollator, 'compare', compare, 2, COLLATOR_TYPE, false);
|
||||
|
||||
function PluralRulesConstructor() {
|
||||
if (IS_UNDEFINED(new.target)) {
|
||||
@ -1166,7 +1166,7 @@ function PluralRulesConstructor() {
|
||||
var pluralRules = %CreatePluralRules(requestedLocale, internalOptions,
|
||||
resolved);
|
||||
|
||||
%MarkAsInitializedIntlObjectOfType(pluralRules, 'pluralrules');
|
||||
%MarkAsInitializedIntlObjectOfType(pluralRules, PLURAL_RULES_TYPE);
|
||||
pluralRules[resolvedSymbol] = resolved;
|
||||
|
||||
return pluralRules;
|
||||
@ -1176,7 +1176,7 @@ function PluralRulesConstructor() {
|
||||
DEFINE_METHOD(
|
||||
GlobalIntlPluralRules.prototype,
|
||||
resolvedOptions() {
|
||||
if (!%IsInitializedIntlObjectOfType(this, 'pluralrules')) {
|
||||
if (!%IsInitializedIntlObjectOfType(this, PLURAL_RULES_TYPE)) {
|
||||
throw %make_type_error(kIncompatibleMethodReceiver,
|
||||
'Intl.PluralRules.prototype.resolvedOptions',
|
||||
this);
|
||||
@ -1217,7 +1217,7 @@ DEFINE_METHOD(
|
||||
DEFINE_METHOD(
|
||||
GlobalIntlPluralRules.prototype,
|
||||
select(value) {
|
||||
if (!%IsInitializedIntlObjectOfType(this, 'pluralrules')) {
|
||||
if (!%IsInitializedIntlObjectOfType(this, PLURAL_RULES_TYPE)) {
|
||||
throw %make_type_error(kIncompatibleMethodReceiver,
|
||||
'Intl.PluralRules.prototype.select',
|
||||
this);
|
||||
@ -1378,7 +1378,7 @@ function CreateNumberFormat(locales, options) {
|
||||
{value: currencyDisplay, writable: true});
|
||||
}
|
||||
|
||||
%MarkAsInitializedIntlObjectOfType(numberFormat, 'numberformat');
|
||||
%MarkAsInitializedIntlObjectOfType(numberFormat, NUMBER_FORMAT_TYPE);
|
||||
numberFormat[resolvedSymbol] = resolved;
|
||||
|
||||
return numberFormat;
|
||||
@ -1404,7 +1404,7 @@ function NumberFormatConstructor() {
|
||||
DEFINE_METHOD(
|
||||
GlobalIntlNumberFormat.prototype,
|
||||
resolvedOptions() {
|
||||
var format = Unwrap(this, 'numberformat', GlobalIntlNumberFormat,
|
||||
var format = Unwrap(this, NUMBER_FORMAT_TYPE, GlobalIntlNumberFormat,
|
||||
'resolvedOptions', true);
|
||||
var result = {
|
||||
locale: format[resolvedSymbol].locale,
|
||||
@ -1465,7 +1465,7 @@ function formatNumber(formatter, value) {
|
||||
|
||||
|
||||
AddBoundMethod(GlobalIntlNumberFormat, 'format', formatNumber, 1,
|
||||
'numberformat', true);
|
||||
NUMBER_FORMAT_TYPE, true);
|
||||
|
||||
/**
|
||||
* Returns a string that matches LDML representation of the options object.
|
||||
@ -1740,7 +1740,7 @@ function CreateDateTimeFormat(locales, options) {
|
||||
throw %make_range_error(kUnsupportedTimeZone, tz);
|
||||
}
|
||||
|
||||
%MarkAsInitializedIntlObjectOfType(dateFormat, 'dateformat');
|
||||
%MarkAsInitializedIntlObjectOfType(dateFormat, DATE_TIME_FORMAT_TYPE);
|
||||
dateFormat[resolvedSymbol] = resolved;
|
||||
|
||||
return dateFormat;
|
||||
@ -1766,7 +1766,7 @@ function DateTimeFormatConstructor() {
|
||||
DEFINE_METHOD(
|
||||
GlobalIntlDateTimeFormat.prototype,
|
||||
resolvedOptions() {
|
||||
var format = Unwrap(this, 'dateformat', GlobalIntlDateTimeFormat,
|
||||
var format = Unwrap(this, DATE_TIME_FORMAT_TYPE, GlobalIntlDateTimeFormat,
|
||||
'resolvedOptions', true);
|
||||
|
||||
/**
|
||||
@ -1841,7 +1841,7 @@ function formatDate(formatter, dateValue) {
|
||||
}
|
||||
|
||||
// Length is 1 as specified in ECMA 402 v2+
|
||||
AddBoundMethod(GlobalIntlDateTimeFormat, 'format', formatDate, 1, 'dateformat',
|
||||
AddBoundMethod(GlobalIntlDateTimeFormat, 'format', formatDate, 1, DATE_TIME_FORMAT_TYPE,
|
||||
true);
|
||||
|
||||
|
||||
@ -1911,7 +1911,7 @@ function CreateBreakIterator(locales, options) {
|
||||
|
||||
var iterator = %CreateBreakIterator(locale.locale, internalOptions, resolved);
|
||||
|
||||
%MarkAsInitializedIntlObjectOfType(iterator, 'breakiterator');
|
||||
%MarkAsInitializedIntlObjectOfType(iterator, BREAK_ITERATOR_TYPE);
|
||||
iterator[resolvedSymbol] = resolved;
|
||||
|
||||
return iterator;
|
||||
@ -1941,7 +1941,7 @@ DEFINE_METHOD(
|
||||
throw %make_type_error(kOrdinaryFunctionCalledAsConstructor);
|
||||
}
|
||||
|
||||
var segmenter = Unwrap(this, 'breakiterator', GlobalIntlv8BreakIterator,
|
||||
var segmenter = Unwrap(this, BREAK_ITERATOR_TYPE, GlobalIntlv8BreakIterator,
|
||||
'resolvedOptions', false);
|
||||
|
||||
return {
|
||||
@ -2012,13 +2012,15 @@ function breakType(iterator) {
|
||||
|
||||
|
||||
AddBoundMethod(GlobalIntlv8BreakIterator, 'adoptText', adoptText, 1,
|
||||
'breakiterator');
|
||||
AddBoundMethod(GlobalIntlv8BreakIterator, 'first', first, 0, 'breakiterator');
|
||||
AddBoundMethod(GlobalIntlv8BreakIterator, 'next', next, 0, 'breakiterator');
|
||||
BREAK_ITERATOR_TYPE);
|
||||
AddBoundMethod(GlobalIntlv8BreakIterator, 'first', first, 0,
|
||||
BREAK_ITERATOR_TYPE);
|
||||
AddBoundMethod(GlobalIntlv8BreakIterator, 'next', next, 0,
|
||||
BREAK_ITERATOR_TYPE);
|
||||
AddBoundMethod(GlobalIntlv8BreakIterator, 'current', current, 0,
|
||||
'breakiterator');
|
||||
BREAK_ITERATOR_TYPE);
|
||||
AddBoundMethod(GlobalIntlv8BreakIterator, 'breakType', breakType, 0,
|
||||
'breakiterator');
|
||||
BREAK_ITERATOR_TYPE);
|
||||
|
||||
// Save references to Intl objects and methods we use, for added security.
|
||||
var savedObjects = {
|
||||
|
@ -83,3 +83,11 @@ macro DEFINE_METHOD(obj, method_def) = DEFINE_METHOD_LEN(obj, method_def, -1);
|
||||
# Constants. The compiler constant folds them.
|
||||
define INFINITY = (1/0);
|
||||
define UNDEFINED = (void 0);
|
||||
|
||||
# This should be kept consistent with Intl::Type.
|
||||
define NUMBER_FORMAT_TYPE = 0;
|
||||
define COLLATOR_TYPE = 1;
|
||||
define DATE_TIME_FORMAT_TYPE = 2;
|
||||
define PLURAL_RULES_TYPE = 3;
|
||||
define BREAK_ITERATOR_TYPE = 4;
|
||||
define LOCALE_TYPE = 5;
|
||||
|
27
src/objects/intl-objects-inl.h
Normal file
27
src/objects/intl-objects-inl.h
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright 2017 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.
|
||||
|
||||
#ifndef V8_OBJECTS_INTL_OBJECTS_INL_H_
|
||||
#define V8_OBJECTS_INTL_OBJECTS_INL_H_
|
||||
|
||||
#include "src/objects/intl-objects.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
inline Intl::Type Intl::TypeFromInt(int type_int) {
|
||||
STATIC_ASSERT(Intl::Type::kNumberFormat == 0);
|
||||
DCHECK_LE(Intl::Type::kNumberFormat, type_int);
|
||||
DCHECK_GT(Intl::Type::kTypeCount, type_int);
|
||||
return static_cast<Intl::Type>(type_int);
|
||||
}
|
||||
|
||||
inline Intl::Type Intl::TypeFromSmi(Smi* type) {
|
||||
return TypeFromInt(Smi::ToInt(type));
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_OBJECTS_INTL_OBJECTS_INL_H_
|
@ -7,6 +7,7 @@
|
||||
#endif // V8_INTL_SUPPORT
|
||||
|
||||
#include "src/objects/intl-objects.h"
|
||||
#include "src/objects/intl-objects-inl.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
@ -1080,8 +1081,8 @@ void V8BreakIterator::DeleteBreakIterator(
|
||||
}
|
||||
|
||||
// Build the shortened locale; eg, convert xx_Yyyy_ZZ to xx_ZZ.
|
||||
bool IntlUtil::RemoveLocaleScriptTag(const std::string& icu_locale,
|
||||
std::string* locale_less_script) {
|
||||
bool Intl::RemoveLocaleScriptTag(const std::string& icu_locale,
|
||||
std::string* locale_less_script) {
|
||||
icu::Locale new_locale = icu::Locale::createCanonical(icu_locale.c_str());
|
||||
const char* icu_script = new_locale.getScript();
|
||||
if (icu_script == NULL || strlen(icu_script) == 0) {
|
||||
@ -1097,7 +1098,7 @@ bool IntlUtil::RemoveLocaleScriptTag(const std::string& icu_locale,
|
||||
return true;
|
||||
}
|
||||
|
||||
std::set<std::string> IntlUtil::GetAvailableLocales(const IcuService& service) {
|
||||
std::set<std::string> Intl::GetAvailableLocales(const IcuService& service) {
|
||||
const icu::Locale* icu_available_locales = nullptr;
|
||||
int32_t count = 0;
|
||||
|
||||
@ -1142,7 +1143,7 @@ std::set<std::string> IntlUtil::GetAvailableLocales(const IcuService& service) {
|
||||
locales.insert(locale);
|
||||
|
||||
std::string shortened_locale;
|
||||
if (IntlUtil::RemoveLocaleScriptTag(icu_name, &shortened_locale)) {
|
||||
if (Intl::RemoveLocaleScriptTag(icu_name, &shortened_locale)) {
|
||||
std::replace(shortened_locale.begin(), shortened_locale.end(), '_', '-');
|
||||
locales.insert(shortened_locale);
|
||||
}
|
||||
@ -1151,5 +1152,19 @@ std::set<std::string> IntlUtil::GetAvailableLocales(const IcuService& service) {
|
||||
return locales;
|
||||
}
|
||||
|
||||
bool Intl::IsObjectOfType(Isolate* isolate, Handle<Object> input,
|
||||
Intl::Type expected_type) {
|
||||
if (!input->IsJSObject()) return false;
|
||||
Handle<JSObject> obj = Handle<JSObject>::cast(input);
|
||||
|
||||
Handle<Symbol> marker = isolate->factory()->intl_initialized_marker_symbol();
|
||||
Handle<Object> tag = JSReceiver::GetDataProperty(obj, marker);
|
||||
|
||||
if (!tag->IsSmi()) return false;
|
||||
|
||||
Intl::Type type = Intl::TypeFromSmi(Smi::cast(*tag));
|
||||
return type == expected_type;
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -163,13 +163,36 @@ class V8BreakIterator {
|
||||
V8BreakIterator();
|
||||
};
|
||||
|
||||
class IntlUtil {
|
||||
class Intl {
|
||||
public:
|
||||
enum Type {
|
||||
kNumberFormat = 0,
|
||||
kCollator,
|
||||
kDateTimeFormat,
|
||||
kPluralRules,
|
||||
kBreakIterator,
|
||||
kLocale,
|
||||
|
||||
kTypeCount
|
||||
};
|
||||
|
||||
inline static Intl::Type TypeFromInt(int type);
|
||||
inline static Intl::Type TypeFromSmi(Smi* type);
|
||||
|
||||
// Checks if the given object has the expected_type based by looking
|
||||
// up a private symbol on the object.
|
||||
//
|
||||
// TODO(gsathya): This should just be an instance type check once we
|
||||
// move all the Intl objects to C++.
|
||||
static bool IsObjectOfType(Isolate* isolate, Handle<Object> object,
|
||||
Intl::Type expected_type);
|
||||
|
||||
// Gets the ICU locales for a given service. If there is a locale with a
|
||||
// script tag then the locales also include a locale without the script; eg,
|
||||
// pa_Guru_IN (language=Panjabi, script=Gurmukhi, country-India) would include
|
||||
// pa_IN.
|
||||
static std::set<std::string> GetAvailableLocales(const IcuService& service);
|
||||
|
||||
// If locale has a script tag then return true and the locale without the
|
||||
// script else return false and an empty string
|
||||
static bool RemoveLocaleScriptTag(const std::string& icu_locale,
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "src/intl.h"
|
||||
#include "src/isolate-inl.h"
|
||||
#include "src/messages.h"
|
||||
#include "src/objects/intl-objects-inl.h"
|
||||
#include "src/objects/intl-objects.h"
|
||||
#include "src/utils.h"
|
||||
|
||||
@ -172,36 +173,18 @@ RUNTIME_FUNCTION(Runtime_GetDefaultICULocale) {
|
||||
return *factory->NewStringFromStaticChars("und");
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_IsInitializedIntlObject) {
|
||||
HandleScope scope(isolate);
|
||||
|
||||
DCHECK_EQ(1, args.length());
|
||||
|
||||
CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
|
||||
|
||||
if (!input->IsJSObject()) return isolate->heap()->false_value();
|
||||
Handle<JSObject> obj = Handle<JSObject>::cast(input);
|
||||
|
||||
Handle<Symbol> marker = isolate->factory()->intl_initialized_marker_symbol();
|
||||
Handle<Object> tag = JSReceiver::GetDataProperty(obj, marker);
|
||||
return isolate->heap()->ToBoolean(!tag->IsUndefined(isolate));
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_IsInitializedIntlObjectOfType) {
|
||||
HandleScope scope(isolate);
|
||||
|
||||
DCHECK_EQ(2, args.length());
|
||||
|
||||
CONVERT_ARG_HANDLE_CHECKED(Object, input, 0);
|
||||
CONVERT_ARG_HANDLE_CHECKED(String, expected_type, 1);
|
||||
CONVERT_SMI_ARG_CHECKED(expected_type_int, 1);
|
||||
|
||||
if (!input->IsJSObject()) return isolate->heap()->false_value();
|
||||
Handle<JSObject> obj = Handle<JSObject>::cast(input);
|
||||
Intl::Type expected_type = Intl::TypeFromInt(expected_type_int);
|
||||
|
||||
Handle<Symbol> marker = isolate->factory()->intl_initialized_marker_symbol();
|
||||
Handle<Object> tag = JSReceiver::GetDataProperty(obj, marker);
|
||||
return isolate->heap()->ToBoolean(tag->IsString() &&
|
||||
String::cast(*tag)->Equals(*expected_type));
|
||||
return isolate->heap()->ToBoolean(
|
||||
Intl::IsObjectOfType(isolate, input, expected_type));
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_MarkAsInitializedIntlObjectOfType) {
|
||||
@ -210,7 +193,13 @@ RUNTIME_FUNCTION(Runtime_MarkAsInitializedIntlObjectOfType) {
|
||||
DCHECK_EQ(2, args.length());
|
||||
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSObject, input, 0);
|
||||
CONVERT_ARG_HANDLE_CHECKED(String, type, 1);
|
||||
CONVERT_ARG_HANDLE_CHECKED(Smi, type, 1);
|
||||
|
||||
#ifdef DEBUG
|
||||
// TypeFromSmi does correctness checks.
|
||||
Intl::Type type_intl = Intl::TypeFromSmi(*type);
|
||||
USE(type_intl);
|
||||
#endif
|
||||
|
||||
Handle<Symbol> marker = isolate->factory()->intl_initialized_marker_symbol();
|
||||
JSObject::SetProperty(input, marker, type, LanguageMode::kStrict).Assert();
|
||||
|
@ -225,7 +225,6 @@ namespace internal {
|
||||
F(InternalCompare, 3, 1) \
|
||||
F(InternalDateFormat, 2, 1) \
|
||||
F(InternalNumberFormat, 2, 1) \
|
||||
F(IsInitializedIntlObject, 1, 1) \
|
||||
F(IsInitializedIntlObjectOfType, 2, 1) \
|
||||
F(MarkAsInitializedIntlObjectOfType, 2, 1) \
|
||||
F(PluralRulesSelect, 2, 1) \
|
||||
|
@ -183,15 +183,13 @@ TEST(GetOptions) {
|
||||
|
||||
bool ScriptTagWasRemoved(std::string locale, std::string expected) {
|
||||
std::string without_script_tag;
|
||||
bool didShorten =
|
||||
IntlUtil::RemoveLocaleScriptTag(locale, &without_script_tag);
|
||||
bool didShorten = Intl::RemoveLocaleScriptTag(locale, &without_script_tag);
|
||||
return didShorten && expected == without_script_tag;
|
||||
}
|
||||
|
||||
bool ScriptTagWasNotRemoved(std::string locale) {
|
||||
std::string without_script_tag;
|
||||
bool didShorten =
|
||||
IntlUtil::RemoveLocaleScriptTag(locale, &without_script_tag);
|
||||
bool didShorten = Intl::RemoveLocaleScriptTag(locale, &without_script_tag);
|
||||
return !didShorten && without_script_tag.empty();
|
||||
}
|
||||
|
||||
@ -209,23 +207,61 @@ TEST(RemoveLocaleScriptTag) {
|
||||
TEST(GetAvailableLocales) {
|
||||
std::set<std::string> locales;
|
||||
|
||||
locales = IntlUtil::GetAvailableLocales(IcuService::kBreakIterator);
|
||||
locales = Intl::GetAvailableLocales(IcuService::kBreakIterator);
|
||||
CHECK(locales.count("en-US"));
|
||||
CHECK(!locales.count("abcdefg"));
|
||||
|
||||
locales = IntlUtil::GetAvailableLocales(IcuService::kCollator);
|
||||
locales = Intl::GetAvailableLocales(IcuService::kCollator);
|
||||
CHECK(locales.count("en-US"));
|
||||
|
||||
locales = IntlUtil::GetAvailableLocales(IcuService::kDateFormat);
|
||||
locales = Intl::GetAvailableLocales(IcuService::kDateFormat);
|
||||
CHECK(locales.count("en-US"));
|
||||
|
||||
locales = IntlUtil::GetAvailableLocales(IcuService::kNumberFormat);
|
||||
locales = Intl::GetAvailableLocales(IcuService::kNumberFormat);
|
||||
CHECK(locales.count("en-US"));
|
||||
|
||||
locales = IntlUtil::GetAvailableLocales(IcuService::kPluralRules);
|
||||
locales = Intl::GetAvailableLocales(IcuService::kPluralRules);
|
||||
CHECK(locales.count("en-US"));
|
||||
}
|
||||
|
||||
TEST(IsObjectOfType) {
|
||||
LocalContext env;
|
||||
Isolate* isolate = CcTest::i_isolate();
|
||||
v8::Isolate* v8_isolate = env->GetIsolate();
|
||||
v8::HandleScope handle_scope(v8_isolate);
|
||||
|
||||
Handle<JSObject> obj = isolate->factory()->NewJSObjectWithNullProto();
|
||||
Handle<Symbol> marker = isolate->factory()->intl_initialized_marker_symbol();
|
||||
|
||||
STATIC_ASSERT(Intl::Type::kNumberFormat == 0);
|
||||
Intl::Type types[] = {Intl::Type::kNumberFormat, Intl::Type::kCollator,
|
||||
Intl::Type::kDateTimeFormat, Intl::Type::kPluralRules,
|
||||
Intl::Type::kBreakIterator, Intl::Type::kLocale};
|
||||
|
||||
for (auto type : types) {
|
||||
Handle<Smi> tag =
|
||||
Handle<Smi>(Smi::FromInt(static_cast<int>(type)), isolate);
|
||||
JSObject::SetProperty(obj, marker, tag, LanguageMode::kStrict).Assert();
|
||||
|
||||
CHECK(Intl::IsObjectOfType(isolate, obj, type));
|
||||
}
|
||||
|
||||
Handle<Object> tag = isolate->factory()->NewStringFromAsciiChecked("foo");
|
||||
JSObject::SetProperty(obj, marker, tag, LanguageMode::kStrict).Assert();
|
||||
CHECK(!Intl::IsObjectOfType(isolate, obj, types[0]));
|
||||
|
||||
CHECK(!Intl::IsObjectOfType(isolate, tag, types[0]));
|
||||
CHECK(!Intl::IsObjectOfType(isolate, Handle<Smi>(Smi::FromInt(0), isolate),
|
||||
types[0]));
|
||||
|
||||
// Proxy with target as an initialized object should fail.
|
||||
tag = Handle<Smi>(Smi::FromInt(static_cast<int>(types[0])), isolate);
|
||||
JSObject::SetProperty(obj, marker, tag, LanguageMode::kStrict).Assert();
|
||||
Handle<JSReceiver> proxy = isolate->factory()->NewJSProxy(
|
||||
obj, isolate->factory()->NewJSObjectWithNullProto());
|
||||
CHECK(!Intl::IsObjectOfType(isolate, proxy, types[0]));
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user