[intl] Create the Intl constructors to C++

This patch moves the creation of the Intl constructors from JavaScript
to C++ in bootstrapper.cc, to match all of the other builtins exposed
to the web.

BUG=v8:5751

Review-Url: https://codereview.chromium.org/2586763002
Cr-Commit-Position: refs/heads/master@{#41959}
This commit is contained in:
littledan 2016-12-27 09:10:00 -08:00 committed by Commit bot
parent d20c23cd13
commit e0359c3629
3 changed files with 148 additions and 52 deletions

View File

@ -2326,6 +2326,74 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY));
}
#ifdef V8_I18N_SUPPORT
{ // -- I n t l
Handle<String> name = factory->InternalizeUtf8String("Intl");
Handle<JSFunction> cons = factory->NewFunction(name);
JSFunction::SetInstancePrototype(
cons,
Handle<Object>(native_context()->initial_object_prototype(), isolate));
Handle<JSObject> intl = factory->NewJSObject(cons, TENURED);
DCHECK(intl->IsJSObject());
JSObject::AddProperty(global, name, intl, DONT_ENUM);
Handle<JSObject> date_time_format_prototype =
factory->NewJSObject(isolate->object_function(), TENURED);
// Install the @@toStringTag property on the {prototype}.
JSObject::AddProperty(
date_time_format_prototype, factory->to_string_tag_symbol(),
factory->Object_string(),
static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY));
Handle<JSFunction> date_time_format_constructor = InstallFunction(
intl, "DateTimeFormat", JS_OBJECT_TYPE, JSObject::kHeaderSize,
date_time_format_prototype, Builtins::kIllegal);
JSObject::AddProperty(date_time_format_prototype,
factory->constructor_string(),
date_time_format_constructor, DONT_ENUM);
Handle<JSObject> number_format_prototype =
factory->NewJSObject(isolate->object_function(), TENURED);
// Install the @@toStringTag property on the {prototype}.
JSObject::AddProperty(
number_format_prototype, factory->to_string_tag_symbol(),
factory->Object_string(),
static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY));
Handle<JSFunction> number_format_constructor = InstallFunction(
intl, "NumberFormat", JS_OBJECT_TYPE, JSObject::kHeaderSize,
number_format_prototype, Builtins::kIllegal);
JSObject::AddProperty(number_format_prototype,
factory->constructor_string(),
number_format_constructor, DONT_ENUM);
Handle<JSObject> collator_prototype =
factory->NewJSObject(isolate->object_function(), TENURED);
// Install the @@toStringTag property on the {prototype}.
JSObject::AddProperty(
collator_prototype, factory->to_string_tag_symbol(),
factory->Object_string(),
static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY));
Handle<JSFunction> collator_constructor =
InstallFunction(intl, "Collator", JS_OBJECT_TYPE, JSObject::kHeaderSize,
collator_prototype, Builtins::kIllegal);
JSObject::AddProperty(collator_prototype, factory->constructor_string(),
collator_constructor, DONT_ENUM);
Handle<JSObject> v8_break_iterator_prototype =
factory->NewJSObject(isolate->object_function(), TENURED);
// Install the @@toStringTag property on the {prototype}.
JSObject::AddProperty(
v8_break_iterator_prototype, factory->to_string_tag_symbol(),
factory->Object_string(),
static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY));
Handle<JSFunction> v8_break_iterator_constructor = InstallFunction(
intl, "v8BreakIterator", JS_OBJECT_TYPE, JSObject::kHeaderSize,
v8_break_iterator_prototype, Builtins::kIllegal);
JSObject::AddProperty(v8_break_iterator_prototype,
factory->constructor_string(),
v8_break_iterator_constructor, DONT_ENUM);
}
#endif // V8_I18N_SUPPORT
{ // -- A r r a y B u f f e r
Handle<JSFunction> array_buffer_fun = InstallArrayBuffer(
global, "ArrayBuffer", Builtins::kArrayBufferPrototypeGetByteLength,

View File

@ -20,6 +20,11 @@
var ArrayJoin;
var ArrayPush;
var GlobalDate = global.Date;
var GlobalIntl = global.Intl;
var GlobalIntlDateTimeFormat = GlobalIntl.DateTimeFormat;
var GlobalIntlNumberFormat = GlobalIntl.NumberFormat;
var GlobalIntlCollator = GlobalIntl.Collator;
var GlobalIntlv8BreakIterator = GlobalIntl.v8BreakIterator;
var GlobalNumber = global.Number;
var GlobalRegExp = global.RegExp;
var GlobalString = global.String;
@ -47,14 +52,6 @@ function InstallFunction(object, name, func) {
}
function InstallConstructor(object, name, func) {
%CheckIsBootstrapping();
SetFunctionName(func, name);
%AddNamedProperty(object, name, func, DONT_ENUM);
%SetNativeFlag(func);
%ToFastProperties(object);
}
/**
* Adds bound method to the prototype of the given object.
*/
@ -138,10 +135,6 @@ function Unwrap(receiver, typename, constructor, method, compat) {
// -------------------------------------------------------------------
var Intl = {};
%AddNamedProperty(global, "Intl", Intl, DONT_ENUM);
/**
* Caches available locales for each service.
*/
@ -948,7 +941,7 @@ var resolvedAccessor = {
};
// ECMA 402 section 8.2.1
InstallFunction(Intl, 'getCanonicalLocales', function(locales) {
InstallFunction(GlobalIntl, 'getCanonicalLocales', function(locales) {
return makeArray(canonicalizeLocaleList(locales));
}
);
@ -1066,18 +1059,19 @@ function initializeCollator(collator, locales, options) {
*
* @constructor
*/
function Collator() {
return IntlConstruct(this, Collator, initializeCollator, new.target,
function CollatorConstructor() {
return IntlConstruct(this, GlobalIntlCollator, initializeCollator, new.target,
arguments);
}
InstallConstructor(Intl, 'Collator', Collator);
%SetCode(GlobalIntlCollator, CollatorConstructor);
/**
* Collator resolvedOptions method.
*/
InstallFunction(Intl.Collator.prototype, 'resolvedOptions', function() {
var coll = Unwrap(this, 'collator', Collator, 'resolvedOptions', false);
InstallFunction(GlobalIntlCollator.prototype, 'resolvedOptions', function() {
var coll = Unwrap(this, 'collator', GlobalIntlCollator, 'resolvedOptions',
false);
var locale = getOptimalLanguageTag(coll[resolvedSymbol].requestedLocale,
coll[resolvedSymbol].locale);
@ -1100,7 +1094,7 @@ InstallFunction(Intl.Collator.prototype, 'resolvedOptions', function() {
* order in the returned list as in the input list.
* Options are optional parameter.
*/
InstallFunction(Intl.Collator, 'supportedLocalesOf', function(locales) {
InstallFunction(GlobalIntlCollator, 'supportedLocalesOf', function(locales) {
return supportedLocalesOf('collator', locales, arguments[1]);
}
);
@ -1122,7 +1116,7 @@ function compare(collator, x, y) {
};
AddBoundMethod(Intl.Collator, 'compare', compare, 2, 'collator', false);
AddBoundMethod(GlobalIntlCollator, 'compare', compare, 2, 'collator', false);
/**
* Verifies that the input is a well-formed ISO 4217 currency code.
@ -1288,18 +1282,19 @@ function initializeNumberFormat(numberFormat, locales, options) {
*
* @constructor
*/
function NumberFormat() {
return IntlConstruct(this, NumberFormat, initializeNumberFormat, new.target,
arguments, true);
function NumberFormatConstructor() {
return IntlConstruct(this, GlobalIntlNumberFormat, initializeNumberFormat,
new.target, arguments, true);
}
InstallConstructor(Intl, 'NumberFormat', NumberFormat);
%SetCode(GlobalIntlNumberFormat, NumberFormatConstructor);
/**
* NumberFormat resolvedOptions method.
*/
InstallFunction(Intl.NumberFormat.prototype, 'resolvedOptions', function() {
var format = Unwrap(this, 'numberformat', NumberFormat,
InstallFunction(GlobalIntlNumberFormat.prototype, 'resolvedOptions',
function() {
var format = Unwrap(this, 'numberformat', GlobalIntlNumberFormat,
'resolvedOptions', true);
var locale = getOptimalLanguageTag(format[resolvedSymbol].requestedLocale,
format[resolvedSymbol].locale);
@ -1341,7 +1336,8 @@ InstallFunction(Intl.NumberFormat.prototype, 'resolvedOptions', function() {
* order in the returned list as in the input list.
* Options are optional parameter.
*/
InstallFunction(Intl.NumberFormat, 'supportedLocalesOf', function(locales) {
InstallFunction(GlobalIntlNumberFormat, 'supportedLocalesOf',
function(locales) {
return supportedLocalesOf('numberformat', locales, arguments[1]);
}
);
@ -1361,8 +1357,8 @@ function formatNumber(formatter, value) {
}
AddBoundMethod(Intl.NumberFormat, 'format', formatNumber, 1, 'numberformat',
true);
AddBoundMethod(GlobalIntlNumberFormat, 'format', formatNumber, 1,
'numberformat', true);
/**
* Returns a string that matches LDML representation of the options object.
@ -1655,18 +1651,19 @@ function initializeDateTimeFormat(dateFormat, locales, options) {
*
* @constructor
*/
function DateTimeFormat() {
return IntlConstruct(this, DateTimeFormat, initializeDateTimeFormat,
function DateTimeFormatConstructor() {
return IntlConstruct(this, GlobalIntlDateTimeFormat, initializeDateTimeFormat,
new.target, arguments, true);
}
InstallConstructor(Intl, 'DateTimeFormat', DateTimeFormat);
%SetCode(GlobalIntlDateTimeFormat, DateTimeFormatConstructor);
/**
* DateTimeFormat resolvedOptions method.
*/
InstallFunction(Intl.DateTimeFormat.prototype, 'resolvedOptions', function() {
var format = Unwrap(this, 'dateformat', DateTimeFormat,
InstallFunction(GlobalIntlDateTimeFormat.prototype, 'resolvedOptions',
function() {
var format = Unwrap(this, 'dateformat', GlobalIntlDateTimeFormat,
'resolvedOptions', true);
/**
@ -1719,7 +1716,8 @@ InstallFunction(Intl.DateTimeFormat.prototype, 'resolvedOptions', function() {
* order in the returned list as in the input list.
* Options are optional parameter.
*/
InstallFunction(Intl.DateTimeFormat, 'supportedLocalesOf', function(locales) {
InstallFunction(GlobalIntlDateTimeFormat, 'supportedLocalesOf',
function(locales) {
return supportedLocalesOf('dateformat', locales, arguments[1]);
}
);
@ -1766,7 +1764,7 @@ function FormatDateToParts(dateValue) {
// 0 because date is optional argument.
AddBoundMethod(Intl.DateTimeFormat, 'format', formatDate, 0, 'dateformat',
AddBoundMethod(GlobalIntlDateTimeFormat, 'format', formatDate, 0, 'dateformat',
true);
@ -1856,23 +1854,23 @@ function initializeBreakIterator(iterator, locales, options) {
*
* @constructor
*/
function v8BreakIterator() {
return IntlConstruct(this, v8BreakIterator, initializeBreakIterator,
function v8BreakIteratorConstructor() {
return IntlConstruct(this, GlobalIntlv8BreakIterator, initializeBreakIterator,
new.target, arguments);
}
InstallConstructor(Intl, 'v8BreakIterator', v8BreakIterator);
%SetCode(GlobalIntlv8BreakIterator, v8BreakIteratorConstructor);
/**
* BreakIterator resolvedOptions method.
*/
InstallFunction(Intl.v8BreakIterator.prototype, 'resolvedOptions',
InstallFunction(GlobalIntlv8BreakIterator.prototype, 'resolvedOptions',
function() {
if (!IS_UNDEFINED(new.target)) {
throw %make_type_error(kOrdinaryFunctionCalledAsConstructor);
}
var segmenter = Unwrap(this, 'breakiterator', v8BreakIterator,
var segmenter = Unwrap(this, 'breakiterator', GlobalIntlv8BreakIterator,
'resolvedOptions', false);
var locale =
@ -1893,7 +1891,7 @@ InstallFunction(Intl.v8BreakIterator.prototype, 'resolvedOptions',
* order in the returned list as in the input list.
* Options are optional parameter.
*/
InstallFunction(Intl.v8BreakIterator, 'supportedLocalesOf',
InstallFunction(GlobalIntlv8BreakIterator, 'supportedLocalesOf',
function(locales) {
if (!IS_UNDEFINED(new.target)) {
throw %make_type_error(kOrdinaryFunctionCalledAsConstructor);
@ -1946,21 +1944,22 @@ function breakType(iterator) {
}
AddBoundMethod(Intl.v8BreakIterator, 'adoptText', adoptText, 1,
AddBoundMethod(GlobalIntlv8BreakIterator, 'adoptText', adoptText, 1,
'breakiterator');
AddBoundMethod(Intl.v8BreakIterator, 'first', first, 0, 'breakiterator');
AddBoundMethod(Intl.v8BreakIterator, 'next', next, 0, 'breakiterator');
AddBoundMethod(Intl.v8BreakIterator, 'current', current, 0, 'breakiterator');
AddBoundMethod(Intl.v8BreakIterator, 'breakType', breakType, 0,
AddBoundMethod(GlobalIntlv8BreakIterator, 'first', first, 0, 'breakiterator');
AddBoundMethod(GlobalIntlv8BreakIterator, 'next', next, 0, 'breakiterator');
AddBoundMethod(GlobalIntlv8BreakIterator, 'current', current, 0,
'breakiterator');
AddBoundMethod(GlobalIntlv8BreakIterator, 'breakType', breakType, 0,
'breakiterator');
// Save references to Intl objects and methods we use, for added security.
var savedObjects = {
'collator': Intl.Collator,
'numberformat': Intl.NumberFormat,
'dateformatall': Intl.DateTimeFormat,
'dateformatdate': Intl.DateTimeFormat,
'dateformattime': Intl.DateTimeFormat
'collator': GlobalIntlCollator,
'numberformat': GlobalIntlNumberFormat,
'dateformatall': GlobalIntlDateTimeFormat,
'dateformatdate': GlobalIntlDateTimeFormat,
'dateformattime': GlobalIntlDateTimeFormat
};

29
test/intl/toStringTag.js Normal file
View File

@ -0,0 +1,29 @@
// Copyright 2016 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.
let descriptor;
descriptor = Object.getOwnPropertyDescriptor(Intl.DateTimeFormat.prototype,
Symbol.toStringTag);
assertEquals("Object", descriptor.value);
assertFalse(descriptor.writable);
assertFalse(descriptor.enumerable);
assertTrue(descriptor.configurable);
descriptor = Object.getOwnPropertyDescriptor(Intl.NumberFormat.prototype,
Symbol.toStringTag);
assertEquals("Object", descriptor.value);
assertFalse(descriptor.writable);
assertFalse(descriptor.enumerable);
assertTrue(descriptor.configurable);
descriptor = Object.getOwnPropertyDescriptor(Intl.Collator.prototype,
Symbol.toStringTag);
assertEquals("Object", descriptor.value);
assertFalse(descriptor.writable);
assertFalse(descriptor.enumerable);
assertTrue(descriptor.configurable);