Commit f03a754c authored by Sathya Gunasekaran's avatar Sathya Gunasekaran Committed by Commit Bot

[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: 's avatarJakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54143}
parent 7da34b96
...@@ -2122,6 +2122,7 @@ v8_source_set("v8_base") { ...@@ -2122,6 +2122,7 @@ v8_source_set("v8_base") {
"src/objects/frame-array.h", "src/objects/frame-array.h",
"src/objects/hash-table-inl.h", "src/objects/hash-table-inl.h",
"src/objects/hash-table.h", "src/objects/hash-table.h",
"src/objects/intl-objects-inl.h",
"src/objects/intl-objects.cc", "src/objects/intl-objects.cc",
"src/objects/intl-objects.h", "src/objects/intl-objects.h",
"src/objects/js-array-inl.h", "src/objects/js-array-inl.h",
...@@ -2804,6 +2805,7 @@ v8_source_set("v8_base") { ...@@ -2804,6 +2805,7 @@ v8_source_set("v8_base") {
"src/char-predicates.cc", "src/char-predicates.cc",
"src/intl.cc", "src/intl.cc",
"src/intl.h", "src/intl.h",
"src/objects/intl-objects-inl.h",
"src/objects/intl-objects.cc", "src/objects/intl-objects.cc",
"src/objects/intl-objects.h", "src/objects/intl-objects.h",
"src/objects/js-locale-inl.h", "src/objects/js-locale-inl.h",
......
...@@ -443,12 +443,8 @@ BUILTIN(NumberFormatPrototypeFormatToParts) { ...@@ -443,12 +443,8 @@ BUILTIN(NumberFormatPrototypeFormatToParts) {
HandleScope handle_scope(isolate); HandleScope handle_scope(isolate);
CHECK_RECEIVER(JSObject, number_format_holder, method); CHECK_RECEIVER(JSObject, number_format_holder, method);
Handle<Symbol> marker = isolate->factory()->intl_initialized_marker_symbol(); if (!Intl::IsObjectOfType(isolate, number_format_holder,
Handle<Object> tag = Intl::Type::kNumberFormat)) {
JSReceiver::GetDataProperty(number_format_holder, marker);
Handle<String> expected_tag =
isolate->factory()->NewStringFromStaticChars("numberformat");
if (!(tag->IsString() && String::cast(*tag)->Equals(*expected_tag))) {
THROW_NEW_ERROR_RETURN_FAILURE( THROW_NEW_ERROR_RETURN_FAILURE(
isolate, isolate,
NewTypeError(MessageTemplate::kIncompatibleMethodReceiver, NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
...@@ -478,10 +474,8 @@ BUILTIN(DateTimeFormatPrototypeFormatToParts) { ...@@ -478,10 +474,8 @@ BUILTIN(DateTimeFormatPrototypeFormatToParts) {
CHECK_RECEIVER(JSObject, date_format_holder, method); CHECK_RECEIVER(JSObject, date_format_holder, method);
Factory* factory = isolate->factory(); Factory* factory = isolate->factory();
Handle<Symbol> marker = factory->intl_initialized_marker_symbol(); if (!Intl::IsObjectOfType(isolate, date_format_holder,
Handle<Object> tag = JSReceiver::GetDataProperty(date_format_holder, marker); Intl::Type::kDateTimeFormat)) {
Handle<String> expected_tag = factory->NewStringFromStaticChars("dateformat");
if (!(tag->IsString() && String::cast(*tag)->Equals(*expected_tag))) {
THROW_NEW_ERROR_RETURN_FAILURE( THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kIncompatibleMethodReceiver, isolate, NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
factory->NewStringFromAsciiChecked(method), factory->NewStringFromAsciiChecked(method),
......
...@@ -67,7 +67,7 @@ endmacro ...@@ -67,7 +67,7 @@ endmacro
/** /**
* Adds bound method to the prototype of the given object. * 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) { compat) {
%CheckIsBootstrapping(); %CheckIsBootstrapping();
var internalName = %CreatePrivateSymbol(methodName); var internalName = %CreatePrivateSymbol(methodName);
...@@ -75,7 +75,7 @@ function AddBoundMethod(obj, methodName, implementation, length, typename, ...@@ -75,7 +75,7 @@ function AddBoundMethod(obj, methodName, implementation, length, typename,
DEFINE_METHOD( DEFINE_METHOD(
obj.prototype, obj.prototype,
get [methodName]() { get [methodName]() {
var receiver = Unwrap(this, typename, obj, methodName, compat); var receiver = Unwrap(this, type, obj, methodName, compat);
if (IS_UNDEFINED(receiver[internalName])) { if (IS_UNDEFINED(receiver[internalName])) {
var boundMethod; var boundMethod;
if (IS_UNDEFINED(length) || length === 2) { if (IS_UNDEFINED(length) || length === 2) {
...@@ -120,11 +120,11 @@ function IntlConstruct(receiver, constructor, create, newTarget, args, ...@@ -120,11 +120,11 @@ function IntlConstruct(receiver, constructor, create, newTarget, args,
function Unwrap(receiver, typename, constructor, method, compat) { function Unwrap(receiver, type, constructor, method, compat) {
if (!%IsInitializedIntlObjectOfType(receiver, typename)) { if (!%IsInitializedIntlObjectOfType(receiver, type)) {
if (compat && receiver instanceof constructor) { if (compat && receiver instanceof constructor) {
let fallback = receiver[IntlFallbackSymbol]; let fallback = receiver[IntlFallbackSymbol];
if (%IsInitializedIntlObjectOfType(fallback, typename)) { if (%IsInitializedIntlObjectOfType(fallback, type)) {
return fallback; return fallback;
} }
} }
...@@ -1053,7 +1053,7 @@ function CreateCollator(locales, options) { ...@@ -1053,7 +1053,7 @@ function CreateCollator(locales, options) {
var collator = %CreateCollator(requestedLocale, internalOptions, resolved); var collator = %CreateCollator(requestedLocale, internalOptions, resolved);
%MarkAsInitializedIntlObjectOfType(collator, 'collator'); %MarkAsInitializedIntlObjectOfType(collator, COLLATOR_TYPE);
collator[resolvedSymbol] = resolved; collator[resolvedSymbol] = resolved;
return collator; return collator;
...@@ -1079,8 +1079,8 @@ function CollatorConstructor() { ...@@ -1079,8 +1079,8 @@ function CollatorConstructor() {
DEFINE_METHOD( DEFINE_METHOD(
GlobalIntlCollator.prototype, GlobalIntlCollator.prototype,
resolvedOptions() { resolvedOptions() {
var coll = Unwrap(this, 'collator', GlobalIntlCollator, 'resolvedOptions', var coll = Unwrap(this, COLLATOR_TYPE, GlobalIntlCollator,
false); 'resolvedOptions', false);
return { return {
locale: coll[resolvedSymbol].locale, locale: coll[resolvedSymbol].locale,
usage: coll[resolvedSymbol].usage, usage: coll[resolvedSymbol].usage,
...@@ -1123,7 +1123,7 @@ function compare(collator, x, y) { ...@@ -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() { function PluralRulesConstructor() {
if (IS_UNDEFINED(new.target)) { if (IS_UNDEFINED(new.target)) {
...@@ -1166,7 +1166,7 @@ function PluralRulesConstructor() { ...@@ -1166,7 +1166,7 @@ function PluralRulesConstructor() {
var pluralRules = %CreatePluralRules(requestedLocale, internalOptions, var pluralRules = %CreatePluralRules(requestedLocale, internalOptions,
resolved); resolved);
%MarkAsInitializedIntlObjectOfType(pluralRules, 'pluralrules'); %MarkAsInitializedIntlObjectOfType(pluralRules, PLURAL_RULES_TYPE);
pluralRules[resolvedSymbol] = resolved; pluralRules[resolvedSymbol] = resolved;
return pluralRules; return pluralRules;
...@@ -1176,7 +1176,7 @@ function PluralRulesConstructor() { ...@@ -1176,7 +1176,7 @@ function PluralRulesConstructor() {
DEFINE_METHOD( DEFINE_METHOD(
GlobalIntlPluralRules.prototype, GlobalIntlPluralRules.prototype,
resolvedOptions() { resolvedOptions() {
if (!%IsInitializedIntlObjectOfType(this, 'pluralrules')) { if (!%IsInitializedIntlObjectOfType(this, PLURAL_RULES_TYPE)) {
throw %make_type_error(kIncompatibleMethodReceiver, throw %make_type_error(kIncompatibleMethodReceiver,
'Intl.PluralRules.prototype.resolvedOptions', 'Intl.PluralRules.prototype.resolvedOptions',
this); this);
...@@ -1217,7 +1217,7 @@ DEFINE_METHOD( ...@@ -1217,7 +1217,7 @@ DEFINE_METHOD(
DEFINE_METHOD( DEFINE_METHOD(
GlobalIntlPluralRules.prototype, GlobalIntlPluralRules.prototype,
select(value) { select(value) {
if (!%IsInitializedIntlObjectOfType(this, 'pluralrules')) { if (!%IsInitializedIntlObjectOfType(this, PLURAL_RULES_TYPE)) {
throw %make_type_error(kIncompatibleMethodReceiver, throw %make_type_error(kIncompatibleMethodReceiver,
'Intl.PluralRules.prototype.select', 'Intl.PluralRules.prototype.select',
this); this);
...@@ -1378,7 +1378,7 @@ function CreateNumberFormat(locales, options) { ...@@ -1378,7 +1378,7 @@ function CreateNumberFormat(locales, options) {
{value: currencyDisplay, writable: true}); {value: currencyDisplay, writable: true});
} }
%MarkAsInitializedIntlObjectOfType(numberFormat, 'numberformat'); %MarkAsInitializedIntlObjectOfType(numberFormat, NUMBER_FORMAT_TYPE);
numberFormat[resolvedSymbol] = resolved; numberFormat[resolvedSymbol] = resolved;
return numberFormat; return numberFormat;
...@@ -1404,7 +1404,7 @@ function NumberFormatConstructor() { ...@@ -1404,7 +1404,7 @@ function NumberFormatConstructor() {
DEFINE_METHOD( DEFINE_METHOD(
GlobalIntlNumberFormat.prototype, GlobalIntlNumberFormat.prototype,
resolvedOptions() { resolvedOptions() {
var format = Unwrap(this, 'numberformat', GlobalIntlNumberFormat, var format = Unwrap(this, NUMBER_FORMAT_TYPE, GlobalIntlNumberFormat,
'resolvedOptions', true); 'resolvedOptions', true);
var result = { var result = {
locale: format[resolvedSymbol].locale, locale: format[resolvedSymbol].locale,
...@@ -1465,7 +1465,7 @@ function formatNumber(formatter, value) { ...@@ -1465,7 +1465,7 @@ function formatNumber(formatter, value) {
AddBoundMethod(GlobalIntlNumberFormat, 'format', formatNumber, 1, AddBoundMethod(GlobalIntlNumberFormat, 'format', formatNumber, 1,
'numberformat', true); NUMBER_FORMAT_TYPE, true);
/** /**
* Returns a string that matches LDML representation of the options object. * Returns a string that matches LDML representation of the options object.
...@@ -1740,7 +1740,7 @@ function CreateDateTimeFormat(locales, options) { ...@@ -1740,7 +1740,7 @@ function CreateDateTimeFormat(locales, options) {
throw %make_range_error(kUnsupportedTimeZone, tz); throw %make_range_error(kUnsupportedTimeZone, tz);
} }
%MarkAsInitializedIntlObjectOfType(dateFormat, 'dateformat'); %MarkAsInitializedIntlObjectOfType(dateFormat, DATE_TIME_FORMAT_TYPE);
dateFormat[resolvedSymbol] = resolved; dateFormat[resolvedSymbol] = resolved;
return dateFormat; return dateFormat;
...@@ -1766,7 +1766,7 @@ function DateTimeFormatConstructor() { ...@@ -1766,7 +1766,7 @@ function DateTimeFormatConstructor() {
DEFINE_METHOD( DEFINE_METHOD(
GlobalIntlDateTimeFormat.prototype, GlobalIntlDateTimeFormat.prototype,
resolvedOptions() { resolvedOptions() {
var format = Unwrap(this, 'dateformat', GlobalIntlDateTimeFormat, var format = Unwrap(this, DATE_TIME_FORMAT_TYPE, GlobalIntlDateTimeFormat,
'resolvedOptions', true); 'resolvedOptions', true);
/** /**
...@@ -1841,7 +1841,7 @@ function formatDate(formatter, dateValue) { ...@@ -1841,7 +1841,7 @@ function formatDate(formatter, dateValue) {
} }
// Length is 1 as specified in ECMA 402 v2+ // 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); true);
...@@ -1911,7 +1911,7 @@ function CreateBreakIterator(locales, options) { ...@@ -1911,7 +1911,7 @@ function CreateBreakIterator(locales, options) {
var iterator = %CreateBreakIterator(locale.locale, internalOptions, resolved); var iterator = %CreateBreakIterator(locale.locale, internalOptions, resolved);
%MarkAsInitializedIntlObjectOfType(iterator, 'breakiterator'); %MarkAsInitializedIntlObjectOfType(iterator, BREAK_ITERATOR_TYPE);
iterator[resolvedSymbol] = resolved; iterator[resolvedSymbol] = resolved;
return iterator; return iterator;
...@@ -1941,7 +1941,7 @@ DEFINE_METHOD( ...@@ -1941,7 +1941,7 @@ DEFINE_METHOD(
throw %make_type_error(kOrdinaryFunctionCalledAsConstructor); throw %make_type_error(kOrdinaryFunctionCalledAsConstructor);
} }
var segmenter = Unwrap(this, 'breakiterator', GlobalIntlv8BreakIterator, var segmenter = Unwrap(this, BREAK_ITERATOR_TYPE, GlobalIntlv8BreakIterator,
'resolvedOptions', false); 'resolvedOptions', false);
return { return {
...@@ -2012,13 +2012,15 @@ function breakType(iterator) { ...@@ -2012,13 +2012,15 @@ function breakType(iterator) {
AddBoundMethod(GlobalIntlv8BreakIterator, 'adoptText', adoptText, 1, AddBoundMethod(GlobalIntlv8BreakIterator, 'adoptText', adoptText, 1,
'breakiterator'); BREAK_ITERATOR_TYPE);
AddBoundMethod(GlobalIntlv8BreakIterator, 'first', first, 0, 'breakiterator'); AddBoundMethod(GlobalIntlv8BreakIterator, 'first', first, 0,
AddBoundMethod(GlobalIntlv8BreakIterator, 'next', next, 0, 'breakiterator'); BREAK_ITERATOR_TYPE);
AddBoundMethod(GlobalIntlv8BreakIterator, 'next', next, 0,
BREAK_ITERATOR_TYPE);
AddBoundMethod(GlobalIntlv8BreakIterator, 'current', current, 0, AddBoundMethod(GlobalIntlv8BreakIterator, 'current', current, 0,
'breakiterator'); BREAK_ITERATOR_TYPE);
AddBoundMethod(GlobalIntlv8BreakIterator, 'breakType', breakType, 0, AddBoundMethod(GlobalIntlv8BreakIterator, 'breakType', breakType, 0,
'breakiterator'); BREAK_ITERATOR_TYPE);
// Save references to Intl objects and methods we use, for added security. // Save references to Intl objects and methods we use, for added security.
var savedObjects = { var savedObjects = {
......
...@@ -83,3 +83,11 @@ macro DEFINE_METHOD(obj, method_def) = DEFINE_METHOD_LEN(obj, method_def, -1); ...@@ -83,3 +83,11 @@ macro DEFINE_METHOD(obj, method_def) = DEFINE_METHOD_LEN(obj, method_def, -1);
# Constants. The compiler constant folds them. # Constants. The compiler constant folds them.
define INFINITY = (1/0); define INFINITY = (1/0);
define UNDEFINED = (void 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;
// 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 @@ ...@@ -7,6 +7,7 @@
#endif // V8_INTL_SUPPORT #endif // V8_INTL_SUPPORT
#include "src/objects/intl-objects.h" #include "src/objects/intl-objects.h"
#include "src/objects/intl-objects-inl.h"
#include <memory> #include <memory>
...@@ -1080,7 +1081,7 @@ void V8BreakIterator::DeleteBreakIterator( ...@@ -1080,7 +1081,7 @@ void V8BreakIterator::DeleteBreakIterator(
} }
// Build the shortened locale; eg, convert xx_Yyyy_ZZ to xx_ZZ. // Build the shortened locale; eg, convert xx_Yyyy_ZZ to xx_ZZ.
bool IntlUtil::RemoveLocaleScriptTag(const std::string& icu_locale, bool Intl::RemoveLocaleScriptTag(const std::string& icu_locale,
std::string* locale_less_script) { std::string* locale_less_script) {
icu::Locale new_locale = icu::Locale::createCanonical(icu_locale.c_str()); icu::Locale new_locale = icu::Locale::createCanonical(icu_locale.c_str());
const char* icu_script = new_locale.getScript(); const char* icu_script = new_locale.getScript();
...@@ -1097,7 +1098,7 @@ bool IntlUtil::RemoveLocaleScriptTag(const std::string& icu_locale, ...@@ -1097,7 +1098,7 @@ bool IntlUtil::RemoveLocaleScriptTag(const std::string& icu_locale,
return true; 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; const icu::Locale* icu_available_locales = nullptr;
int32_t count = 0; int32_t count = 0;
...@@ -1142,7 +1143,7 @@ std::set<std::string> IntlUtil::GetAvailableLocales(const IcuService& service) { ...@@ -1142,7 +1143,7 @@ std::set<std::string> IntlUtil::GetAvailableLocales(const IcuService& service) {
locales.insert(locale); locales.insert(locale);
std::string shortened_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(), '_', '-'); std::replace(shortened_locale.begin(), shortened_locale.end(), '_', '-');
locales.insert(shortened_locale); locales.insert(shortened_locale);
} }
...@@ -1151,5 +1152,19 @@ std::set<std::string> IntlUtil::GetAvailableLocales(const IcuService& service) { ...@@ -1151,5 +1152,19 @@ std::set<std::string> IntlUtil::GetAvailableLocales(const IcuService& service) {
return locales; 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 internal
} // namespace v8 } // namespace v8
...@@ -163,13 +163,36 @@ class V8BreakIterator { ...@@ -163,13 +163,36 @@ class V8BreakIterator {
V8BreakIterator(); V8BreakIterator();
}; };
class IntlUtil { class Intl {
public: 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 // 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, // 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_Guru_IN (language=Panjabi, script=Gurmukhi, country-India) would include
// pa_IN. // pa_IN.
static std::set<std::string> GetAvailableLocales(const IcuService& service); static std::set<std::string> GetAvailableLocales(const IcuService& service);
// If locale has a script tag then return true and the locale without the // If locale has a script tag then return true and the locale without the
// script else return false and an empty string // script else return false and an empty string
static bool RemoveLocaleScriptTag(const std::string& icu_locale, static bool RemoveLocaleScriptTag(const std::string& icu_locale,
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "src/intl.h" #include "src/intl.h"
#include "src/isolate-inl.h" #include "src/isolate-inl.h"
#include "src/messages.h" #include "src/messages.h"
#include "src/objects/intl-objects-inl.h"
#include "src/objects/intl-objects.h" #include "src/objects/intl-objects.h"
#include "src/utils.h" #include "src/utils.h"
...@@ -172,36 +173,18 @@ RUNTIME_FUNCTION(Runtime_GetDefaultICULocale) { ...@@ -172,36 +173,18 @@ RUNTIME_FUNCTION(Runtime_GetDefaultICULocale) {
return *factory->NewStringFromStaticChars("und"); 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) { RUNTIME_FUNCTION(Runtime_IsInitializedIntlObjectOfType) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK_EQ(2, args.length()); DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, input, 0); 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(); Intl::Type expected_type = Intl::TypeFromInt(expected_type_int);
Handle<JSObject> obj = Handle<JSObject>::cast(input);
Handle<Symbol> marker = isolate->factory()->intl_initialized_marker_symbol(); return isolate->heap()->ToBoolean(
Handle<Object> tag = JSReceiver::GetDataProperty(obj, marker); Intl::IsObjectOfType(isolate, input, expected_type));
return isolate->heap()->ToBoolean(tag->IsString() &&
String::cast(*tag)->Equals(*expected_type));
} }
RUNTIME_FUNCTION(Runtime_MarkAsInitializedIntlObjectOfType) { RUNTIME_FUNCTION(Runtime_MarkAsInitializedIntlObjectOfType) {
...@@ -210,7 +193,13 @@ RUNTIME_FUNCTION(Runtime_MarkAsInitializedIntlObjectOfType) { ...@@ -210,7 +193,13 @@ RUNTIME_FUNCTION(Runtime_MarkAsInitializedIntlObjectOfType) {
DCHECK_EQ(2, args.length()); DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSObject, input, 0); 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(); Handle<Symbol> marker = isolate->factory()->intl_initialized_marker_symbol();
JSObject::SetProperty(input, marker, type, LanguageMode::kStrict).Assert(); JSObject::SetProperty(input, marker, type, LanguageMode::kStrict).Assert();
......
...@@ -225,7 +225,6 @@ namespace internal { ...@@ -225,7 +225,6 @@ namespace internal {
F(InternalCompare, 3, 1) \ F(InternalCompare, 3, 1) \
F(InternalDateFormat, 2, 1) \ F(InternalDateFormat, 2, 1) \
F(InternalNumberFormat, 2, 1) \ F(InternalNumberFormat, 2, 1) \
F(IsInitializedIntlObject, 1, 1) \
F(IsInitializedIntlObjectOfType, 2, 1) \ F(IsInitializedIntlObjectOfType, 2, 1) \
F(MarkAsInitializedIntlObjectOfType, 2, 1) \ F(MarkAsInitializedIntlObjectOfType, 2, 1) \
F(PluralRulesSelect, 2, 1) \ F(PluralRulesSelect, 2, 1) \
......
...@@ -183,15 +183,13 @@ TEST(GetOptions) { ...@@ -183,15 +183,13 @@ TEST(GetOptions) {
bool ScriptTagWasRemoved(std::string locale, std::string expected) { bool ScriptTagWasRemoved(std::string locale, std::string expected) {
std::string without_script_tag; std::string without_script_tag;
bool didShorten = bool didShorten = Intl::RemoveLocaleScriptTag(locale, &without_script_tag);
IntlUtil::RemoveLocaleScriptTag(locale, &without_script_tag);
return didShorten && expected == without_script_tag; return didShorten && expected == without_script_tag;
} }
bool ScriptTagWasNotRemoved(std::string locale) { bool ScriptTagWasNotRemoved(std::string locale) {
std::string without_script_tag; std::string without_script_tag;
bool didShorten = bool didShorten = Intl::RemoveLocaleScriptTag(locale, &without_script_tag);
IntlUtil::RemoveLocaleScriptTag(locale, &without_script_tag);
return !didShorten && without_script_tag.empty(); return !didShorten && without_script_tag.empty();
} }
...@@ -209,23 +207,61 @@ TEST(RemoveLocaleScriptTag) { ...@@ -209,23 +207,61 @@ TEST(RemoveLocaleScriptTag) {
TEST(GetAvailableLocales) { TEST(GetAvailableLocales) {
std::set<std::string> locales; std::set<std::string> locales;
locales = IntlUtil::GetAvailableLocales(IcuService::kBreakIterator); locales = Intl::GetAvailableLocales(IcuService::kBreakIterator);
CHECK(locales.count("en-US")); CHECK(locales.count("en-US"));
CHECK(!locales.count("abcdefg")); CHECK(!locales.count("abcdefg"));
locales = IntlUtil::GetAvailableLocales(IcuService::kCollator); locales = Intl::GetAvailableLocales(IcuService::kCollator);
CHECK(locales.count("en-US")); CHECK(locales.count("en-US"));
locales = IntlUtil::GetAvailableLocales(IcuService::kDateFormat); locales = Intl::GetAvailableLocales(IcuService::kDateFormat);
CHECK(locales.count("en-US")); CHECK(locales.count("en-US"));
locales = IntlUtil::GetAvailableLocales(IcuService::kNumberFormat); locales = Intl::GetAvailableLocales(IcuService::kNumberFormat);
CHECK(locales.count("en-US")); CHECK(locales.count("en-US"));
locales = IntlUtil::GetAvailableLocales(IcuService::kPluralRules); locales = Intl::GetAvailableLocales(IcuService::kPluralRules);
CHECK(locales.count("en-US")); 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 internal
} // namespace v8 } // namespace v8
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment