Commit 363fe1eb authored by Sathya Gunasekaran's avatar Sathya Gunasekaran Committed by Commit Bot

[Intl] Optimize Intl.Collator

This patch ports most of the Intl.Collator from JS to C++.

The Intl.Collator object no longer stores all the resolved
values. Instead these are looked up on demand as part of
Intl.Collator.prototype.resolvedOptions(), saving several words. In
the future, we can cache the result of the resolvedOptions as well.

In this patch, we use ICU to do parsing of the unicode extension in
the bcp47 language tag instead of using a custom extension parser.

This patch also fixes several spec compliance bugs as well.

Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng
Change-Id: Iaaa7be4a628404da1bd83d882e04a2c6de70ebd9
Bug: v8:5751, v8:7480
Reviewed-on: https://chromium-review.googlesource.com/1165084
Commit-Queue: Sathya Gunasekaran <gsathya@chromium.org>
Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54965}
parent 18a0a974
......@@ -2158,6 +2158,9 @@ v8_source_set("v8_base") {
"src/objects/intl-objects.h",
"src/objects/js-array-inl.h",
"src/objects/js-array.h",
"src/objects/js-collator-inl.h",
"src/objects/js-collator.cc",
"src/objects/js-collator.h",
"src/objects/js-collection-inl.h",
"src/objects/js-collection.h",
"src/objects/js-generator-inl.h",
......@@ -2862,6 +2865,9 @@ v8_source_set("v8_base") {
"src/objects/intl-objects-inl.h",
"src/objects/intl-objects.cc",
"src/objects/intl-objects.h",
"src/objects/js-collator-inl.h",
"src/objects/js-collator.cc",
"src/objects/js-collator.h",
"src/objects/js-list-format-inl.h",
"src/objects/js-list-format.cc",
"src/objects/js-list-format.h",
......
......@@ -24,6 +24,7 @@
#include "src/objects/hash-table-inl.h"
#ifdef V8_INTL_SUPPORT
#include "src/objects/intl-objects.h"
#include "src/objects/js-collator.h"
#include "src/objects/js-list-format.h"
#include "src/objects/js-locale.h"
#endif // V8_INTL_SUPPORT
......@@ -2935,9 +2936,11 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
{
Handle<JSFunction> collator_constructor = InstallFunction(
isolate_, intl, "Collator", JS_OBJECT_TYPE, Collator::kSize, 0,
factory->the_hole_value(), Builtins::kIllegal);
native_context()->set_intl_collator_function(*collator_constructor);
isolate_, intl, "Collator", JS_INTL_COLLATOR_TYPE, JSCollator::kSize,
0, factory->the_hole_value(), Builtins::kCollatorConstructor);
collator_constructor->shared()->DontAdaptArguments();
InstallWithIntrinsicDefaultProto(isolate_, collator_constructor,
Context::INTL_COLLATOR_FUNCTION_INDEX);
Handle<JSObject> prototype(
JSObject::cast(collator_constructor->prototype()), isolate_);
......
......@@ -1324,6 +1324,8 @@ namespace internal {
BUILTIN_LIST_BASE(CPP, API, TFJ, TFC, TFS, TFH, ASM) \
BUILTIN_LIST_FROM_DSL(CPP, API, TFJ, TFC, TFS, TFH, ASM) \
\
/* ecma402 #sec-intl.collator */ \
CPP(CollatorConstructor) \
TFS(StringToLowerCaseIntl, kString) \
/* ES #sec-string.prototype.tolowercase */ \
TFJ(StringPrototypeToLowerCaseIntl, 0, kReceiver) \
......
......@@ -15,6 +15,7 @@
#include "src/intl.h"
#include "src/objects-inl.h"
#include "src/objects/intl-objects.h"
#include "src/objects/js-collator-inl.h"
#include "src/objects/js-list-format-inl.h"
#include "src/objects/js-locale-inl.h"
#include "src/objects/js-plural-rules-inl.h"
......@@ -1131,5 +1132,35 @@ BUILTIN(PluralRulesConstructor) {
locales, options));
}
BUILTIN(CollatorConstructor) {
HandleScope scope(isolate);
Handle<JSReceiver> new_target;
// 1. If NewTarget is undefined, let newTarget be the active
// function object, else let newTarget be NewTarget.
if (args.new_target()->IsUndefined(isolate)) {
new_target = args.target();
} else {
new_target = Handle<JSReceiver>::cast(args.new_target());
}
// [[Construct]]
Handle<JSFunction> target = args.target();
Handle<Object> locales = args.atOrUndefined(isolate, 1);
Handle<Object> options = args.atOrUndefined(isolate, 2);
// 5. Let collator be ? OrdinaryCreateFromConstructor(newTarget,
// "%CollatorPrototype%", internalSlotsList).
Handle<JSObject> collator_obj;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, collator_obj,
JSObject::New(target, new_target));
Handle<JSCollator> collator = Handle<JSCollator>::cast(collator_obj);
collator->set_flags(0);
// 6. Return ? InitializeCollator(collator, locales, options).
RETURN_RESULT_OR_FAILURE(isolate, JSCollator::InitializeCollator(
isolate, collator, locales, options));
}
} // namespace internal
} // namespace v8
......@@ -207,6 +207,7 @@ Type::bitset BitsetType::Lub(HeapObjectType const& type) {
case JS_MESSAGE_OBJECT_TYPE:
case JS_DATE_TYPE:
#ifdef V8_INTL_SUPPORT
case JS_INTL_COLLATOR_TYPE:
case JS_INTL_LIST_FORMAT_TYPE:
case JS_INTL_LOCALE_TYPE:
case JS_INTL_PLURAL_RULES_TYPE:
......
......@@ -37,9 +37,11 @@
V(call_string, "call") \
V(callee_string, "callee") \
V(caller_string, "caller") \
V(caseFirst_string, "caseFirst") \
V(cell_value_string, "%cell_value") \
V(char_at_string, "CharAt") \
V(closure_string, "(closure)") \
V(collation_string, "collation") \
V(column_string, "column") \
V(CompileError_string, "CompileError") \
V(configurable_string, "configurable") \
......@@ -98,6 +100,7 @@
V(has_string, "has") \
V(hour_string, "hour") \
V(ignoreCase_string, "ignoreCase") \
V(ignorePunctuation_string, "ignorePunctuation") \
V(illegal_access_string, "illegal access") \
V(illegal_argument_string, "illegal argument") \
V(index_string, "index") \
......@@ -182,8 +185,9 @@
V(script_string, "script") \
V(short_string, "short") \
V(second_string, "second") \
V(set_space_string, "set ") \
V(Set_string, "Set") \
V(sensitivity_string, "sensitivity") \
V(set_space_string, "set ") \
V(set_string, "set") \
V(SetIterator_string, "Set Iterator") \
V(setPrototypeOf_string, "setPrototypeOf") \
......@@ -222,6 +226,7 @@
V(unicode_string, "unicode") \
V(unit_string, "unit") \
V(URIError_string, "URIError") \
V(usage_string, "usage") \
V(use_asm_string, "use asm") \
V(use_strict_string, "use strict") \
V(value_string, "value") \
......
......@@ -426,7 +426,12 @@ function attemptSingleLookup(availableLocales, requestedLocale) {
var extensionMatch = %regexp_internal_match(
GetUnicodeExtensionRE(), requestedLocale);
var extension = IS_NULL(extensionMatch) ? '' : extensionMatch[0];
return {__proto__: null, locale: availableLocale, extension: extension};
return {
__proto__: null,
locale: availableLocale,
extension: extension,
localeWithExtension: availableLocale + extension,
};
}
return UNDEFINED;
}
......@@ -463,7 +468,8 @@ function lookupMatcher(service, requestedLocales) {
return {
__proto__: null,
locale: 'und',
extension: ''
extension: '',
localeWithExtension: 'und',
};
}
......@@ -780,141 +786,13 @@ DEFINE_METHOD(
}
);
/**
* Initializes the given object so it's a valid Collator instance.
* Useful for subclassing.
*/
function CreateCollator(locales, options) {
if (IS_UNDEFINED(options)) {
options = {__proto__: null};
}
var getOption = getGetOption(options, 'collator');
var internalOptions = {__proto__: null};
%DefineWEProperty(internalOptions, 'usage', getOption(
'usage', 'string', ['sort', 'search'], 'sort'));
var sensitivity = getOption('sensitivity', 'string',
['base', 'accent', 'case', 'variant']);
if (IS_UNDEFINED(sensitivity) && internalOptions.usage === 'sort') {
sensitivity = 'variant';
}
%DefineWEProperty(internalOptions, 'sensitivity', sensitivity);
%DefineWEProperty(internalOptions, 'ignorePunctuation', getOption(
'ignorePunctuation', 'boolean', UNDEFINED, false));
var locale = resolveLocale('collator', locales, options);
// TODO(jshin): ICU now can take kb, kc, etc. Switch over to using ICU
// directly. See Collator::InitializeCollator and
// Collator::CreateICUCollator in src/objects/intl-objects.cc
// ICU can't take kb, kc... parameters through localeID, so we need to pass
// them as options.
// One exception is -co- which has to be part of the extension, but only for
// usage: sort, and its value can't be 'standard' or 'search'.
var extensionMap = parseExtension(locale.extension);
/**
* Map of Unicode extensions to option properties, and their values and types,
* for a collator.
*/
var COLLATOR_KEY_MAP = {
__proto__: null,
'kn': { __proto__: null, 'property': 'numeric', 'type': 'boolean'},
'kf': { __proto__: null, 'property': 'caseFirst', 'type': 'string',
'values': ['false', 'lower', 'upper']}
};
setOptions(
options, extensionMap, COLLATOR_KEY_MAP, getOption, internalOptions);
var collation = 'default';
var extension = '';
if (HAS_OWN_PROPERTY(extensionMap, 'co') && internalOptions.usage === 'sort') {
/**
* Allowed -u-co- values. List taken from:
* http://unicode.org/repos/cldr/trunk/common/bcp47/collation.xml
*/
var ALLOWED_CO_VALUES = [
'big5han', 'dict', 'direct', 'ducet', 'gb2312', 'phonebk', 'phonetic',
'pinyin', 'reformed', 'searchjl', 'stroke', 'trad', 'unihan', 'zhuyin'
];
if (%ArrayIndexOf(ALLOWED_CO_VALUES, extensionMap.co, 0) !== -1) {
extension = '-u-co-' + extensionMap.co;
// ICU can't tell us what the collation is, so save user's input.
collation = extensionMap.co;
}
} else if (internalOptions.usage === 'search') {
extension = '-u-co-search';
}
%DefineWEProperty(internalOptions, 'collation', collation);
var requestedLocale = locale.locale + extension;
// We define all properties C++ code may produce, to prevent security
// problems. If malicious user decides to redefine Object.prototype.locale
// we can't just use plain x.locale = 'us' or in C++ Set("locale", "us").
// %object_define_properties will either succeed defining or throw an error.
var resolved = %object_define_properties({__proto__: null}, {
caseFirst: {writable: true},
collation: {value: internalOptions.collation, writable: true},
ignorePunctuation: {writable: true},
locale: {writable: true},
numeric: {writable: true},
requestedLocale: {value: requestedLocale, writable: true},
sensitivity: {writable: true},
strength: {writable: true},
usage: {value: internalOptions.usage, writable: true}
});
var collator = %CreateCollator(requestedLocale, internalOptions, resolved);
%MarkAsInitializedIntlObjectOfType(collator, COLLATOR_TYPE);
collator[resolvedSymbol] = resolved;
return collator;
}
/**
* Constructs Intl.Collator object given optional locales and options
* parameters.
*
* @constructor
*/
function CollatorConstructor() {
return IntlConstruct(this, GlobalIntlCollator, CreateCollator, new.target,
arguments);
}
%SetCode(GlobalIntlCollator, CollatorConstructor);
/**
* Collator resolvedOptions method.
*/
DEFINE_METHOD(
GlobalIntlCollator.prototype,
resolvedOptions() {
var methodName = 'resolvedOptions';
if(!IS_RECEIVER(this)) {
throw %make_type_error(kIncompatibleMethodReceiver, methodName, this);
}
var coll = %IntlUnwrapReceiver(this, COLLATOR_TYPE, GlobalIntlCollator,
methodName, false);
return {
locale: coll[resolvedSymbol].locale,
usage: coll[resolvedSymbol].usage,
sensitivity: coll[resolvedSymbol].sensitivity,
ignorePunctuation: coll[resolvedSymbol].ignorePunctuation,
numeric: coll[resolvedSymbol].numeric,
caseFirst: coll[resolvedSymbol].caseFirst,
collation: coll[resolvedSymbol].collation
};
return %CollatorResolvedOptions(this);
}
);
......
......@@ -726,6 +726,7 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) {
case JS_MESSAGE_OBJECT_TYPE:
case JS_BOUND_FUNCTION_TYPE:
#ifdef V8_INTL_SUPPORT
case JS_INTL_COLLATOR_TYPE:
case JS_INTL_LIST_FORMAT_TYPE:
case JS_INTL_LOCALE_TYPE:
case JS_INTL_PLURAL_RULES_TYPE:
......
......@@ -15,6 +15,9 @@
#include "src/objects-inl.h"
#include "src/objects/arguments-inl.h"
#include "src/objects/bigint.h"
#ifdef V8_INTL_SUPPORT
#include "src/objects/js-collator-inl.h"
#endif // V8_INTL_SUPPORT
#include "src/objects/data-handler-inl.h"
#include "src/objects/debug-objects-inl.h"
#include "src/objects/hash-table-inl.h"
......@@ -353,6 +356,9 @@ void HeapObject::HeapObjectVerify(Isolate* isolate) {
CodeDataContainer::cast(this)->CodeDataContainerVerify(isolate);
break;
#ifdef V8_INTL_SUPPORT
case JS_INTL_COLLATOR_TYPE:
JSCollator::cast(this)->JSCollatorVerify(isolate);
break;
case JS_INTL_LIST_FORMAT_TYPE:
JSListFormat::cast(this)->JSListFormatVerify(isolate);
break;
......@@ -1868,6 +1874,13 @@ void InterpreterData::InterpreterDataVerify(Isolate* isolate) {
}
#ifdef V8_INTL_SUPPORT
void JSCollator::JSCollatorVerify(Isolate* isolate) {
CHECK(IsJSCollator());
JSObjectVerify(isolate);
VerifyObjectField(isolate, kICUCollatorOffset);
VerifyObjectField(isolate, kFlagsOffset);
}
void JSListFormat::JSListFormatVerify(Isolate* isolate) {
JSObjectVerify(isolate);
VerifyObjectField(isolate, kLocaleOffset);
......
......@@ -217,6 +217,7 @@ namespace internal {
#ifdef V8_INTL_SUPPORT
#define INSTANCE_TYPE_LIST(V) \
INSTANCE_TYPE_LIST_BEFORE_INTL(V) \
V(JS_INTL_COLLATOR_TYPE) \
V(JS_INTL_LIST_FORMAT_TYPE) \
V(JS_INTL_LOCALE_TYPE) \
V(JS_INTL_PLURAL_RULES_TYPE) \
......
......@@ -14,6 +14,9 @@
#include "src/interpreter/bytecodes.h"
#include "src/objects-inl.h"
#include "src/objects/arguments-inl.h"
#ifdef V8_INTL_SUPPORT
#include "src/objects/js-collator-inl.h"
#endif // V8_INTL_SUPPORT
#include "src/objects/data-handler-inl.h"
#include "src/objects/debug-objects-inl.h"
#include "src/objects/hash-table-inl.h"
......@@ -305,6 +308,9 @@ void HeapObject::HeapObjectPrint(std::ostream& os) { // NOLINT
JSDataView::cast(this)->JSDataViewPrint(os);
break;
#ifdef V8_INTL_SUPPORT
case JS_INTL_COLLATOR_TYPE:
JSCollator::cast(this)->JSCollatorPrint(os);
break;
case JS_INTL_LIST_FORMAT_TYPE:
JSListFormat::cast(this)->JSListFormatPrint(os);
break;
......@@ -1955,6 +1961,13 @@ void Script::ScriptPrint(std::ostream& os) { // NOLINT
}
#ifdef V8_INTL_SUPPORT
void JSCollator::JSCollatorPrint(std::ostream& os) { // NOLINT
JSObjectPrintHeader(os, this, "JSCollator");
os << "\n - usage: " << JSCollator::UsageToString(usage());
os << "\n - icu collator: " << Brief(icu_collator());
os << "\n";
}
void JSListFormat::JSListFormatPrint(std::ostream& os) { // NOLINT
JSObjectPrintHeader(os, this, "JSListFormat");
os << "\n - locale: " << Brief(locale());
......
......@@ -59,6 +59,9 @@
#include "src/objects/debug-objects-inl.h"
#include "src/objects/frame-array-inl.h"
#include "src/objects/hash-table-inl.h"
#ifdef V8_INTL_SUPPORT
#include "src/objects/js-collator.h"
#endif // V8_INTL_SUPPORT
#include "src/objects/js-collection-inl.h"
#include "src/objects/js-generator-inl.h"
#ifdef V8_INTL_SUPPORT
......@@ -1419,6 +1422,8 @@ int JSObject::GetHeaderSize(InstanceType type,
case JS_MODULE_NAMESPACE_TYPE:
return JSModuleNamespace::kHeaderSize;
#ifdef V8_INTL_SUPPORT
case JS_INTL_COLLATOR_TYPE:
return JSCollator::kSize;
case JS_INTL_LIST_FORMAT_TYPE:
return JSListFormat::kSize;
case JS_INTL_LOCALE_TYPE:
......@@ -3171,6 +3176,7 @@ VisitorId Map::GetVisitorId(Map* map) {
case JS_REGEXP_TYPE:
case JS_REGEXP_STRING_ITERATOR_TYPE:
#ifdef V8_INTL_SUPPORT
case JS_INTL_COLLATOR_TYPE:
case JS_INTL_LIST_FORMAT_TYPE:
case JS_INTL_LOCALE_TYPE:
case JS_INTL_PLURAL_RULES_TYPE:
......@@ -13099,6 +13105,7 @@ bool CanSubclassHaveInobjectProperties(InstanceType instance_type) {
case JS_FUNCTION_TYPE:
case JS_GENERATOR_OBJECT_TYPE:
#ifdef V8_INTL_SUPPORT
case JS_INTL_COLLATOR_TYPE:
case JS_INTL_PLURAL_RULES_TYPE:
#endif
case JS_ASYNC_GENERATOR_OBJECT_TYPE:
......
......@@ -75,9 +75,10 @@
// - JSDate
// - JSMessageObject
// - JSModuleNamespace
// - JSListFormat // If V8_INTL_SUPPORT enabled.
// - JSLocale // If V8_INTL_SUPPORT enabled.
// - JSPluralRules // If V8_INTL_SUPPORT enabled.
// - JSCollator // If V8_INTL_SUPPORT enabled.
// - JSListFormat // If V8_INTL_SUPPORT enabled.
// - JSLocale // If V8_INTL_SUPPORT enabled.
// - JSPluralRules // If V8_INTL_SUPPORT enabled.
// - JSRelativeTimeFormat // If V8_INTL_SUPPORT enabled.
// - WasmGlobalObject
// - WasmInstanceObject
......@@ -583,6 +584,7 @@ enum InstanceType : uint16_t {
JS_DATA_VIEW_TYPE,
#ifdef V8_INTL_SUPPORT
JS_INTL_COLLATOR_TYPE,
JS_INTL_LIST_FORMAT_TYPE,
JS_INTL_LOCALE_TYPE,
JS_INTL_PLURAL_RULES_TYPE,
......@@ -700,6 +702,7 @@ class JSAsyncGeneratorObject;
class JSGlobalObject;
class JSGlobalProxy;
#ifdef V8_INTL_SUPPORT
class JSCollator;
class JSListFormat;
class JSLocale;
class JSPluralRules;
......@@ -911,6 +914,7 @@ class ZoneForwardList;
#ifdef V8_INTL_SUPPORT
#define HEAP_OBJECT_ORDINARY_TYPE_LIST(V) \
HEAP_OBJECT_ORDINARY_TYPE_LIST_BASE(V) \
V(JSCollator) \
V(JSListFormat) \
V(JSLocale) \
V(JSPluralRules) \
......@@ -1031,6 +1035,7 @@ class ZoneForwardList;
#define INSTANCE_TYPE_CHECKERS_SINGLE(V) \
INSTANCE_TYPE_CHECKERS_SINGLE_BASE(V) \
V(JSCollator, JS_INTL_COLLATOR_TYPE) \
V(JSListFormat, JS_INTL_LIST_FORMAT_TYPE) \
V(JSLocale, JS_INTL_LOCALE_TYPE) \
V(JSPluralRules, JS_INTL_PLURAL_RULES_TYPE) \
......
This diff is collapsed.
......@@ -117,26 +117,6 @@ class NumberFormat {
NumberFormat();
};
class Collator {
public:
// Create a collator for the specificied locale and options. Stores the
// collator in the provided collator_holder.
static icu::Collator* InitializeCollator(Isolate* isolate,
Handle<String> locale,
Handle<JSObject> options,
Handle<JSObject> resolved);
// Unpacks collator object from corresponding JavaScript object.
static icu::Collator* UnpackCollator(Handle<JSObject> obj);
// Layout description.
static const int kCollator = JSObject::kHeaderSize;
static const int kSize = kCollator + kPointerSize;
private:
Collator();
};
class V8BreakIterator {
public:
// Create a BreakIterator for the specificied locale and options. Returns the
......@@ -313,7 +293,7 @@ class Intl {
Handle<Object> locales, Handle<Object> options);
V8_WARN_UNUSED_RESULT static Handle<Object> InternalCompare(
Isolate* isolate, Handle<JSObject> collator, Handle<String> s1,
Isolate* isolate, Handle<JSCollator> collator, Handle<String> s1,
Handle<String> s2);
// ecma402/#sup-properties-of-the-number-prototype-object
......
// 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.
#ifndef V8_INTL_SUPPORT
#error Internationalization is expected to be enabled.
#endif // V8_INTL_SUPPORT
#ifndef V8_OBJECTS_JS_COLLATOR_INL_H_
#define V8_OBJECTS_JS_COLLATOR_INL_H_
#include "src/objects-inl.h"
#include "src/objects/js-collator.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
namespace v8 {
namespace internal {
ACCESSORS(JSCollator, icu_collator, Managed<icu::Collator>, kICUCollatorOffset)
SMI_ACCESSORS(JSCollator, flags, kFlagsOffset)
inline void JSCollator::set_usage(Usage usage) {
DCHECK_LT(usage, Usage::COUNT);
int hints = flags();
hints = UsageBits::update(hints, usage);
set_flags(hints);
}
inline JSCollator::Usage JSCollator::usage() const {
return UsageBits::decode(flags());
}
CAST_ACCESSOR(JSCollator);
} // namespace internal
} // namespace v8
#include "src/objects/object-macros-undef.h"
#endif // V8_OBJECTS_JS_COLLATOR_INL_H_
This diff is collapsed.
// 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.
#ifndef V8_INTL_SUPPORT
#error Internationalization is expected to be enabled.
#endif // V8_INTL_SUPPORT
#ifndef V8_OBJECTS_JS_COLLATOR_H_
#define V8_OBJECTS_JS_COLLATOR_H_
#include "src/heap/factory.h"
#include "src/isolate.h"
#include "src/objects.h"
#include "src/objects/intl-objects.h"
#include "src/objects/managed.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
namespace v8 {
namespace internal {
class JSCollator : public JSObject {
public:
// ecma402/#sec-initializecollator
V8_WARN_UNUSED_RESULT static MaybeHandle<JSCollator> InitializeCollator(
Isolate* isolate, Handle<JSCollator> collator, Handle<Object> locales,
Handle<Object> options);
// ecma402/#sec-intl.collator.prototype.resolvedoptions
static Handle<JSObject> ResolvedOptions(Isolate* isolate,
Handle<JSCollator> collator);
DECL_CAST(JSCollator)
DECL_PRINTER(JSCollator)
DECL_VERIFIER(JSCollator)
// [[Usage]] is one of the values "sort" or "search", identifying
// the collator usage.
enum class Usage {
SORT,
SEARCH,
COUNT
};
inline void set_usage(Usage usage);
inline Usage usage() const;
static const char* UsageToString(Usage usage);
// Layout description.
#define JS_COLLATOR_FIELDS(V) \
V(kICUCollatorOffset, kPointerSize) \
V(kFlagsOffset, kPointerSize) \
/* Total size. */ \
V(kSize, 0)
DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize, JS_COLLATOR_FIELDS)
#undef JS_COLLATOR_FIELDS
// Bit positions in |flags|.
#define FLAGS_BIT_FIELDS(V, _) V(UsageBits, Usage, 1, _)
DEFINE_BIT_FIELDS(FLAGS_BIT_FIELDS)
#undef FLAGS_BIT_FIELDS
STATIC_ASSERT(Usage::SORT <= UsageBits::kMax);
STATIC_ASSERT(Usage::SEARCH <= UsageBits::kMax);
DECL_ACCESSORS(icu_collator, Managed<icu::Collator>)
DECL_INT_ACCESSORS(flags)
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSCollator);
};
} // namespace internal
} // namespace v8
#include "src/objects/object-macros-undef.h"
#endif // V8_OBJECTS_JS_COLLATOR_H_
......@@ -20,6 +20,7 @@
#include "src/messages.h"
#include "src/objects/intl-objects-inl.h"
#include "src/objects/intl-objects.h"
#include "src/objects/js-collator-inl.h"
#include "src/objects/js-plural-rules-inl.h"
#include "src/objects/managed.h"
#include "src/runtime/runtime-utils.h"
......@@ -250,42 +251,37 @@ RUNTIME_FUNCTION(Runtime_CurrencyDigits) {
return *Intl::CurrencyDigits(isolate, currency);
}
RUNTIME_FUNCTION(Runtime_CreateCollator) {
RUNTIME_FUNCTION(Runtime_InternalCompare) {
HandleScope scope(isolate);
DCHECK_EQ(3, args.length());
CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
Handle<JSFunction> constructor(
isolate->native_context()->intl_collator_function(), isolate);
Handle<JSObject> collator_holder;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, collator_holder,
JSObject::New(constructor, constructor));
icu::Collator* collator =
Collator::InitializeCollator(isolate, locale, options, resolved);
CHECK_NOT_NULL(collator);
Handle<Managed<icu::Collator>> managed =
Managed<icu::Collator>::FromRawPtr(isolate, 0, collator);
collator_holder->SetEmbedderField(0, *managed);
CONVERT_ARG_HANDLE_CHECKED(JSCollator, collator, 0);
CONVERT_ARG_HANDLE_CHECKED(String, string1, 1);
CONVERT_ARG_HANDLE_CHECKED(String, string2, 2);
return *collator_holder;
return *Intl::InternalCompare(isolate, collator, string1, string2);
}
RUNTIME_FUNCTION(Runtime_InternalCompare) {
RUNTIME_FUNCTION(Runtime_CollatorResolvedOptions) {
HandleScope scope(isolate);
DCHECK_EQ(3, args.length());
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, collator_obj, 0);
CONVERT_ARG_HANDLE_CHECKED(JSObject, collator_holder, 0);
CONVERT_ARG_HANDLE_CHECKED(String, string1, 1);
CONVERT_ARG_HANDLE_CHECKED(String, string2, 2);
return *Intl::InternalCompare(isolate, collator_holder, string1, string2);
// 3. If pr does not have an [[InitializedCollator]] internal
// slot, throw a TypeError exception.
if (!collator_obj->IsJSCollator()) {
Handle<String> method_str = isolate->factory()->NewStringFromStaticChars(
"Intl.Collator.prototype.resolvedOptions");
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
method_str, collator_obj));
}
Handle<JSCollator> collator = Handle<JSCollator>::cast(collator_obj);
return *JSCollator::ResolvedOptions(isolate, collator);
}
RUNTIME_FUNCTION(Runtime_PluralRulesResolvedOptions) {
......
......@@ -209,8 +209,8 @@ namespace internal {
F(BreakIteratorFirst, 1, 1) \
F(BreakIteratorNext, 1, 1) \
F(CanonicalizeLanguageTag, 1, 1) \
F(CollatorResolvedOptions, 1, 1) \
F(CreateBreakIterator, 3, 1) \
F(CreateCollator, 3, 1) \
F(CreateDateTimeFormat, 3, 1) \
F(CreateNumberFormat, 3, 1) \
F(DefineWEProperty, 3, 1) \
......@@ -231,7 +231,7 @@ namespace internal {
F(StringToUpperCaseIntl, 1, 1)
#else
#define FOR_EACH_INTRINSIC_INTL(F)
#endif
#endif // V8_INTL_SUPPORT
#define FOR_EACH_INTRINSIC_INTERNAL(F) \
F(AllocateInNewSpace, 1, 1) \
......
......@@ -48,8 +48,6 @@ var collatorBraket = new Intl.Collator({});
assertEquals(options.locale, collatorBraket.resolvedOptions().locale);
var collatorWithOptions = new Intl.Collator(undefined, {usage: 'search'});
assertLanguageTag(%GetDefaultICULocale(),
collatorWithOptions.resolvedOptions().locale);
assertNotNull(
%regexp_internal_match(/-u(-[a-zA-Z]+-[a-zA-Z]+)*-co-search/,
collatorWithOptions.resolvedOptions().locale));
var locale = collatorWithOptions.resolvedOptions().locale;
assertLanguageTag(%GetDefaultICULocale(), locale);
assertEquals(locale.indexOf('-co-search'), -1);
......@@ -61,5 +61,3 @@ properties.forEach(function(prop) {
});
taintProperties(properties);
var locale = Intl.Collator().resolvedOptions().locale;
......@@ -419,10 +419,6 @@
'intl402/NumberFormat/prototype/format/format-fraction-digits': [FAIL],
'intl402/NumberFormat/prototype/format/format-significant-digits': [FAIL],
# https://bugs.chromium.org/p/v8/issues/detail?id=7480
'intl402/Collator/unicode-ext-seq-in-private-tag': [FAIL],
'intl402/Collator/unicode-ext-seq-with-attribute': [FAIL],
# https://bugs.chromium.org/p/v8/issues/detail?id=7481
'intl402/NumberFormat/ignore-invalid-unicode-ext-values': [FAIL],
'intl402/DateTimeFormat/ignore-invalid-unicode-ext-values': [FAIL],
......
......@@ -159,17 +159,18 @@ INSTANCE_TYPES = {
1081: "JS_WEAK_SET_TYPE",
1082: "JS_TYPED_ARRAY_TYPE",
1083: "JS_DATA_VIEW_TYPE",
1084: "JS_INTL_LIST_FORMAT_TYPE",
1085: "JS_INTL_LOCALE_TYPE",
1086: "JS_INTL_PLURAL_RULES_TYPE",
1087: "JS_INTL_RELATIVE_TIME_FORMAT_TYPE",
1088: "WASM_GLOBAL_TYPE",
1089: "WASM_INSTANCE_TYPE",
1090: "WASM_MEMORY_TYPE",
1091: "WASM_MODULE_TYPE",
1092: "WASM_TABLE_TYPE",
1093: "JS_BOUND_FUNCTION_TYPE",
1094: "JS_FUNCTION_TYPE",
1084: "JS_INTL_COLLATOR_TYPE",
1085: "JS_INTL_LIST_FORMAT_TYPE",
1086: "JS_INTL_LOCALE_TYPE",
1087: "JS_INTL_PLURAL_RULES_TYPE",
1088: "JS_INTL_RELATIVE_TIME_FORMAT_TYPE",
1089: "WASM_GLOBAL_TYPE",
1090: "WASM_INSTANCE_TYPE",
1091: "WASM_MEMORY_TYPE",
1092: "WASM_MODULE_TYPE",
1093: "WASM_TABLE_TYPE",
1094: "JS_BOUND_FUNCTION_TYPE",
1095: "JS_FUNCTION_TYPE",
}
# List of known V8 maps.
......@@ -284,33 +285,33 @@ KNOWN_MAPS = {
("RO_SPACE", 0x047b1): (171, "Tuple2Map"),
("RO_SPACE", 0x04ae9): (161, "InterceptorInfoMap"),
("RO_SPACE", 0x04bf1): (169, "ScriptMap"),
("RO_SPACE", 0x09a19): (154, "AccessorInfoMap"),
("RO_SPACE", 0x09a69): (153, "AccessCheckInfoMap"),
("RO_SPACE", 0x09ab9): (155, "AccessorPairMap"),
("RO_SPACE", 0x09b09): (156, "AliasedArgumentsEntryMap"),
("RO_SPACE", 0x09b59): (157, "AllocationMementoMap"),
("RO_SPACE", 0x09ba9): (158, "AsyncGeneratorRequestMap"),
("RO_SPACE", 0x09bf9): (159, "DebugInfoMap"),
("RO_SPACE", 0x09c49): (160, "FunctionTemplateInfoMap"),
("RO_SPACE", 0x09c99): (162, "InterpreterDataMap"),
("RO_SPACE", 0x09ce9): (163, "ModuleInfoEntryMap"),
("RO_SPACE", 0x09d39): (164, "ModuleMap"),
("RO_SPACE", 0x09d89): (165, "ObjectTemplateInfoMap"),
("RO_SPACE", 0x09dd9): (166, "PromiseCapabilityMap"),
("RO_SPACE", 0x09e29): (167, "PromiseReactionMap"),
("RO_SPACE", 0x09e79): (168, "PrototypeInfoMap"),
("RO_SPACE", 0x09ec9): (170, "StackFrameInfoMap"),
("RO_SPACE", 0x09f19): (172, "Tuple3Map"),
("RO_SPACE", 0x09f69): (173, "ArrayBoilerplateDescriptionMap"),
("RO_SPACE", 0x09fb9): (174, "WasmDebugInfoMap"),
("RO_SPACE", 0x0a009): (175, "WasmExportedFunctionDataMap"),
("RO_SPACE", 0x0a059): (176, "CallableTaskMap"),
("RO_SPACE", 0x0a0a9): (177, "CallbackTaskMap"),
("RO_SPACE", 0x0a0f9): (178, "PromiseFulfillReactionJobTaskMap"),
("RO_SPACE", 0x0a149): (179, "PromiseRejectReactionJobTaskMap"),
("RO_SPACE", 0x0a199): (180, "PromiseResolveThenableJobTaskMap"),
("RO_SPACE", 0x0a1e9): (181, "AllocationSiteMap"),
("RO_SPACE", 0x0a239): (181, "AllocationSiteMap"),
("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"),
("MAP_SPACE", 0x02201): (1057, "ExternalMap"),
("MAP_SPACE", 0x02251): (1072, "JSMessageObjectMap"),
}
......
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