Commit 9c7ec98a authored by Frank Tang's avatar Frank Tang Committed by Commit Bot

[Intl] Move NumberFormat to JSNumberFormat

Bug: v8:7979

TBR: benedikt@chromium.org
Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng;luci.chromium.try:linux_chromium_rel_ng
Change-Id: I9d5181c15b56de3bc5288d11bd83e55157c7a610
Reviewed-on: https://chromium-review.googlesource.com/1168518
Commit-Queue: Sathya Gunasekaran <gsathya@chromium.org>
Reviewed-by: 's avatarSathya Gunasekaran <gsathya@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55621}
parent 71f14bd0
...@@ -2191,6 +2191,9 @@ v8_source_set("v8_base") { ...@@ -2191,6 +2191,9 @@ v8_source_set("v8_base") {
"src/objects/js-locale-inl.h", "src/objects/js-locale-inl.h",
"src/objects/js-locale.cc", "src/objects/js-locale.cc",
"src/objects/js-locale.h", "src/objects/js-locale.h",
"src/objects/js-number-format-inl.h",
"src/objects/js-number-format.cc",
"src/objects/js-number-format.h",
"src/objects/js-plural-rules-inl.h", "src/objects/js-plural-rules-inl.h",
"src/objects/js-plural-rules.cc", "src/objects/js-plural-rules.cc",
"src/objects/js-plural-rules.h", "src/objects/js-plural-rules.h",
...@@ -2902,6 +2905,9 @@ v8_source_set("v8_base") { ...@@ -2902,6 +2905,9 @@ v8_source_set("v8_base") {
"src/objects/js-locale-inl.h", "src/objects/js-locale-inl.h",
"src/objects/js-locale.cc", "src/objects/js-locale.cc",
"src/objects/js-locale.h", "src/objects/js-locale.h",
"src/objects/js-number-format-inl.h",
"src/objects/js-number-format.cc",
"src/objects/js-number-format.h",
"src/objects/js-plural-rules-inl.h", "src/objects/js-plural-rules-inl.h",
"src/objects/js-plural-rules.cc", "src/objects/js-plural-rules.cc",
"src/objects/js-plural-rules.h", "src/objects/js-plural-rules.h",
......
...@@ -24,16 +24,19 @@ ...@@ -24,16 +24,19 @@
#include "src/objects/hash-table-inl.h" #include "src/objects/hash-table-inl.h"
#ifdef V8_INTL_SUPPORT #ifdef V8_INTL_SUPPORT
#include "src/objects/intl-objects.h" #include "src/objects/intl-objects.h"
#endif // V8_INTL_SUPPORT
#include "src/objects/js-array-buffer-inl.h"
#include "src/objects/js-array-inl.h"
#ifdef V8_INTL_SUPPORT
#include "src/objects/js-collator.h" #include "src/objects/js-collator.h"
#include "src/objects/js-list-format.h" #include "src/objects/js-list-format.h"
#include "src/objects/js-locale.h" #include "src/objects/js-locale.h"
#include "src/objects/js-number-format.h"
#include "src/objects/js-plural-rules.h"
#endif // V8_INTL_SUPPORT #endif // V8_INTL_SUPPORT
#include "src/objects/js-array-buffer-inl.h"
#include "src/objects/js-array-inl.h"
#include "src/objects/js-regexp-string-iterator.h" #include "src/objects/js-regexp-string-iterator.h"
#include "src/objects/js-regexp.h" #include "src/objects/js-regexp.h"
#ifdef V8_INTL_SUPPORT #ifdef V8_INTL_SUPPORT
#include "src/objects/js-plural-rules.h"
#include "src/objects/js-relative-time-format.h" #include "src/objects/js-relative-time-format.h"
#endif // V8_INTL_SUPPORT #endif // V8_INTL_SUPPORT
#include "src/objects/templates.h" #include "src/objects/templates.h"
...@@ -2925,10 +2928,14 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object, ...@@ -2925,10 +2928,14 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
{ {
Handle<JSFunction> number_format_constructor = InstallFunction( Handle<JSFunction> number_format_constructor = InstallFunction(
isolate_, intl, "NumberFormat", JS_OBJECT_TYPE, NumberFormat::kSize, isolate_, intl, "NumberFormat", JS_INTL_NUMBER_FORMAT_TYPE,
0, factory->the_hole_value(), Builtins::kIllegal); JSNumberFormat::kSize, 0, factory->the_hole_value(),
native_context()->set_intl_number_format_function( Builtins::kNumberFormatConstructor);
*number_format_constructor); number_format_constructor->shared()->set_length(0);
number_format_constructor->shared()->DontAdaptArguments();
InstallWithIntrinsicDefaultProto(
isolate_, number_format_constructor,
Context::INTL_NUMBER_FORMAT_FUNCTION_INDEX);
SimpleInstallFunction( SimpleInstallFunction(
isolate(), number_format_constructor, "supportedLocalesOf", isolate(), number_format_constructor, "supportedLocalesOf",
......
...@@ -1336,6 +1336,8 @@ namespace internal { ...@@ -1336,6 +1336,8 @@ namespace internal {
CPP(StringPrototypeToUpperCaseIntl) \ CPP(StringPrototypeToUpperCaseIntl) \
/* ES #sec-string.prototype.normalize */ \ /* ES #sec-string.prototype.normalize */ \
CPP(StringPrototypeNormalizeIntl) \ CPP(StringPrototypeNormalizeIntl) \
/* ecma402 #sec-intl.numberformat */ \
CPP(NumberFormatConstructor) \
/* ecma402 #sec-intl.numberformat.prototype.formattoparts */ \ /* ecma402 #sec-intl.numberformat.prototype.formattoparts */ \
CPP(NumberFormatPrototypeFormatToParts) \ CPP(NumberFormatPrototypeFormatToParts) \
/* ecma402 #sec-intl.datetimeformat.prototype.formattoparts */ \ /* ecma402 #sec-intl.datetimeformat.prototype.formattoparts */ \
......
...@@ -22,8 +22,10 @@ ...@@ -22,8 +22,10 @@
#include "src/objects/js-collator-inl.h" #include "src/objects/js-collator-inl.h"
#include "src/objects/js-list-format-inl.h" #include "src/objects/js-list-format-inl.h"
#include "src/objects/js-locale-inl.h" #include "src/objects/js-locale-inl.h"
#include "src/objects/js-number-format-inl.h"
#include "src/objects/js-plural-rules-inl.h" #include "src/objects/js-plural-rules-inl.h"
#include "src/objects/js-relative-time-format-inl.h" #include "src/objects/js-relative-time-format-inl.h"
#include "src/property-descriptor.h"
#include "unicode/datefmt.h" #include "unicode/datefmt.h"
#include "unicode/decimfmt.h" #include "unicode/decimfmt.h"
...@@ -475,16 +477,7 @@ BUILTIN(NumberFormatSupportedLocalesOf) { ...@@ -475,16 +477,7 @@ BUILTIN(NumberFormatSupportedLocalesOf) {
BUILTIN(NumberFormatPrototypeFormatToParts) { BUILTIN(NumberFormatPrototypeFormatToParts) {
const char* const method = "Intl.NumberFormat.prototype.formatToParts"; const char* const method = "Intl.NumberFormat.prototype.formatToParts";
HandleScope handle_scope(isolate); HandleScope handle_scope(isolate);
CHECK_RECEIVER(JSObject, number_format_holder, method); CHECK_RECEIVER(JSNumberFormat, number_format, method);
if (!Intl::IsObjectOfType(isolate, number_format_holder,
Intl::Type::kNumberFormat)) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate,
NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
isolate->factory()->NewStringFromAsciiChecked(method),
number_format_holder));
}
Handle<Object> x; Handle<Object> x;
if (args.length() >= 2) { if (args.length() >= 2) {
...@@ -494,12 +487,12 @@ BUILTIN(NumberFormatPrototypeFormatToParts) { ...@@ -494,12 +487,12 @@ BUILTIN(NumberFormatPrototypeFormatToParts) {
x = isolate->factory()->nan_value(); x = isolate->factory()->nan_value();
} }
icu::DecimalFormat* number_format = icu::NumberFormat* icu_number_format =
NumberFormat::UnpackNumberFormat(number_format_holder); number_format->icu_number_format()->raw();
CHECK_NOT_NULL(number_format); CHECK_NOT_NULL(icu_number_format);
RETURN_RESULT_OR_FAILURE( RETURN_RESULT_OR_FAILURE(
isolate, FormatNumberToParts(isolate, number_format, x->Number())); isolate, FormatNumberToParts(isolate, icu_number_format, x->Number()));
} }
BUILTIN(DateTimeFormatSupportedLocalesOf) { BUILTIN(DateTimeFormatSupportedLocalesOf) {
...@@ -570,6 +563,91 @@ Handle<JSFunction> CreateBoundFunction(Isolate* isolate, ...@@ -570,6 +563,91 @@ Handle<JSFunction> CreateBoundFunction(Isolate* isolate,
return new_bound_function; return new_bound_function;
} }
} // namespace } // namespace
BUILTIN(NumberFormatConstructor) {
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);
// 2. Let numberFormat be ? OrdinaryCreateFromConstructor(newTarget,
// "%NumberFormatPrototype%", « [[InitializedNumberFormat]], [[Locale]],
// [[NumberingSystem]], [[Style]], [[Currency]], [[CurrencyDisplay]],
// [[MinimumIntegerDigits]], [[MinimumFractionDigits]],
// [[MaximumFractionDigits]], [[MinimumSignificantDigits]],
// [[MaximumSignificantDigits]], [[UseGrouping]], [[PositivePattern]],
// [[NegativePattern]], [[BoundFormat]] »).
Handle<JSObject> number_format_obj;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, number_format_obj,
JSObject::New(target, new_target));
Handle<JSNumberFormat> number_format =
Handle<JSNumberFormat>::cast(number_format_obj);
number_format->set_flags(0);
// 3. Perform ? InitializeNumberFormat(numberFormat, locales, options).
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, number_format,
JSNumberFormat::InitializeNumberFormat(isolate, number_format, locales,
options));
// 4. Let this be the this value.
Handle<Object> receiver = args.receiver();
// 5. If NewTarget is undefined and ? InstanceofOperator(this, %NumberFormat%)
// is true, then
//
// Look up the intrinsic value that has been stored on the context.
Handle<Object> number_format_constructor =
isolate->intl_number_format_function();
// Call the instanceof function
Handle<Object> is_instance_of_obj;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, is_instance_of_obj,
Object::InstanceOf(isolate, receiver, number_format_constructor));
// Get the boolean value of the result
bool is_instance_of = is_instance_of_obj->BooleanValue(isolate);
if (args.new_target()->IsUndefined(isolate) && is_instance_of) {
if (!receiver->IsJSReceiver()) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
isolate->factory()->NewStringFromStaticChars(
"Intl.NumberFormat"),
receiver));
}
Handle<JSReceiver> rec = Handle<JSReceiver>::cast(receiver);
// a. Perform ? DefinePropertyOrThrow(this,
// %Intl%.[[FallbackSymbol]], PropertyDescriptor{ [[Value]]: numberFormat,
// [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }).
PropertyDescriptor desc;
desc.set_value(number_format);
desc.set_writable(false);
desc.set_enumerable(false);
desc.set_configurable(false);
Maybe<bool> success = JSReceiver::DefineOwnProperty(
isolate, rec, isolate->factory()->intl_fallback_symbol(), &desc,
kThrowOnError);
MAYBE_RETURN(success, ReadOnlyRoots(isolate).exception());
CHECK(success.FromJust());
// b. b. Return this.
return *receiver;
}
// 6. Return numberFormat.
return *number_format;
}
BUILTIN(NumberFormatPrototypeFormatNumber) { BUILTIN(NumberFormatPrototypeFormatNumber) {
const char* const method = "get Intl.NumberFormat.prototype.format"; const char* const method = "get Intl.NumberFormat.prototype.format";
...@@ -577,20 +655,14 @@ BUILTIN(NumberFormatPrototypeFormatNumber) { ...@@ -577,20 +655,14 @@ BUILTIN(NumberFormatPrototypeFormatNumber) {
// 1. Let nf be the this value. // 1. Let nf be the this value.
// 2. If Type(nf) is not Object, throw a TypeError exception. // 2. If Type(nf) is not Object, throw a TypeError exception.
CHECK_RECEIVER(JSReceiver, receiver, method); CHECK_RECEIVER(JSObject, format_holder, method);
// 3. Let nf be ? UnwrapNumberFormat(nf). // 3. Let nf be ? UnwrapNumberFormat(nf).
Handle<JSObject> number_format_holder; Handle<JSNumberFormat> nf;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION( ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, number_format_holder, isolate, nf, JSNumberFormat::UnwrapNumberFormat(isolate, format_holder));
NumberFormat::Unwrap(isolate, receiver, method));
DCHECK(Intl::IsObjectOfType(isolate, number_format_holder,
Intl::Type::kNumberFormat));
Handle<Object> bound_format = Handle<Object>( Handle<Object> bound_format = Handle<Object>(nf->bound_format(), isolate);
number_format_holder->GetEmbedderField(NumberFormat::kBoundFormatIndex),
isolate);
// 4. If nf.[[BoundFormat]] is undefined, then // 4. If nf.[[BoundFormat]] is undefined, then
if (!bound_format->IsUndefined(isolate)) { if (!bound_format->IsUndefined(isolate)) {
...@@ -599,13 +671,11 @@ BUILTIN(NumberFormatPrototypeFormatNumber) { ...@@ -599,13 +671,11 @@ BUILTIN(NumberFormatPrototypeFormatNumber) {
return *bound_format; return *bound_format;
} }
Handle<JSFunction> new_bound_format_function = Handle<JSFunction> new_bound_format_function = CreateBoundFunction(
CreateBoundFunction(isolate, number_format_holder, isolate, format_holder, Builtins::kNumberFormatInternalFormatNumber, 1);
Builtins::kNumberFormatInternalFormatNumber, 1);
// 4. c. Set nf.[[BoundFormat]] to F. // 4. c. Set nf.[[BoundFormat]] to F.
number_format_holder->SetEmbedderField(NumberFormat::kBoundFormatIndex, nf->set_bound_format(*new_bound_format_function);
*new_bound_format_function);
// 5. Return nf.[[BoundFormat]]. // 5. Return nf.[[BoundFormat]].
return *new_bound_format_function; return *new_bound_format_function;
...@@ -617,15 +687,12 @@ BUILTIN(NumberFormatInternalFormatNumber) { ...@@ -617,15 +687,12 @@ BUILTIN(NumberFormatInternalFormatNumber) {
Handle<Context> context = Handle<Context>(isolate->context(), isolate); Handle<Context> context = Handle<Context>(isolate->context(), isolate);
// 1. Let nf be F.[[NumberFormat]]. // 1. Let nf be F.[[NumberFormat]].
Handle<JSObject> number_format_holder = Handle<JSObject>(
JSObject::cast(context->get(
static_cast<int>(Intl::BoundFunctionContextSlot::kBoundFunction))),
isolate);
// 2. Assert: Type(nf) is Object and nf has an // 2. Assert: Type(nf) is Object and nf has an
// [[InitializedNumberFormat]] internal slot. // [[InitializedNumberFormat]] internal slot.
DCHECK(Intl::IsObjectOfType(isolate, number_format_holder, Handle<JSNumberFormat> number_format = Handle<JSNumberFormat>(
Intl::Type::kNumberFormat)); JSNumberFormat::cast(
context->get(JSNumberFormat::ContextSlot::kNumberFormat)),
isolate);
// 3. If value is not provided, let value be undefined. // 3. If value is not provided, let value be undefined.
Handle<Object> value = args.atOrUndefined(isolate, 1); Handle<Object> value = args.atOrUndefined(isolate, 1);
...@@ -642,8 +709,8 @@ BUILTIN(NumberFormatInternalFormatNumber) { ...@@ -642,8 +709,8 @@ BUILTIN(NumberFormatInternalFormatNumber) {
double number = number_obj->Number(); double number = number_obj->Number();
// Return FormatNumber(nf, x). // Return FormatNumber(nf, x).
RETURN_RESULT_OR_FAILURE(isolate, NumberFormat::FormatNumber( RETURN_RESULT_OR_FAILURE(
isolate, number_format_holder, number)); isolate, JSNumberFormat::FormatNumber(isolate, number_format, number));
} }
BUILTIN(DateTimeFormatPrototypeFormat) { BUILTIN(DateTimeFormatPrototypeFormat) {
......
...@@ -211,6 +211,7 @@ Type::bitset BitsetType::Lub(HeapObjectType const& type) { ...@@ -211,6 +211,7 @@ Type::bitset BitsetType::Lub(HeapObjectType const& type) {
case JS_INTL_DATE_TIME_FORMAT_TYPE: case JS_INTL_DATE_TIME_FORMAT_TYPE:
case JS_INTL_LIST_FORMAT_TYPE: case JS_INTL_LIST_FORMAT_TYPE:
case JS_INTL_LOCALE_TYPE: case JS_INTL_LOCALE_TYPE:
case JS_INTL_NUMBER_FORMAT_TYPE:
case JS_INTL_PLURAL_RULES_TYPE: case JS_INTL_PLURAL_RULES_TYPE:
case JS_INTL_RELATIVE_TIME_FORMAT_TYPE: case JS_INTL_RELATIVE_TIME_FORMAT_TYPE:
#endif // V8_INTL_SUPPORT #endif // V8_INTL_SUPPORT
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
V(cell_value_string, "%cell_value") \ V(cell_value_string, "%cell_value") \
V(char_at_string, "CharAt") \ V(char_at_string, "CharAt") \
V(closure_string, "(closure)") \ V(closure_string, "(closure)") \
V(code_string, "code") \
V(collation_string, "collation") \ V(collation_string, "collation") \
V(column_string, "column") \ V(column_string, "column") \
V(CompileError_string, "CompileError") \ V(CompileError_string, "CompileError") \
...@@ -50,6 +51,7 @@ ...@@ -50,6 +51,7 @@
V(conjunction_string, "conjunction") \ V(conjunction_string, "conjunction") \
V(create_string, "create") \ V(create_string, "create") \
V(currency_string, "currency") \ V(currency_string, "currency") \
V(currencyDisplay_string, "currencyDisplay") \
V(Date_string, "Date") \ V(Date_string, "Date") \
V(date_to_string, "[object Date]") \ V(date_to_string, "[object Date]") \
V(day_string, "day") \ V(day_string, "day") \
...@@ -128,9 +130,14 @@ ...@@ -128,9 +130,14 @@
V(long_string, "long") \ V(long_string, "long") \
V(Map_string, "Map") \ V(Map_string, "Map") \
V(MapIterator_string, "Map Iterator") \ V(MapIterator_string, "Map Iterator") \
V(maximumFractionDigits_string, "maximumFractionDigits") \
V(maximumSignificantDigits_string, "maximumSignificantDigits") \
V(message_string, "message") \ V(message_string, "message") \
V(minus_Infinity_string, "-Infinity") \ V(minus_Infinity_string, "-Infinity") \
V(minus_zero_string, "-0") \ V(minus_zero_string, "-0") \
V(minimumFractionDigits_string, "minimumFractionDigits") \
V(minimumIntegerDigits_string, "minimumIntegerDigits") \
V(minimumSignificantDigits_string, "minimumSignificantDigits") \
V(minusSign_string, "minusSign") \ V(minusSign_string, "minusSign") \
V(minute_string, "minute") \ V(minute_string, "minute") \
V(Module_string, "Module") \ V(Module_string, "Module") \
...@@ -153,6 +160,7 @@ ...@@ -153,6 +160,7 @@
V(Number_string, "Number") \ V(Number_string, "Number") \
V(number_string, "number") \ V(number_string, "number") \
V(number_to_string, "[object Number]") \ V(number_to_string, "[object Number]") \
V(numberingSystem_string, "numberingSystem") \
V(numeric_string, "numeric") \ V(numeric_string, "numeric") \
V(Object_string, "Object") \ V(Object_string, "Object") \
V(object_string, "object") \ V(object_string, "object") \
...@@ -160,6 +168,7 @@ ...@@ -160,6 +168,7 @@
V(ok, "ok") \ V(ok, "ok") \
V(one_string, "1") \ V(one_string, "1") \
V(ownKeys_string, "ownKeys") \ V(ownKeys_string, "ownKeys") \
V(percent_string, "percent") \
V(percentSign_string, "percentSign") \ V(percentSign_string, "percentSign") \
V(plusSign_string, "plusSign") \ V(plusSign_string, "plusSign") \
V(position_string, "position") \ V(position_string, "position") \
...@@ -231,6 +240,7 @@ ...@@ -231,6 +240,7 @@
V(usage_string, "usage") \ V(usage_string, "usage") \
V(use_asm_string, "use asm") \ V(use_asm_string, "use asm") \
V(use_strict_string, "use strict") \ V(use_strict_string, "use strict") \
V(useGrouping_string, "useGrouping") \
V(value_string, "value") \ V(value_string, "value") \
V(valueOf_string, "valueOf") \ V(valueOf_string, "valueOf") \
V(values_string, "values") \ V(values_string, "values") \
......
...@@ -584,188 +584,13 @@ DEFINE_METHOD( ...@@ -584,188 +584,13 @@ DEFINE_METHOD(
} }
); );
// ECMA 402 #sec-setnfdigitoptions
// SetNumberFormatDigitOptions ( intlObj, options, mnfdDefault, mxfdDefault )
function SetNumberFormatDigitOptions(internalOptions, options,
mnfdDefault, mxfdDefault) {
// Digit ranges.
var mnid = %GetNumberOption(options, 'minimumIntegerDigits', 1, 21, 1);
%DefineWEProperty(internalOptions, 'minimumIntegerDigits', mnid);
var mnfd = %GetNumberOption(options, 'minimumFractionDigits', 0, 20,
mnfdDefault);
%DefineWEProperty(internalOptions, 'minimumFractionDigits', mnfd);
var mxfdActualDefault = MathMax(mnfd, mxfdDefault);
var mxfd = %GetNumberOption(options, 'maximumFractionDigits', mnfd, 20,
mxfdActualDefault);
%DefineWEProperty(internalOptions, 'maximumFractionDigits', mxfd);
var mnsd = options['minimumSignificantDigits'];
var mxsd = options['maximumSignificantDigits'];
if (!IS_UNDEFINED(mnsd) || !IS_UNDEFINED(mxsd)) {
mnsd = %DefaultNumberOption(mnsd, 1, 21, 1, 'minimumSignificantDigits');
%DefineWEProperty(internalOptions, 'minimumSignificantDigits', mnsd);
mxsd = %DefaultNumberOption(mxsd, mnsd, 21, 21, 'maximumSignificantDigits');
%DefineWEProperty(internalOptions, 'maximumSignificantDigits', mxsd);
}
}
/**
* Initializes the given object so it's a valid NumberFormat instance.
* Useful for subclassing.
*/
function CreateNumberFormat(locales, options) {
if (IS_UNDEFINED(options)) {
options = {__proto__: null};
} else {
options = TO_OBJECT(options);
}
var getOption = getGetOption(options, 'numberformat');
var locale = resolveLocale('numberformat', locales, options);
var internalOptions = {__proto__: null};
%DefineWEProperty(internalOptions, 'style', getOption(
'style', 'string', ['decimal', 'percent', 'currency'], 'decimal'));
var currency = getOption('currency', 'string');
if (!IS_UNDEFINED(currency) && !%IsWellFormedCurrencyCode(currency)) {
throw %make_range_error(kInvalidCurrencyCode, currency);
}
if (internalOptions.style === 'currency' && IS_UNDEFINED(currency)) {
throw %make_type_error(kCurrencyCode);
}
var mnfdDefault, mxfdDefault;
var currencyDisplay = getOption(
'currencyDisplay', 'string', ['code', 'symbol', 'name'], 'symbol');
if (internalOptions.style === 'currency') {
%DefineWEProperty(internalOptions, 'currency', %StringToUpperCaseIntl(currency));
%DefineWEProperty(internalOptions, 'currencyDisplay', currencyDisplay);
mnfdDefault = mxfdDefault = %CurrencyDigits(internalOptions.currency);
} else {
mnfdDefault = 0;
mxfdDefault = internalOptions.style === 'percent' ? 0 : 3;
}
SetNumberFormatDigitOptions(internalOptions, options, mnfdDefault,
mxfdDefault);
// Grouping.
%DefineWEProperty(internalOptions, 'useGrouping', getOption(
'useGrouping', 'boolean', UNDEFINED, true));
// ICU prefers options to be passed using -u- extension key/values for
// number format, so we need to build that.
var extensionMap = %ParseExtension(locale.extension);
/**
* Map of Unicode extensions to option properties, and their values and types,
* for a number format.
*/
var NUMBER_FORMAT_KEY_MAP = {
__proto__: null,
'nu': {__proto__: null, 'property': UNDEFINED, 'type': 'string'}
};
var extension = setOptions(options, extensionMap, NUMBER_FORMAT_KEY_MAP,
getOption, internalOptions);
var requestedLocale = locale.locale + extension;
var resolved = %object_define_properties({__proto__: null}, {
currency: {writable: true},
currencyDisplay: {writable: true},
locale: {writable: true},
maximumFractionDigits: {writable: true},
minimumFractionDigits: {writable: true},
minimumIntegerDigits: {writable: true},
numberingSystem: {writable: true},
requestedLocale: {value: requestedLocale, writable: true},
style: {value: internalOptions.style, writable: true},
useGrouping: {writable: true}
});
if (HAS_OWN_PROPERTY(internalOptions, 'minimumSignificantDigits')) {
%DefineWEProperty(resolved, 'minimumSignificantDigits', UNDEFINED);
}
if (HAS_OWN_PROPERTY(internalOptions, 'maximumSignificantDigits')) {
%DefineWEProperty(resolved, 'maximumSignificantDigits', UNDEFINED);
}
var numberFormat = %CreateNumberFormat(requestedLocale, internalOptions,
resolved);
if (internalOptions.style === 'currency') {
%object_define_property(resolved, 'currencyDisplay',
{value: currencyDisplay, writable: true});
}
%MarkAsInitializedIntlObjectOfType(numberFormat, NUMBER_FORMAT_TYPE);
numberFormat[resolvedSymbol] = resolved;
return numberFormat;
}
/**
* Constructs Intl.NumberFormat object given optional locales and options
* parameters.
*
* @constructor
*/
function NumberFormatConstructor() {
return IntlConstruct(this, GlobalIntlNumberFormat, CreateNumberFormat,
new.target, arguments, true);
}
%SetCode(GlobalIntlNumberFormat, NumberFormatConstructor);
/** /**
* NumberFormat resolvedOptions method. * NumberFormat resolvedOptions method.
*/ */
DEFINE_METHOD( DEFINE_METHOD(
GlobalIntlNumberFormat.prototype, GlobalIntlNumberFormat.prototype,
resolvedOptions() { resolvedOptions() {
var methodName = 'resolvedOptions'; return %NumberFormatResolvedOptions(this);
if(!IS_RECEIVER(this)) {
throw %make_type_error(kIncompatibleMethodReceiver, methodName, this);
}
var format = %IntlUnwrapReceiver(this, NUMBER_FORMAT_TYPE,
GlobalIntlNumberFormat,
methodName, true);
var result = {
locale: format[resolvedSymbol].locale,
numberingSystem: format[resolvedSymbol].numberingSystem,
style: format[resolvedSymbol].style,
useGrouping: format[resolvedSymbol].useGrouping,
minimumIntegerDigits: format[resolvedSymbol].minimumIntegerDigits,
minimumFractionDigits: format[resolvedSymbol].minimumFractionDigits,
maximumFractionDigits: format[resolvedSymbol].maximumFractionDigits,
};
if (result.style === 'currency') {
defineWECProperty(result, 'currency', format[resolvedSymbol].currency);
defineWECProperty(result, 'currencyDisplay',
format[resolvedSymbol].currencyDisplay);
}
if (HAS_OWN_PROPERTY(format[resolvedSymbol], 'minimumSignificantDigits')) {
defineWECProperty(result, 'minimumSignificantDigits',
format[resolvedSymbol].minimumSignificantDigits);
}
if (HAS_OWN_PROPERTY(format[resolvedSymbol], 'maximumSignificantDigits')) {
defineWECProperty(result, 'maximumSignificantDigits',
format[resolvedSymbol].maximumSignificantDigits);
}
return result;
} }
); );
......
...@@ -730,6 +730,7 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) { ...@@ -730,6 +730,7 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) {
case JS_INTL_DATE_TIME_FORMAT_TYPE: case JS_INTL_DATE_TIME_FORMAT_TYPE:
case JS_INTL_LIST_FORMAT_TYPE: case JS_INTL_LIST_FORMAT_TYPE:
case JS_INTL_LOCALE_TYPE: case JS_INTL_LOCALE_TYPE:
case JS_INTL_NUMBER_FORMAT_TYPE:
case JS_INTL_PLURAL_RULES_TYPE: case JS_INTL_PLURAL_RULES_TYPE:
case JS_INTL_RELATIVE_TIME_FORMAT_TYPE: case JS_INTL_RELATIVE_TIME_FORMAT_TYPE:
#endif // V8_INTL_SUPPORT #endif // V8_INTL_SUPPORT
......
...@@ -30,11 +30,12 @@ ...@@ -30,11 +30,12 @@
#ifdef V8_INTL_SUPPORT #ifdef V8_INTL_SUPPORT
#include "src/objects/js-list-format-inl.h" #include "src/objects/js-list-format-inl.h"
#include "src/objects/js-locale-inl.h" #include "src/objects/js-locale-inl.h"
#include "src/objects/js-number-format-inl.h"
#include "src/objects/js-plural-rules-inl.h"
#endif // V8_INTL_SUPPORT #endif // V8_INTL_SUPPORT
#include "src/objects/js-regexp-inl.h" #include "src/objects/js-regexp-inl.h"
#include "src/objects/js-regexp-string-iterator-inl.h" #include "src/objects/js-regexp-string-iterator-inl.h"
#ifdef V8_INTL_SUPPORT #ifdef V8_INTL_SUPPORT
#include "src/objects/js-plural-rules-inl.h"
#include "src/objects/js-relative-time-format-inl.h" #include "src/objects/js-relative-time-format-inl.h"
#endif // V8_INTL_SUPPORT #endif // V8_INTL_SUPPORT
#include "src/objects/literal-objects-inl.h" #include "src/objects/literal-objects-inl.h"
...@@ -371,6 +372,9 @@ void HeapObject::HeapObjectVerify(Isolate* isolate) { ...@@ -371,6 +372,9 @@ void HeapObject::HeapObjectVerify(Isolate* isolate) {
case JS_INTL_LOCALE_TYPE: case JS_INTL_LOCALE_TYPE:
JSLocale::cast(this)->JSLocaleVerify(isolate); JSLocale::cast(this)->JSLocaleVerify(isolate);
break; break;
case JS_INTL_NUMBER_FORMAT_TYPE:
JSNumberFormat::cast(this)->JSNumberFormatVerify(isolate);
break;
case JS_INTL_PLURAL_RULES_TYPE: case JS_INTL_PLURAL_RULES_TYPE:
JSPluralRules::cast(this)->JSPluralRulesVerify(isolate); JSPluralRules::cast(this)->JSPluralRulesVerify(isolate);
break; break;
...@@ -1911,6 +1915,15 @@ void JSLocale::JSLocaleVerify(Isolate* isolate) { ...@@ -1911,6 +1915,15 @@ void JSLocale::JSLocaleVerify(Isolate* isolate) {
VerifyObjectField(isolate, kNumberingSystemOffset); VerifyObjectField(isolate, kNumberingSystemOffset);
} }
void JSNumberFormat::JSNumberFormatVerify(Isolate* isolate) {
CHECK(IsJSNumberFormat());
JSObjectVerify(isolate);
VerifyObjectField(isolate, kLocaleOffset);
VerifyObjectField(isolate, kIcuNumberFormatOffset);
VerifyObjectField(isolate, kBoundFormatOffset);
VerifyObjectField(isolate, kFlagsOffset);
}
void JSPluralRules::JSPluralRulesVerify(Isolate* isolate) { void JSPluralRules::JSPluralRulesVerify(Isolate* isolate) {
CHECK(IsJSPluralRules()); CHECK(IsJSPluralRules());
JSObjectVerify(isolate); JSObjectVerify(isolate);
......
...@@ -220,6 +220,7 @@ namespace internal { ...@@ -220,6 +220,7 @@ namespace internal {
V(JS_INTL_DATE_TIME_FORMAT_TYPE) \ V(JS_INTL_DATE_TIME_FORMAT_TYPE) \
V(JS_INTL_LIST_FORMAT_TYPE) \ V(JS_INTL_LIST_FORMAT_TYPE) \
V(JS_INTL_LOCALE_TYPE) \ V(JS_INTL_LOCALE_TYPE) \
V(JS_INTL_NUMBER_FORMAT_TYPE) \
V(JS_INTL_PLURAL_RULES_TYPE) \ V(JS_INTL_PLURAL_RULES_TYPE) \
V(JS_INTL_RELATIVE_TIME_FORMAT_TYPE) \ V(JS_INTL_RELATIVE_TIME_FORMAT_TYPE) \
INSTANCE_TYPE_LIST_AFTER_INTL(V) INSTANCE_TYPE_LIST_AFTER_INTL(V)
......
...@@ -30,11 +30,12 @@ ...@@ -30,11 +30,12 @@
#ifdef V8_INTL_SUPPORT #ifdef V8_INTL_SUPPORT
#include "src/objects/js-list-format-inl.h" #include "src/objects/js-list-format-inl.h"
#include "src/objects/js-locale-inl.h" #include "src/objects/js-locale-inl.h"
#include "src/objects/js-number-format-inl.h"
#include "src/objects/js-plural-rules-inl.h"
#endif // V8_INTL_SUPPORT #endif // V8_INTL_SUPPORT
#include "src/objects/js-regexp-inl.h" #include "src/objects/js-regexp-inl.h"
#include "src/objects/js-regexp-string-iterator-inl.h" #include "src/objects/js-regexp-string-iterator-inl.h"
#ifdef V8_INTL_SUPPORT #ifdef V8_INTL_SUPPORT
#include "src/objects/js-plural-rules-inl.h"
#include "src/objects/js-relative-time-format-inl.h" #include "src/objects/js-relative-time-format-inl.h"
#endif // V8_INTL_SUPPORT #endif // V8_INTL_SUPPORT
#include "src/objects/literal-objects-inl.h" #include "src/objects/literal-objects-inl.h"
...@@ -324,6 +325,9 @@ void HeapObject::HeapObjectPrint(std::ostream& os) { // NOLINT ...@@ -324,6 +325,9 @@ void HeapObject::HeapObjectPrint(std::ostream& os) { // NOLINT
case JS_INTL_LOCALE_TYPE: case JS_INTL_LOCALE_TYPE:
JSLocale::cast(this)->JSLocalePrint(os); JSLocale::cast(this)->JSLocalePrint(os);
break; break;
case JS_INTL_NUMBER_FORMAT_TYPE:
JSNumberFormat::cast(this)->JSNumberFormatPrint(os);
break;
case JS_INTL_PLURAL_RULES_TYPE: case JS_INTL_PLURAL_RULES_TYPE:
JSPluralRules::cast(this)->JSPluralRulesPrint(os); JSPluralRules::cast(this)->JSPluralRulesPrint(os);
break; break;
...@@ -1995,6 +1999,16 @@ void JSLocale::JSLocalePrint(std::ostream& os) { // NOLINT ...@@ -1995,6 +1999,16 @@ void JSLocale::JSLocalePrint(std::ostream& os) { // NOLINT
os << "\n"; os << "\n";
} }
void JSNumberFormat::JSNumberFormatPrint(std::ostream& os) { // NOLINT
JSObjectPrintHeader(os, this, "JSNumberFormat");
os << "\n - locale: " << Brief(locale());
os << "\n - icu_number_format: " << Brief(icu_number_format());
os << "\n - bound_format: " << Brief(bound_format());
os << "\n - style: " << StyleAsString();
os << "\n - currency_display: " << CurrencyDisplayAsString();
os << "\n";
}
void JSPluralRules::JSPluralRulesPrint(std::ostream& os) { // NOLINT void JSPluralRules::JSPluralRulesPrint(std::ostream& os) { // NOLINT
HeapObject::PrintHeader(os, "JSPluralRules"); HeapObject::PrintHeader(os, "JSPluralRules");
JSObjectPrint(os); JSObjectPrint(os);
......
...@@ -71,11 +71,12 @@ ...@@ -71,11 +71,12 @@
#ifdef V8_INTL_SUPPORT #ifdef V8_INTL_SUPPORT
#include "src/objects/js-list-format.h" #include "src/objects/js-list-format.h"
#include "src/objects/js-locale.h" #include "src/objects/js-locale.h"
#include "src/objects/js-number-format.h"
#include "src/objects/js-plural-rules.h"
#endif // V8_INTL_SUPPORT #endif // V8_INTL_SUPPORT
#include "src/objects/js-regexp-inl.h" #include "src/objects/js-regexp-inl.h"
#include "src/objects/js-regexp-string-iterator.h" #include "src/objects/js-regexp-string-iterator.h"
#ifdef V8_INTL_SUPPORT #ifdef V8_INTL_SUPPORT
#include "src/objects/js-plural-rules.h"
#include "src/objects/js-relative-time-format.h" #include "src/objects/js-relative-time-format.h"
#endif // V8_INTL_SUPPORT #endif // V8_INTL_SUPPORT
#include "src/objects/literal-objects-inl.h" #include "src/objects/literal-objects-inl.h"
...@@ -1464,6 +1465,8 @@ int JSObject::GetHeaderSize(InstanceType type, ...@@ -1464,6 +1465,8 @@ int JSObject::GetHeaderSize(InstanceType type,
return JSListFormat::kSize; return JSListFormat::kSize;
case JS_INTL_LOCALE_TYPE: case JS_INTL_LOCALE_TYPE:
return JSLocale::kSize; return JSLocale::kSize;
case JS_INTL_NUMBER_FORMAT_TYPE:
return JSNumberFormat::kSize;
case JS_INTL_PLURAL_RULES_TYPE: case JS_INTL_PLURAL_RULES_TYPE:
return JSPluralRules::kSize; return JSPluralRules::kSize;
case JS_INTL_RELATIVE_TIME_FORMAT_TYPE: case JS_INTL_RELATIVE_TIME_FORMAT_TYPE:
...@@ -3207,6 +3210,7 @@ VisitorId Map::GetVisitorId(Map* map) { ...@@ -3207,6 +3210,7 @@ VisitorId Map::GetVisitorId(Map* map) {
case JS_INTL_DATE_TIME_FORMAT_TYPE: case JS_INTL_DATE_TIME_FORMAT_TYPE:
case JS_INTL_LIST_FORMAT_TYPE: case JS_INTL_LIST_FORMAT_TYPE:
case JS_INTL_LOCALE_TYPE: case JS_INTL_LOCALE_TYPE:
case JS_INTL_NUMBER_FORMAT_TYPE:
case JS_INTL_PLURAL_RULES_TYPE: case JS_INTL_PLURAL_RULES_TYPE:
case JS_INTL_RELATIVE_TIME_FORMAT_TYPE: case JS_INTL_RELATIVE_TIME_FORMAT_TYPE:
#endif // V8_INTL_SUPPORT #endif // V8_INTL_SUPPORT
...@@ -13152,6 +13156,7 @@ bool CanSubclassHaveInobjectProperties(InstanceType instance_type) { ...@@ -13152,6 +13156,7 @@ bool CanSubclassHaveInobjectProperties(InstanceType instance_type) {
case JS_INTL_COLLATOR_TYPE: case JS_INTL_COLLATOR_TYPE:
case JS_INTL_DATE_TIME_FORMAT_TYPE: case JS_INTL_DATE_TIME_FORMAT_TYPE:
case JS_INTL_LIST_FORMAT_TYPE: case JS_INTL_LIST_FORMAT_TYPE:
case JS_INTL_NUMBER_FORMAT_TYPE:
case JS_INTL_PLURAL_RULES_TYPE: case JS_INTL_PLURAL_RULES_TYPE:
case JS_INTL_RELATIVE_TIME_FORMAT_TYPE: case JS_INTL_RELATIVE_TIME_FORMAT_TYPE:
#endif #endif
......
...@@ -79,6 +79,7 @@ ...@@ -79,6 +79,7 @@
// - JSDateTimeFormat // If V8_INTL_SUPPORT enabled. // - JSDateTimeFormat // If V8_INTL_SUPPORT enabled.
// - JSListFormat // If V8_INTL_SUPPORT enabled. // - JSListFormat // If V8_INTL_SUPPORT enabled.
// - JSLocale // If V8_INTL_SUPPORT enabled. // - JSLocale // If V8_INTL_SUPPORT enabled.
// - JSNumberFormat // If V8_INTL_SUPPORT enabled.
// - JSPluralRules // If V8_INTL_SUPPORT enabled. // - JSPluralRules // If V8_INTL_SUPPORT enabled.
// - JSRelativeTimeFormat // If V8_INTL_SUPPORT enabled. // - JSRelativeTimeFormat // If V8_INTL_SUPPORT enabled.
// - WasmGlobalObject // - WasmGlobalObject
...@@ -587,6 +588,7 @@ enum InstanceType : uint16_t { ...@@ -587,6 +588,7 @@ enum InstanceType : uint16_t {
JS_INTL_DATE_TIME_FORMAT_TYPE, JS_INTL_DATE_TIME_FORMAT_TYPE,
JS_INTL_LIST_FORMAT_TYPE, JS_INTL_LIST_FORMAT_TYPE,
JS_INTL_LOCALE_TYPE, JS_INTL_LOCALE_TYPE,
JS_INTL_NUMBER_FORMAT_TYPE,
JS_INTL_PLURAL_RULES_TYPE, JS_INTL_PLURAL_RULES_TYPE,
JS_INTL_RELATIVE_TIME_FORMAT_TYPE, JS_INTL_RELATIVE_TIME_FORMAT_TYPE,
#endif // V8_INTL_SUPPORT #endif // V8_INTL_SUPPORT
...@@ -706,6 +708,7 @@ class JSCollator; ...@@ -706,6 +708,7 @@ class JSCollator;
class JSDateTimeFormat; class JSDateTimeFormat;
class JSListFormat; class JSListFormat;
class JSLocale; class JSLocale;
class JSNumberFormat;
class JSPluralRules; class JSPluralRules;
class JSRelativeTimeFormat; class JSRelativeTimeFormat;
#endif // V8_INTL_SUPPORT #endif // V8_INTL_SUPPORT
...@@ -918,6 +921,7 @@ class ZoneForwardList; ...@@ -918,6 +921,7 @@ class ZoneForwardList;
V(JSDateTimeFormat) \ V(JSDateTimeFormat) \
V(JSListFormat) \ V(JSListFormat) \
V(JSLocale) \ V(JSLocale) \
V(JSNumberFormat) \
V(JSPluralRules) \ V(JSPluralRules) \
V(JSRelativeTimeFormat) V(JSRelativeTimeFormat)
#else #else
...@@ -1039,6 +1043,7 @@ class ZoneForwardList; ...@@ -1039,6 +1043,7 @@ class ZoneForwardList;
V(JSDateTimeFormat, JS_INTL_DATE_TIME_FORMAT_TYPE) \ V(JSDateTimeFormat, JS_INTL_DATE_TIME_FORMAT_TYPE) \
V(JSListFormat, JS_INTL_LIST_FORMAT_TYPE) \ V(JSListFormat, JS_INTL_LIST_FORMAT_TYPE) \
V(JSLocale, JS_INTL_LOCALE_TYPE) \ V(JSLocale, JS_INTL_LOCALE_TYPE) \
V(JSNumberFormat, JS_INTL_NUMBER_FORMAT_TYPE) \
V(JSPluralRules, JS_INTL_PLURAL_RULES_TYPE) \ V(JSPluralRules, JS_INTL_PLURAL_RULES_TYPE) \
V(JSRelativeTimeFormat, JS_INTL_RELATIVE_TIME_FORMAT_TYPE) V(JSRelativeTimeFormat, JS_INTL_RELATIVE_TIME_FORMAT_TYPE)
......
This diff is collapsed.
...@@ -23,6 +23,7 @@ namespace U_ICU_NAMESPACE { ...@@ -23,6 +23,7 @@ namespace U_ICU_NAMESPACE {
class BreakIterator; class BreakIterator;
class Collator; class Collator;
class DecimalFormat; class DecimalFormat;
class NumberFormat;
class PluralRules; class PluralRules;
class SimpleDateFormat; class SimpleDateFormat;
class UnicodeString; class UnicodeString;
...@@ -101,58 +102,6 @@ class DateFormat { ...@@ -101,58 +102,6 @@ class DateFormat {
DateFormat(); DateFormat();
}; };
class NumberFormat {
public:
// Create a formatter for the specificied locale and options. Returns the
// resolved settings for the locale / options.
static icu::DecimalFormat* InitializeNumberFormat(Isolate* isolate,
Handle<String> locale,
Handle<JSObject> options,
Handle<JSObject> resolved);
// Unpacks number format object from corresponding JavaScript object.
static icu::DecimalFormat* UnpackNumberFormat(Handle<JSObject> obj);
// Release memory we allocated for the NumberFormat once the JS object that
// holds the pointer gets garbage collected.
static void DeleteNumberFormat(const v8::WeakCallbackInfo<void>& data);
// The UnwrapNumberFormat abstract operation gets the underlying
// NumberFormat operation for various methods which implement
// ECMA-402 v1 semantics for supporting initializing existing Intl
// objects.
//
// ecma402/#sec-unwrapnumberformat
static MaybeHandle<JSObject> Unwrap(Isolate* isolate,
Handle<JSReceiver> receiver,
const char* method_name);
// ecm402/#sec-formatnumber
static MaybeHandle<String> FormatNumber(Isolate* isolate,
Handle<JSObject> number_format_holder,
double value);
// Layout description.
#define NUMBER_FORMAT_FIELDS(V) \
/* Pointer fields. */ \
V(kDecimalFormat, kPointerSize) \
V(kBoundFormat, kPointerSize) \
V(kSize, 0)
DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize, NUMBER_FORMAT_FIELDS)
#undef NUMBER_FORMAT_FIELDS
// TODO(gsathya): Remove this and use regular accessors once
// NumberFormat is a sub class of JSObject.
//
// This needs to be consistent with the above LayoutDescription.
static const int kDecimalFormatIndex = 0;
static const int kBoundFormatIndex = 1;
private:
NumberFormat();
};
class V8BreakIterator { class V8BreakIterator {
public: public:
// Create a BreakIterator for the specificied locale and options. Returns the // Create a BreakIterator for the specificied locale and options. Returns the
...@@ -241,6 +190,12 @@ class Intl { ...@@ -241,6 +190,12 @@ class Intl {
// pa_IN. // pa_IN.
static std::set<std::string> GetAvailableLocales(const IcuService& service); static std::set<std::string> GetAvailableLocales(const IcuService& service);
// Get the name of the numbering system from locale.
// ICU doesn't expose numbering system in any way, so we have to assume that
// for given locale NumberingSystem constructor produces the same digits as
// NumberFormat/Calendar would.
static std::string GetNumberingSystem(const icu::Locale& icu_locale);
static V8_WARN_UNUSED_RESULT MaybeHandle<JSObject> AvailableLocalesOf( static V8_WARN_UNUSED_RESULT MaybeHandle<JSObject> AvailableLocalesOf(
Isolate* isolate, Handle<String> service); Isolate* isolate, Handle<String> service);
...@@ -251,7 +206,7 @@ class Intl { ...@@ -251,7 +206,7 @@ class Intl {
static std::string DefaultLocale(Isolate* isolate); static std::string DefaultLocale(Isolate* isolate);
static void DefineWEProperty(Isolate* isolate, Handle<JSObject> target, static void DefineWEProperty(Isolate* isolate, Handle<JSReceiver> target,
Handle<Name> key, Handle<Object> value); Handle<Name> key, Handle<Object> value);
// 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
...@@ -345,10 +300,6 @@ class Intl { ...@@ -345,10 +300,6 @@ class Intl {
Isolate* isolate, Handle<Object> locales, Isolate* isolate, Handle<Object> locales,
bool only_return_one_result = false); bool only_return_one_result = false);
// ecma-402/#sec-currencydigits
// The currency is expected to an all upper case string value.
static Handle<Smi> CurrencyDigits(Isolate* isolate, Handle<String> currency);
// TODO(ftang): Remove this and use ICU to the conversion in the future // TODO(ftang): Remove this and use ICU to the conversion in the future
static void ParseExtension(Isolate* isolate, const std::string& extension, static void ParseExtension(Isolate* isolate, const std::string& extension,
std::map<std::string, std::string>& out); std::map<std::string, std::string>& out);
...@@ -357,10 +308,6 @@ class Intl { ...@@ -357,10 +308,6 @@ class Intl {
Isolate* isolate, Handle<String> locale, Handle<JSObject> options, Isolate* isolate, Handle<String> locale, Handle<JSObject> options,
Handle<JSObject> resolved); Handle<JSObject> resolved);
// ecma402/#sec-iswellformedcurrencycode
static bool IsWellFormedCurrencyCode(Isolate* isolate,
Handle<String> currency);
// For locale sensitive functions // For locale sensitive functions
V8_WARN_UNUSED_RESULT static MaybeHandle<String> StringLocaleConvertCase( V8_WARN_UNUSED_RESULT static MaybeHandle<String> StringLocaleConvertCase(
Isolate* isolate, Handle<String> s, bool is_upper, Isolate* isolate, Handle<String> s, bool is_upper,
......
// 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_NUMBER_FORMAT_INL_H_
#define V8_OBJECTS_JS_NUMBER_FORMAT_INL_H_
#include "src/objects-inl.h"
#include "src/objects/js-number-format.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
namespace v8 {
namespace internal {
ACCESSORS(JSNumberFormat, locale, String, kLocaleOffset)
ACCESSORS(JSNumberFormat, icu_number_format, Managed<icu::NumberFormat>,
kIcuNumberFormatOffset)
ACCESSORS(JSNumberFormat, bound_format, Object, kBoundFormatOffset)
SMI_ACCESSORS(JSNumberFormat, flags, kFlagsOffset)
inline void JSNumberFormat::set_style(Style style) {
DCHECK_LT(style, Style::COUNT);
int hints = flags();
hints = StyleBits::update(hints, style);
set_flags(hints);
}
inline JSNumberFormat::Style JSNumberFormat::style() const {
return StyleBits::decode(flags());
}
inline void JSNumberFormat::set_currency_display(
CurrencyDisplay currency_display) {
DCHECK_LT(currency_display, CurrencyDisplay::COUNT);
int hints = flags();
hints = CurrencyDisplayBits::update(hints, currency_display);
set_flags(hints);
}
inline JSNumberFormat::CurrencyDisplay JSNumberFormat::currency_display()
const {
return CurrencyDisplayBits::decode(flags());
}
CAST_ACCESSOR(JSNumberFormat);
} // namespace internal
} // namespace v8
#include "src/objects/object-macros-undef.h"
#endif // V8_OBJECTS_JS_NUMBER_FORMAT_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_NUMBER_FORMAT_H_
#define V8_OBJECTS_JS_NUMBER_FORMAT_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 JSNumberFormat : public JSObject {
public:
// ecma402/#sec-initializenumberformat
V8_WARN_UNUSED_RESULT static MaybeHandle<JSNumberFormat>
InitializeNumberFormat(Isolate* isolate, Handle<JSNumberFormat> number_format,
Handle<Object> locales, Handle<Object> options);
// ecma402/#sec-unwrapnumberformat
V8_WARN_UNUSED_RESULT static MaybeHandle<JSNumberFormat> UnwrapNumberFormat(
Isolate* isolate, Handle<JSReceiver> format_holder);
// ecma402/#sec-intl.numberformat.prototype.resolvedoptions
static Handle<JSObject> ResolvedOptions(Isolate* isolate,
Handle<JSNumberFormat> number_format);
V8_WARN_UNUSED_RESULT static MaybeHandle<String> FormatNumber(
Isolate* isolate, Handle<JSNumberFormat> number_format, double number);
// Unpacks format object from corresponding JavaScript object.
static icu::NumberFormat* UnpackIcuNumberFormat(
Isolate* isolate, Handle<JSNumberFormat> number_format_holder);
Handle<String> StyleAsString() const;
Handle<String> CurrencyDisplayAsString() const;
DECL_CAST(JSNumberFormat)
DECL_PRINTER(JSNumberFormat)
DECL_VERIFIER(JSNumberFormat)
// [[Style]] is one of the values "decimal", "percent" or "currency",
// identifying the style of the number format.
enum class Style {
DECIMAL,
PERCENT,
CURRENCY,
COUNT
};
inline void set_style(Style style);
inline Style style() const;
// [[CurrencyDisplay]] is one of the values "code", "symbol" or "name",
// identifying the display of the currency number format.
enum class CurrencyDisplay {
CODE,
SYMBOL,
NAME,
COUNT
};
inline void set_currency_display(CurrencyDisplay currency_display);
inline CurrencyDisplay currency_display() const;
// Layout description.
#define JS_NUMBER_FORMAT_FIELDS(V) \
V(kLocaleOffset, kPointerSize) \
V(kIcuNumberFormatOffset, kPointerSize) \
V(kBoundFormatOffset, kPointerSize) \
V(kFlagsOffset, kPointerSize) \
/* Total size. */ \
V(kSize, 0)
DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize, JS_NUMBER_FORMAT_FIELDS)
#undef JS_NUMBER_FORMAT_FIELDS
// Bit positions in |flags|.
#define FLAGS_BIT_FIELDS(V, _) \
V(StyleBits, Style, 2, _) \
V(CurrencyDisplayBits, CurrencyDisplay, 2, _)
DEFINE_BIT_FIELDS(FLAGS_BIT_FIELDS)
#undef FLAGS_BIT_FIELDS
STATIC_ASSERT(Style::DECIMAL <= StyleBits::kMax);
STATIC_ASSERT(Style::PERCENT <= StyleBits::kMax);
STATIC_ASSERT(Style::CURRENCY <= StyleBits::kMax);
STATIC_ASSERT(CurrencyDisplay::CODE <= CurrencyDisplayBits::kMax);
STATIC_ASSERT(CurrencyDisplay::SYMBOL <= CurrencyDisplayBits::kMax);
STATIC_ASSERT(CurrencyDisplay::NAME <= CurrencyDisplayBits::kMax);
DECL_ACCESSORS(locale, String)
DECL_ACCESSORS(icu_number_format, Managed<icu::NumberFormat>)
DECL_ACCESSORS(bound_format, Object)
DECL_INT_ACCESSORS(flags)
// ContextSlot defines the context structure for the bound
// NumberFormat.prototype.format function.
enum ContextSlot {
// The number format instance that the function holding this
// context is bound to.
kNumberFormat = Context::MIN_CONTEXT_SLOTS,
kLength
};
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSNumberFormat);
};
} // namespace internal
} // namespace v8
#include "src/objects/object-macros-undef.h"
#endif // V8_OBJECTS_JS_NUMBER_FORMAT_H_
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "src/objects/js-date-time-format-inl.h" #include "src/objects/js-date-time-format-inl.h"
#include "src/objects/js-list-format-inl.h" #include "src/objects/js-list-format-inl.h"
#include "src/objects/js-list-format.h" #include "src/objects/js-list-format.h"
#include "src/objects/js-number-format-inl.h"
#include "src/objects/js-plural-rules-inl.h" #include "src/objects/js-plural-rules-inl.h"
#include "src/objects/managed.h" #include "src/objects/managed.h"
#include "src/runtime/runtime-utils.h" #include "src/runtime/runtime-utils.h"
...@@ -77,40 +78,6 @@ RUNTIME_FUNCTION(Runtime_FormatListToParts) { ...@@ -77,40 +78,6 @@ RUNTIME_FUNCTION(Runtime_FormatListToParts) {
isolate, JSListFormat::FormatListToParts(isolate, list_format, list)); isolate, JSListFormat::FormatListToParts(isolate, list_format, list));
} }
RUNTIME_FUNCTION(Runtime_GetNumberOption) {
HandleScope scope(isolate);
DCHECK_EQ(5, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, options, 0);
CONVERT_ARG_HANDLE_CHECKED(String, property, 1);
CONVERT_SMI_ARG_CHECKED(min, 2);
CONVERT_SMI_ARG_CHECKED(max, 3);
CONVERT_SMI_ARG_CHECKED(fallback, 4);
Maybe<int> num =
Intl::GetNumberOption(isolate, options, property, min, max, fallback);
if (num.IsNothing()) {
return ReadOnlyRoots(isolate).exception();
}
return Smi::FromInt(num.FromJust());
}
RUNTIME_FUNCTION(Runtime_DefaultNumberOption) {
HandleScope scope(isolate);
DCHECK_EQ(5, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
CONVERT_SMI_ARG_CHECKED(min, 1);
CONVERT_SMI_ARG_CHECKED(max, 2);
CONVERT_SMI_ARG_CHECKED(fallback, 3);
CONVERT_ARG_HANDLE_CHECKED(String, property, 4);
Maybe<int> num =
Intl::DefaultNumberOption(isolate, value, min, max, fallback, property);
if (num.IsNothing()) {
return ReadOnlyRoots(isolate).exception();
}
return Smi::FromInt(num.FromJust());
}
// ECMA 402 6.2.3 // ECMA 402 6.2.3
RUNTIME_FUNCTION(Runtime_CanonicalizeLanguageTag) { RUNTIME_FUNCTION(Runtime_CanonicalizeLanguageTag) {
HandleScope scope(isolate); HandleScope scope(isolate);
...@@ -143,14 +110,6 @@ RUNTIME_FUNCTION(Runtime_GetDefaultICULocale) { ...@@ -143,14 +110,6 @@ RUNTIME_FUNCTION(Runtime_GetDefaultICULocale) {
Intl::DefaultLocale(isolate).c_str()); Intl::DefaultLocale(isolate).c_str());
} }
RUNTIME_FUNCTION(Runtime_IsWellFormedCurrencyCode) {
HandleScope scope(isolate);
DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(String, currency, 0);
return *(isolate->factory()->ToBoolean(
Intl::IsWellFormedCurrencyCode(isolate, currency)));
}
RUNTIME_FUNCTION(Runtime_DefineWEProperty) { RUNTIME_FUNCTION(Runtime_DefineWEProperty) {
HandleScope scope(isolate); HandleScope scope(isolate);
...@@ -255,23 +214,31 @@ RUNTIME_FUNCTION(Runtime_DateTimeFormatResolvedOptions) { ...@@ -255,23 +214,31 @@ RUNTIME_FUNCTION(Runtime_DateTimeFormatResolvedOptions) {
isolate, JSDateTimeFormat::ResolvedOptions(isolate, date_format_holder)); isolate, JSDateTimeFormat::ResolvedOptions(isolate, date_format_holder));
} }
RUNTIME_FUNCTION(Runtime_CreateNumberFormat) { RUNTIME_FUNCTION(Runtime_NumberFormatResolvedOptions) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK_EQ(3, args.length()); DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(Object, number_format_obj, 0);
CONVERT_ARG_HANDLE_CHECKED(String, locale, 0); // 2. If Type(nf) is not Object, throw a TypeError exception
CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1); if (!number_format_obj->IsJSReceiver()) {
CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2); Handle<String> method_str = isolate->factory()->NewStringFromStaticChars(
RETURN_RESULT_OR_FAILURE( "Intl.NumberFormat.prototype.resolvedOptions");
isolate, Intl::CreateNumberFormat(isolate, locale, options, resolved)); THROW_NEW_ERROR_RETURN_FAILURE(
} isolate, NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
method_str, number_format_obj));
}
RUNTIME_FUNCTION(Runtime_CurrencyDigits) { // 3. Let nf be ? UnwrapNumberFormat(nf).
HandleScope scope(isolate); Handle<JSReceiver> format_holder =
DCHECK_EQ(1, args.length()); Handle<JSReceiver>::cast(number_format_obj);
CONVERT_ARG_HANDLE_CHECKED(String, currency, 0);
return *Intl::CurrencyDigits(isolate, currency); Handle<JSNumberFormat> number_format;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, number_format,
JSNumberFormat::UnwrapNumberFormat(isolate, format_holder));
return *JSNumberFormat::ResolvedOptions(isolate, number_format);
} }
RUNTIME_FUNCTION(Runtime_CollatorResolvedOptions) { RUNTIME_FUNCTION(Runtime_CollatorResolvedOptions) {
......
...@@ -205,21 +205,17 @@ namespace internal { ...@@ -205,21 +205,17 @@ namespace internal {
F(CollatorResolvedOptions, 1, 1) \ F(CollatorResolvedOptions, 1, 1) \
F(CreateBreakIterator, 3, 1) \ F(CreateBreakIterator, 3, 1) \
F(CreateDateTimeFormat, 3, 1) \ F(CreateDateTimeFormat, 3, 1) \
F(CreateNumberFormat, 3, 1) \
F(CurrencyDigits, 1, 1) \
F(DateCacheVersion, 0, 1) \ F(DateCacheVersion, 0, 1) \
F(DateTimeFormatResolvedOptions, 1, 1) \ F(DateTimeFormatResolvedOptions, 1, 1) \
F(DefaultNumberOption, 5, 1) \
F(DefineWEProperty, 3, 1) \ F(DefineWEProperty, 3, 1) \
F(FormatList, 2, 1) \ F(FormatList, 2, 1) \
F(FormatListToParts, 2, 1) \ F(FormatListToParts, 2, 1) \
F(GetDefaultICULocale, 0, 1) \ F(GetDefaultICULocale, 0, 1) \
F(GetNumberOption, 5, 1) \
F(IntlUnwrapReceiver, 5, 1) \ F(IntlUnwrapReceiver, 5, 1) \
F(IsInitializedIntlObjectOfType, 2, 1) \ F(IsInitializedIntlObjectOfType, 2, 1) \
F(IsWellFormedCurrencyCode, 1, 1) \
F(MarkAsInitializedIntlObjectOfType, 2, 1) \ F(MarkAsInitializedIntlObjectOfType, 2, 1) \
F(ParseExtension, 1, 1) \ F(ParseExtension, 1, 1) \
F(NumberFormatResolvedOptions, 1, 1) \
F(PluralRulesResolvedOptions, 1, 1) \ F(PluralRulesResolvedOptions, 1, 1) \
F(PluralRulesSelect, 2, 1) \ F(PluralRulesSelect, 2, 1) \
F(ToDateTimeOptions, 3, 1) \ F(ToDateTimeOptions, 3, 1) \
......
// 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.
// Make sure passing 1 or false to patched construtor won't cause crash
Object.defineProperty(Intl.NumberFormat, Symbol.hasInstance, { value: _ => true });
assertThrows(() =>
Intl.NumberFormat.call(1), TypeError);
assertThrows(() =>
Intl.NumberFormat.call(false), TypeError);
...@@ -162,15 +162,16 @@ INSTANCE_TYPES = { ...@@ -162,15 +162,16 @@ INSTANCE_TYPES = {
1085: "JS_INTL_DATE_TIME_FORMAT_TYPE", 1085: "JS_INTL_DATE_TIME_FORMAT_TYPE",
1086: "JS_INTL_LIST_FORMAT_TYPE", 1086: "JS_INTL_LIST_FORMAT_TYPE",
1087: "JS_INTL_LOCALE_TYPE", 1087: "JS_INTL_LOCALE_TYPE",
1088: "JS_INTL_PLURAL_RULES_TYPE", 1088: "JS_INTL_NUMBER_FORMAT_TYPE",
1089: "JS_INTL_RELATIVE_TIME_FORMAT_TYPE", 1089: "JS_INTL_PLURAL_RULES_TYPE",
1090: "WASM_GLOBAL_TYPE", 1090: "JS_INTL_RELATIVE_TIME_FORMAT_TYPE",
1091: "WASM_INSTANCE_TYPE", 1091: "WASM_GLOBAL_TYPE",
1092: "WASM_MEMORY_TYPE", 1092: "WASM_INSTANCE_TYPE",
1093: "WASM_MODULE_TYPE", 1093: "WASM_MEMORY_TYPE",
1094: "WASM_TABLE_TYPE", 1094: "WASM_MODULE_TYPE",
1095: "JS_BOUND_FUNCTION_TYPE", 1095: "WASM_TABLE_TYPE",
1096: "JS_FUNCTION_TYPE", 1096: "JS_BOUND_FUNCTION_TYPE",
1097: "JS_FUNCTION_TYPE",
} }
# List of known V8 maps. # List of known V8 maps.
...@@ -285,32 +286,32 @@ KNOWN_MAPS = { ...@@ -285,32 +286,32 @@ KNOWN_MAPS = {
("RO_SPACE", 0x04811): (173, "ArrayBoilerplateDescriptionMap"), ("RO_SPACE", 0x04811): (173, "ArrayBoilerplateDescriptionMap"),
("RO_SPACE", 0x04b01): (161, "InterceptorInfoMap"), ("RO_SPACE", 0x04b01): (161, "InterceptorInfoMap"),
("RO_SPACE", 0x04bf9): (169, "ScriptMap"), ("RO_SPACE", 0x04bf9): (169, "ScriptMap"),
("RO_SPACE", 0x09ac1): (154, "AccessorInfoMap"), ("RO_SPACE", 0x09c69): (154, "AccessorInfoMap"),
("RO_SPACE", 0x09b11): (153, "AccessCheckInfoMap"), ("RO_SPACE", 0x09cb9): (153, "AccessCheckInfoMap"),
("RO_SPACE", 0x09b61): (155, "AccessorPairMap"), ("RO_SPACE", 0x09d09): (155, "AccessorPairMap"),
("RO_SPACE", 0x09bb1): (156, "AliasedArgumentsEntryMap"), ("RO_SPACE", 0x09d59): (156, "AliasedArgumentsEntryMap"),
("RO_SPACE", 0x09c01): (157, "AllocationMementoMap"), ("RO_SPACE", 0x09da9): (157, "AllocationMementoMap"),
("RO_SPACE", 0x09c51): (158, "AsyncGeneratorRequestMap"), ("RO_SPACE", 0x09df9): (158, "AsyncGeneratorRequestMap"),
("RO_SPACE", 0x09ca1): (159, "DebugInfoMap"), ("RO_SPACE", 0x09e49): (159, "DebugInfoMap"),
("RO_SPACE", 0x09cf1): (160, "FunctionTemplateInfoMap"), ("RO_SPACE", 0x09e99): (160, "FunctionTemplateInfoMap"),
("RO_SPACE", 0x09d41): (162, "InterpreterDataMap"), ("RO_SPACE", 0x09ee9): (162, "InterpreterDataMap"),
("RO_SPACE", 0x09d91): (163, "ModuleInfoEntryMap"), ("RO_SPACE", 0x09f39): (163, "ModuleInfoEntryMap"),
("RO_SPACE", 0x09de1): (164, "ModuleMap"), ("RO_SPACE", 0x09f89): (164, "ModuleMap"),
("RO_SPACE", 0x09e31): (165, "ObjectTemplateInfoMap"), ("RO_SPACE", 0x09fd9): (165, "ObjectTemplateInfoMap"),
("RO_SPACE", 0x09e81): (166, "PromiseCapabilityMap"), ("RO_SPACE", 0x0a029): (166, "PromiseCapabilityMap"),
("RO_SPACE", 0x09ed1): (167, "PromiseReactionMap"), ("RO_SPACE", 0x0a079): (167, "PromiseReactionMap"),
("RO_SPACE", 0x09f21): (168, "PrototypeInfoMap"), ("RO_SPACE", 0x0a0c9): (168, "PrototypeInfoMap"),
("RO_SPACE", 0x09f71): (170, "StackFrameInfoMap"), ("RO_SPACE", 0x0a119): (170, "StackFrameInfoMap"),
("RO_SPACE", 0x09fc1): (172, "Tuple3Map"), ("RO_SPACE", 0x0a169): (172, "Tuple3Map"),
("RO_SPACE", 0x0a011): (174, "WasmDebugInfoMap"), ("RO_SPACE", 0x0a1b9): (174, "WasmDebugInfoMap"),
("RO_SPACE", 0x0a061): (175, "WasmExportedFunctionDataMap"), ("RO_SPACE", 0x0a209): (175, "WasmExportedFunctionDataMap"),
("RO_SPACE", 0x0a0b1): (176, "CallableTaskMap"), ("RO_SPACE", 0x0a259): (176, "CallableTaskMap"),
("RO_SPACE", 0x0a101): (177, "CallbackTaskMap"), ("RO_SPACE", 0x0a2a9): (177, "CallbackTaskMap"),
("RO_SPACE", 0x0a151): (178, "PromiseFulfillReactionJobTaskMap"), ("RO_SPACE", 0x0a2f9): (178, "PromiseFulfillReactionJobTaskMap"),
("RO_SPACE", 0x0a1a1): (179, "PromiseRejectReactionJobTaskMap"), ("RO_SPACE", 0x0a349): (179, "PromiseRejectReactionJobTaskMap"),
("RO_SPACE", 0x0a1f1): (180, "PromiseResolveThenableJobTaskMap"), ("RO_SPACE", 0x0a399): (180, "PromiseResolveThenableJobTaskMap"),
("RO_SPACE", 0x0a241): (181, "AllocationSiteMap"), ("RO_SPACE", 0x0a3e9): (181, "AllocationSiteMap"),
("RO_SPACE", 0x0a291): (181, "AllocationSiteMap"), ("RO_SPACE", 0x0a439): (181, "AllocationSiteMap"),
("MAP_SPACE", 0x02201): (1057, "ExternalMap"), ("MAP_SPACE", 0x02201): (1057, "ExternalMap"),
("MAP_SPACE", 0x02251): (1072, "JSMessageObjectMap"), ("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