diff options
Diffstat (limited to 'deps/v8/src/js/intl.js')
-rw-r--r-- | deps/v8/src/js/intl.js | 142 |
1 files changed, 84 insertions, 58 deletions
diff --git a/deps/v8/src/js/intl.js b/deps/v8/src/js/intl.js index 2e51459883..82c28f79e0 100644 --- a/deps/v8/src/js/intl.js +++ b/deps/v8/src/js/intl.js @@ -29,6 +29,7 @@ var GlobalIntlv8BreakIterator = GlobalIntl.v8BreakIterator; var GlobalNumber = global.Number; var GlobalRegExp = global.RegExp; var GlobalString = global.String; +var GlobalArray = global.Array; var IntlFallbackSymbol = utils.ImportNow("intl_fallback_symbol"); var InternalArray = utils.InternalArray; var MathMax = global.Math.max; @@ -38,6 +39,7 @@ var patternSymbol = utils.ImportNow("intl_pattern_symbol"); var resolvedSymbol = utils.ImportNow("intl_resolved_symbol"); var StringSubstr = GlobalString.prototype.substr; var StringSubstring = GlobalString.prototype.substring; +var ArraySlice = GlobalArray.prototype.slice; utils.Import(function(from) { ArrayJoin = from.ArrayJoin; @@ -67,7 +69,7 @@ endmacro /** * Adds bound method to the prototype of the given object. */ -function AddBoundMethod(obj, methodName, implementation, length, typename, +function AddBoundMethod(obj, methodName, implementation, length, type, compat) { %CheckIsBootstrapping(); var internalName = %CreatePrivateSymbol(methodName); @@ -75,7 +77,10 @@ function AddBoundMethod(obj, methodName, implementation, length, typename, DEFINE_METHOD( obj.prototype, get [methodName]() { - var receiver = Unwrap(this, typename, obj, methodName, compat); + if(!IS_RECEIVER(this)) { + throw %make_type_error(kIncompatibleMethodReceiver, methodName, this); + } + var receiver = %IntlUnwrapReceiver(this, type, obj, methodName, compat); if (IS_UNDEFINED(receiver[internalName])) { var boundMethod; if (IS_UNDEFINED(length) || length === 2) { @@ -120,31 +125,19 @@ function IntlConstruct(receiver, constructor, create, newTarget, args, -function Unwrap(receiver, typename, constructor, method, compat) { - if (!%IsInitializedIntlObjectOfType(receiver, typename)) { - if (compat && receiver instanceof constructor) { - let fallback = receiver[IntlFallbackSymbol]; - if (%IsInitializedIntlObjectOfType(fallback, typename)) { - return fallback; - } - } - throw %make_type_error(kIncompatibleMethodReceiver, method, receiver); - } - return receiver; -} - - // ------------------------------------------------------------------- /** * Caches available locales for each service. */ var AVAILABLE_LOCALES = { + __proto__ : null, 'collator': UNDEFINED, 'numberformat': UNDEFINED, 'dateformat': UNDEFINED, 'breakiterator': UNDEFINED, 'pluralrules': UNDEFINED, + 'relativetimeformat': UNDEFINED, }; /** @@ -363,23 +356,29 @@ function bestFitSupportedLocalesOf(requestedLocales, availableLocales) { function getGetOption(options, caller) { if (IS_UNDEFINED(options)) throw %make_error(kDefaultOptionsMissing, caller); - var getOption = function getOption(property, type, values, defaultValue) { - if (!IS_UNDEFINED(options[property])) { - var value = options[property]; + // Ecma 402 #sec-getoption + var getOption = function (property, type, values, fallback) { + // 1. Let value be ? Get(options, property). + var value = options[property]; + // 2. If value is not undefined, then + if (!IS_UNDEFINED(value)) { switch (type) { + // If type is "boolean", then let value be ToBoolean(value). case 'boolean': value = TO_BOOLEAN(value); break; + // If type is "string", then let value be ToString(value). case 'string': value = TO_STRING(value); break; - case 'number': - value = TO_NUMBER(value); - break; + // Assert: type is "boolean" or "string". default: throw %make_error(kWrongValueType); } + // d. If values is not undefined, then + // If values does not contain an element equal to value, throw a + // RangeError exception. if (!IS_UNDEFINED(values) && %ArrayIndexOf(values, value, 0) === -1) { throw %make_range_error(kValueOutOfRange, value, caller, property); } @@ -387,7 +386,7 @@ function getGetOption(options, caller) { return value; } - return defaultValue; + return fallback; } return getOption; @@ -426,6 +425,9 @@ function resolveLocale(service, requestedLocales, options) { return resolved; } +%InstallToContext([ + "resolve_locale", resolveLocale +]); /** * Look up the longest non-empty prefix of |locale| that is an element of @@ -463,7 +465,7 @@ function attemptSingleLookup(availableLocales, requestedLocale) { var extensionMatch = %regexp_internal_match( GetUnicodeExtensionRE(), requestedLocale); var extension = IS_NULL(extensionMatch) ? '' : extensionMatch[0]; - return {locale: availableLocale, extension: extension}; + return {__proto__: null, locale: availableLocale, extension: extension}; } return UNDEFINED; } @@ -498,6 +500,7 @@ function lookupMatcher(service, requestedLocales) { // Didn't find a match, return default. return { + __proto__: null, locale: 'und', extension: '' }; @@ -1002,8 +1005,9 @@ function CreateCollator(locales, options) { * for a collator. */ var COLLATOR_KEY_MAP = { - 'kn': {'property': 'numeric', 'type': 'boolean'}, - 'kf': {'property': 'caseFirst', 'type': 'string', + __proto__: null, + 'kn': { __proto__: null, 'property': 'numeric', 'type': 'boolean'}, + 'kf': { __proto__: null, 'property': 'caseFirst', 'type': 'string', 'values': ['false', 'lower', 'upper']} }; @@ -1053,7 +1057,7 @@ function CreateCollator(locales, options) { var collator = %CreateCollator(requestedLocale, internalOptions, resolved); - %MarkAsInitializedIntlObjectOfType(collator, 'collator'); + %MarkAsInitializedIntlObjectOfType(collator, COLLATOR_TYPE); collator[resolvedSymbol] = resolved; return collator; @@ -1079,8 +1083,12 @@ function CollatorConstructor() { DEFINE_METHOD( GlobalIntlCollator.prototype, resolvedOptions() { - var coll = Unwrap(this, 'collator', GlobalIntlCollator, 'resolvedOptions', - false); + 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, @@ -1123,7 +1131,7 @@ function compare(collator, x, y) { }; -AddBoundMethod(GlobalIntlCollator, 'compare', compare, 2, 'collator', false); +AddBoundMethod(GlobalIntlCollator, 'compare', compare, 2, COLLATOR_TYPE, false); function PluralRulesConstructor() { if (IS_UNDEFINED(new.target)) { @@ -1166,7 +1174,7 @@ function PluralRulesConstructor() { var pluralRules = %CreatePluralRules(requestedLocale, internalOptions, resolved); - %MarkAsInitializedIntlObjectOfType(pluralRules, 'pluralrules'); + %MarkAsInitializedIntlObjectOfType(pluralRules, PLURAL_RULES_TYPE); pluralRules[resolvedSymbol] = resolved; return pluralRules; @@ -1176,7 +1184,7 @@ function PluralRulesConstructor() { DEFINE_METHOD( GlobalIntlPluralRules.prototype, resolvedOptions() { - if (!%IsInitializedIntlObjectOfType(this, 'pluralrules')) { + if (!%IsInitializedIntlObjectOfType(this, PLURAL_RULES_TYPE)) { throw %make_type_error(kIncompatibleMethodReceiver, 'Intl.PluralRules.prototype.resolvedOptions', this); @@ -1201,8 +1209,7 @@ DEFINE_METHOD( } defineWECProperty(result, 'pluralCategories', - this[resolvedSymbol].pluralCategories); - + %_Call(ArraySlice, this[resolvedSymbol].pluralCategories)); return result; } ); @@ -1217,7 +1224,7 @@ DEFINE_METHOD( DEFINE_METHOD( GlobalIntlPluralRules.prototype, select(value) { - if (!%IsInitializedIntlObjectOfType(this, 'pluralrules')) { + if (!%IsInitializedIntlObjectOfType(this, PLURAL_RULES_TYPE)) { throw %make_type_error(kIncompatibleMethodReceiver, 'Intl.PluralRules.prototype.select', this); @@ -1345,7 +1352,8 @@ function CreateNumberFormat(locales, options) { * for a number format. */ var NUMBER_FORMAT_KEY_MAP = { - 'nu': {'property': UNDEFINED, 'type': 'string'} + __proto__: null, + 'nu': {__proto__: null, 'property': UNDEFINED, 'type': 'string'} }; var extension = setOptions(options, extensionMap, NUMBER_FORMAT_KEY_MAP, @@ -1378,7 +1386,7 @@ function CreateNumberFormat(locales, options) { {value: currencyDisplay, writable: true}); } - %MarkAsInitializedIntlObjectOfType(numberFormat, 'numberformat'); + %MarkAsInitializedIntlObjectOfType(numberFormat, NUMBER_FORMAT_TYPE); numberFormat[resolvedSymbol] = resolved; return numberFormat; @@ -1404,8 +1412,13 @@ function NumberFormatConstructor() { DEFINE_METHOD( GlobalIntlNumberFormat.prototype, resolvedOptions() { - var format = Unwrap(this, 'numberformat', GlobalIntlNumberFormat, - 'resolvedOptions', true); + var methodName = 'resolvedOptions'; + 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, @@ -1463,10 +1476,6 @@ function formatNumber(formatter, value) { return %InternalNumberFormat(formatter, number); } - -AddBoundMethod(GlobalIntlNumberFormat, 'format', formatNumber, 1, - 'numberformat', true); - /** * Returns a string that matches LDML representation of the options object. */ @@ -1705,8 +1714,9 @@ function CreateDateTimeFormat(locales, options) { * for a date/time format. */ var DATETIME_FORMAT_KEY_MAP = { - 'ca': {'property': UNDEFINED, 'type': 'string'}, - 'nu': {'property': UNDEFINED, 'type': 'string'} + __proto__: null, + 'ca': {__proto__: null, 'property': UNDEFINED, 'type': 'string'}, + 'nu': {__proto__: null, 'property': UNDEFINED, 'type': 'string'} }; var extension = setOptions(options, extensionMap, DATETIME_FORMAT_KEY_MAP, @@ -1734,13 +1744,14 @@ function CreateDateTimeFormat(locales, options) { }); var dateFormat = %CreateDateTimeFormat( - requestedLocale, {skeleton: ldmlString, timeZone: tz}, resolved); + requestedLocale, + {__proto__: null, skeleton: ldmlString, timeZone: tz}, resolved); if (resolved.timeZone === "Etc/Unknown") { throw %make_range_error(kUnsupportedTimeZone, tz); } - %MarkAsInitializedIntlObjectOfType(dateFormat, 'dateformat'); + %MarkAsInitializedIntlObjectOfType(dateFormat, DATE_TIME_FORMAT_TYPE); dateFormat[resolvedSymbol] = resolved; return dateFormat; @@ -1766,8 +1777,13 @@ function DateTimeFormatConstructor() { DEFINE_METHOD( GlobalIntlDateTimeFormat.prototype, resolvedOptions() { - var format = Unwrap(this, 'dateformat', GlobalIntlDateTimeFormat, - 'resolvedOptions', true); + var methodName = 'resolvedOptions'; + if(!IS_RECEIVER(this)) { + throw %make_type_error(kIncompatibleMethodReceiver, methodName, this); + } + var format = %IntlUnwrapReceiver(this, DATE_TIME_FORMAT_TYPE, + GlobalIntlDateTimeFormat, + methodName, true); /** * Maps ICU calendar names to LDML/BCP47 types for key 'ca'. @@ -1776,6 +1792,7 @@ DEFINE_METHOD( * http://www.unicode.org/repos/cldr/tags/latest/common/bcp47/calendar.xml */ var ICU_CALENDAR_MAP = { + __proto__: null, 'gregorian': 'gregory', 'ethiopic-amete-alem': 'ethioaa' }; @@ -1841,7 +1858,7 @@ function formatDate(formatter, dateValue) { } // Length is 1 as specified in ECMA 402 v2+ -AddBoundMethod(GlobalIntlDateTimeFormat, 'format', formatDate, 1, 'dateformat', +AddBoundMethod(GlobalIntlDateTimeFormat, 'format', formatDate, 1, DATE_TIME_FORMAT_TYPE, true); @@ -1911,7 +1928,7 @@ function CreateBreakIterator(locales, options) { var iterator = %CreateBreakIterator(locale.locale, internalOptions, resolved); - %MarkAsInitializedIntlObjectOfType(iterator, 'breakiterator'); + %MarkAsInitializedIntlObjectOfType(iterator, BREAK_ITERATOR_TYPE); iterator[resolvedSymbol] = resolved; return iterator; @@ -1941,8 +1958,13 @@ DEFINE_METHOD( throw %make_type_error(kOrdinaryFunctionCalledAsConstructor); } - var segmenter = Unwrap(this, 'breakiterator', GlobalIntlv8BreakIterator, - 'resolvedOptions', false); + var methodName = 'resolvedOptions'; + if(!IS_RECEIVER(this)) { + throw %make_type_error(kIncompatibleMethodReceiver, methodName, this); + } + var segmenter = %IntlUnwrapReceiver(this, BREAK_ITERATOR_TYPE, + GlobalIntlv8BreakIterator, methodName, + false); return { locale: segmenter[resolvedSymbol].locale, @@ -2012,16 +2034,19 @@ function breakType(iterator) { AddBoundMethod(GlobalIntlv8BreakIterator, 'adoptText', adoptText, 1, - 'breakiterator'); -AddBoundMethod(GlobalIntlv8BreakIterator, 'first', first, 0, 'breakiterator'); -AddBoundMethod(GlobalIntlv8BreakIterator, 'next', next, 0, 'breakiterator'); + BREAK_ITERATOR_TYPE, false); +AddBoundMethod(GlobalIntlv8BreakIterator, 'first', first, 0, + BREAK_ITERATOR_TYPE, false); +AddBoundMethod(GlobalIntlv8BreakIterator, 'next', next, 0, + BREAK_ITERATOR_TYPE, false); AddBoundMethod(GlobalIntlv8BreakIterator, 'current', current, 0, - 'breakiterator'); + BREAK_ITERATOR_TYPE, false); AddBoundMethod(GlobalIntlv8BreakIterator, 'breakType', breakType, 0, - 'breakiterator'); + BREAK_ITERATOR_TYPE, false); // Save references to Intl objects and methods we use, for added security. var savedObjects = { + __proto__: null, 'collator': GlobalIntlCollator, 'numberformat': GlobalIntlNumberFormat, 'dateformatall': GlobalIntlDateTimeFormat, @@ -2033,6 +2058,7 @@ var savedObjects = { // Default (created with undefined locales and options parameters) collator, // number and date format instances. They'll be created as needed. var defaultObjects = { + __proto__: null, 'collator': UNDEFINED, 'numberformat': UNDEFINED, 'dateformatall': UNDEFINED, |