[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:
parent
d20c23cd13
commit
e0359c3629
@ -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,
|
||||
|
103
src/js/i18n.js
103
src/js/i18n.js
@ -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
29
test/intl/toStringTag.js
Normal 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);
|
Loading…
Reference in New Issue
Block a user