Bug 769872 - Add self-hosted JavaScript core of Intl constructors Collator, NumberFormat, DateTimeFormat (part 11). r=jwalden
authorNorbert Lindenberg <mozilladev@lindenbergsoftware.com>
Fri, 22 Feb 2013 15:31:09 -0800
changeset 133424 ca9fbb261ec706089a2a98a0bfaa1d98de458985
parent 133423 f9b5cfcd1ca74a38cb4c9e80d733b984d6c97792
child 133425 544ad097d83afa42a14f10bfdafe5edf3f96a9b2
push idunknown
push userunknown
push dateunknown
reviewersjwalden
bugs769872
milestone22.0a1
Bug 769872 - Add self-hosted JavaScript core of Intl constructors Collator, NumberFormat, DateTimeFormat (part 11). r=jwalden
js/src/builtin/Intl.cpp
js/src/builtin/Intl.js
js/src/vm/CommonPropertyNames.h
--- a/js/src/builtin/Intl.cpp
+++ b/js/src/builtin/Intl.cpp
@@ -159,17 +159,17 @@ InitCollatorClass(JSContext *cx, HandleO
         return NULL;
 
     /*
      * Install the getter for Collator.prototype.compare, which returns a bound
      * comparison function for the specified Collator object (suitable for
      * passing to methods like Array.prototype.sort).
      */
     RootedValue getter(cx);
-    if (!cx->global()->getIntrinsicValue(cx, cx->names().CollatorCompare, &getter))
+    if (!cx->global()->getIntrinsicValue(cx, cx->names().CollatorCompareGet, &getter))
         return NULL;
     RootedValue undefinedValue(cx, UndefinedValue());
     if (!JSObject::defineProperty(cx, proto, cx->names().compare, undefinedValue,
                                   JS_DATA_TO_FUNC_PTR(JSPropertyOp, &getter.toObject()),
                                   NULL, JSPROP_GETTER)) {
         return NULL;
     }
 
@@ -311,17 +311,17 @@ InitNumberFormatClass(JSContext *cx, Han
         return NULL;
 
     /*
      * Install the getter for NumberFormat.prototype.format, which returns a
      * bound formatting function for the specified NumberFormat object (suitable
      * for passing to methods like Array.prototype.map).
      */
     RootedValue getter(cx);
-    if (!cx->global()->getIntrinsicValue(cx, cx->names().NumberFormatFormat, &getter))
+    if (!cx->global()->getIntrinsicValue(cx, cx->names().NumberFormatFormatGet, &getter))
         return NULL;
     RootedValue undefinedValue(cx, UndefinedValue());
     if (!JSObject::defineProperty(cx, proto, cx->names().format, undefinedValue,
                                   JS_DATA_TO_FUNC_PTR(JSPropertyOp, &getter.toObject()),
                                   NULL, JSPROP_GETTER)) {
         return NULL;
     }
 
@@ -463,17 +463,17 @@ InitDateTimeFormatClass(JSContext *cx, H
         return NULL;
 
     /*
      * Install the getter for DateTimeFormat.prototype.format, which returns a
      * bound formatting function for the specified DateTimeFormat object
      * (suitable for passing to methods like Array.prototype.map).
      */
     RootedValue getter(cx);
-    if (!cx->global()->getIntrinsicValue(cx, cx->names().DateTimeFormatFormat, &getter))
+    if (!cx->global()->getIntrinsicValue(cx, cx->names().DateTimeFormatFormatGet, &getter))
         return NULL;
     RootedValue undefinedValue(cx, UndefinedValue());
     if (!JSObject::defineProperty(cx, proto, cx->names().format, undefinedValue,
                                   JS_DATA_TO_FUNC_PTR(JSPropertyOp, &getter.toObject()),
                                   NULL, JSPROP_GETTER)) {
         return NULL;
     }
 
--- a/js/src/builtin/Intl.js
+++ b/js/src/builtin/Intl.js
@@ -570,21 +570,23 @@ function BestFitMatcher(availableLocales
  * determines the best available language to meet the request. Options specified
  * through Unicode extension subsequences are negotiated separately, taking the
  * caller's relevant extensions and locale data as well as client-provided
  * options into consideration.
  *
  * Spec: ECMAScript Internationalization API Specification, 9.2.5.
  */
 function ResolveLocale(availableLocales, requestedLocales, options, relevantExtensionKeys, localeData) {
+    /*jshint laxbreak: true */
+
     // Steps 1-3.
     var matcher = options.localeMatcher;
-    var r = (matcher === "lookup") ?
-            LookupMatcher(availableLocales, requestedLocales) :
-            BestFitMatcher(availableLocales, requestedLocales);
+    var r = (matcher === "lookup")
+            ? LookupMatcher(availableLocales, requestedLocales)
+            : BestFitMatcher(availableLocales, requestedLocales);
 
     // Step 4.
     var foundLocale = r.locale;
 
     // Step 5.a.
     var extension = r.extension;
     var extensionIndex, extensionSubtags, extensionSubtagsLength;
 
@@ -751,35 +753,37 @@ function BestFitSupportedLocales(availab
 /**
  * Returns the subset of requestedLocales for which availableLocales has a
  * matching (possibly fallback) locale. Locales appear in the same order in the
  * returned list as in the input list.
  *
  * Spec: ECMAScript Internationalization API Specification, 9.2.8.
  */
 function SupportedLocales(availableLocales, requestedLocales, options) {
+    /*jshint laxbreak: true */
+
     // Step 1.
     var matcher;
     if (options !== undefined) {
         // Steps 1.a-b.
         options = ToObject(options);
         matcher = options.localeMatcher;
 
         // Step 1.c.
         if (matcher !== undefined) {
             matcher = ToString(matcher);
             if (matcher !== "lookup" && matcher !== "best fit")
                 ThrowError(JSMSG_INVALID_LOCALE_MATCHER, matcher);
         }
     }
 
     // Steps 2-3.
-    var subset = (matcher === undefined || matcher === "best fit") ?
-                 BestFitSupportedLocales(availableLocales, requestedLocales) :
-                 LookupSupportedLocales(availableLocales, requestedLocales);
+    var subset = (matcher === undefined || matcher === "best fit")
+                 ? BestFitSupportedLocales(availableLocales, requestedLocales)
+                 : LookupSupportedLocales(availableLocales, requestedLocales);
 
     // Step 4.
     for (var i = 0; i < subset.length; i++)
         std_Object_defineProperty(subset, i, {value: subset[i], writable: false, enumerable: true, configurable: false});
 //    ??? commented out because of SpiderMonkey bugs 591059 and 598996
 //    std_Object_defineProperty(subset, "length", {value: subset.length, writable: false, enumerable: false, configurable: false});
 
     // Step 5.
@@ -989,24 +993,24 @@ function InitializeCollator(collator, lo
     opt.localeMatcher = matcher;
 
     // Check all allowed options properties and convert them to extension keys.
     // Steps 13-13.a.
     var key, mapping, property, value;
     for (key in collatorKeyMappings) {
         if (callFunction(std_Object_hasOwnProperty, collatorKeyMappings, key)) {
             mapping = collatorKeyMappings[key];
-    
+
             // Step 13.b.
             value = GetOption(options, mapping.property, mapping.type, mapping.values, undefined);
-    
+
             // Step 13.c.
             if (mapping.type === "boolean" && value !== undefined)
                 value = callFunction(std_Boolean_toString, value);
-    
+
             // Step 13.d.
             opt[key] = value;
         }
     }
 
     // Compute effective locale.
     // Step 14.
     var relevantExtensionKeys = Collator.relevantExtensionKeys;
@@ -1068,8 +1072,143 @@ function InitializeCollator(collator, lo
     internals.ignorePunctuation = ip;
 
     // Step 25.
     internals.boundFormat = undefined;
 
     // Step 26.
     internals.initializedCollator = true;
 }
+
+
+/**
+ * Returns the subset of the given locale list for which this locale list has a
+ * matching (possibly fallback) locale. Locales appear in the same order in the
+ * returned list as in the input list.
+ *
+ * Spec: ECMAScript Internationalization API Specification, 10.2.2.
+ */
+function Intl_Collator_supportedLocalesOf(locales /*, options*/) {
+    var options = arguments.length > 1 ? arguments[1] : undefined;
+
+    var availableLocales = collatorInternalProperties.availableLocales;
+    var requestedLocales = CanonicalizeLocaleList(locales);
+    return SupportedLocales(availableLocales, requestedLocales, options);
+}
+
+
+/**
+ * Collator internal properties.
+ *
+ * Spec: ECMAScript Internationalization API Specification, 9.1 and 10.2.3.
+ */
+var collatorInternalProperties = {
+    sortLocaleData: collatorSortLocaleData,
+    searchLocaleData: collatorSearchLocaleData,
+    availableLocales: runtimeAvailableLocales, // stub
+    relevantExtensionKeys: ["co", "kn"]
+};
+
+
+function collatorSortLocaleData(locale) {
+    // the following data may or may not match any actual locale support
+    return {
+        co: [null],
+        kn: ["false", "true"]
+    };
+}
+
+
+function collatorSearchLocaleData(locale) {
+    // the following data may or may not match any actual locale support
+    return {
+        co: [null],
+        kn: ["false", "true"],
+        sensitivity: "variant"
+    };
+}
+
+
+/**
+ * Function to be bound and returned by Intl.Collator.prototype.format.
+ *
+ * Spec: ECMAScript Internationalization API Specification, 12.3.2.
+ */
+function collatorCompareToBind(x, y) {
+    // Steps 1.a.i-ii implemented by ECMAScript declaration binding instantiation,
+    // ES5.1 10.5, step 4.d.ii.
+
+    // Step 1.a.iii-v.
+    var X = ToString(x);
+    var Y = ToString(y);
+    return CompareStrings(this, X, Y);
+}
+
+
+/**
+ * Returns a function bound to this Collator that compares x (converted to a
+ * String value) and y (converted to a String value),
+ * and returns a number less than 0 if x < y, 0 if x = y, or a number greater
+ * than 0 if x > y according to the sort order for the locale and collation
+ * options of this Collator object.
+ *
+ * Spec: ECMAScript Internationalization API Specification, 10.3.2.
+ */
+function Intl_Collator_compare_get() {
+    // Check "this Collator object" per introduction of section 10.3.
+    var internals = checkIntlAPIObject(this, "Collator", "compare");
+
+    // Step 1.
+    if (internals.boundCompare === undefined) {
+        // Step 1.a.
+        var F = collatorCompareToBind;
+
+        // Step 1.b-d.
+        var bc = callFunction(std_Function_bind, F, this);
+        internals.boundCompare = bc;
+    }
+
+    // Step 2.
+    return internals.boundCompare;
+}
+
+
+/**
+ * Compares x (converted to a String value) and y (converted to a String value),
+ * and returns a number less than 0 if x < y, 0 if x = y, or a number greater
+ * than 0 if x > y according to the sort order for the locale and collation
+ * options of this Collator object.
+ *
+ * Spec: ECMAScript Internationalization API Specification, 10.3.2.
+ */
+function CompareStrings(collator, x, y) {
+    assert(typeof x === "string", "CompareStrings");
+    assert(typeof y === "string", "CompareStrings");
+
+    // ??? stub
+    return x.localeCompare(y);
+}
+
+
+/**
+ * Returns the resolved options for a Collator object.
+ *
+ * Spec: ECMAScript Internationalization API Specification, 10.3.3 and 10.4.
+ */
+function Intl_Collator_resolvedOptions() {
+    // Check "this Collator object" per introduction of section 10.3.
+    var internals = checkIntlAPIObject(this, "Collator", "resolvedOptions");
+
+    var result = {
+        locale: internals.locale,
+        usage: internals.usage,
+        sensitivity: internals.sensitivity,
+        ignorePunctuation: internals.ignorePunctuation
+    };
+
+    var relevantExtensionKeys = collatorInternalProperties.relevantExtensionKeys;
+    for (var i = 0; i < relevantExtensionKeys.length; i++) {
+        var key = relevantExtensionKeys[i];
+        var property = (key === "co") ? "collation" : collatorKeyMappings[key].property;
+        defineProperty(result, property, internals[property]);
+    }
+    return result;
+}
--- a/js/src/vm/CommonPropertyNames.h
+++ b/js/src/vm/CommonPropertyNames.h
@@ -23,24 +23,24 @@
     macro(byteOffset, byteOffset, "byteOffset") \
     macro(BYTES_PER_ELEMENT, BYTES_PER_ELEMENT, "BYTES_PER_ELEMENT") \
     macro(call, call, "call") \
     macro(callee, callee, "callee") \
     macro(caller, caller, "caller") \
     macro(callFunction, callFunction, "callFunction") \
     macro(classPrototype, classPrototype, "prototype") \
     macro(Collator, Collator, "Collator") \
-    macro(CollatorCompare, CollatorCompare, "Intl_Collator_compare") \
+    macro(CollatorCompareGet, CollatorCompareGet, "Intl_Collator_compare_get") \
     macro(columnNumber, columnNumber, "columnNumber") \
     macro(compare, compare, "compare") \
     macro(configurable, configurable, "configurable") \
     macro(construct, construct, "construct") \
     macro(constructor, constructor, "constructor") \
     macro(DateTimeFormat, DateTimeFormat, "DateTimeFormat") \
-    macro(DateTimeFormatFormat, DateTimeFormatFormat, "Intl_DateTimeFormat_format") \
+    macro(DateTimeFormatFormatGet, DateTimeFormatFormatGet, "Intl_DateTimeFormat_format_get") \
     macro(decodeURI, decodeURI, "decodeURI") \
     macro(decodeURIComponent, decodeURIComponent, "decodeURIComponent") \
     macro(defineProperty, defineProperty, "defineProperty") \
     macro(defineGetter, defineGetter, "__defineGetter__") \
     macro(defineSetter, defineSetter, "__defineSetter__") \
     macro(delete, delete_, "delete") \
     macro(deleteProperty, deleteProperty, "deleteProperty") \
     macro(each, each, "each") \
@@ -89,17 +89,17 @@
     macro(message, message, "message") \
     macro(module, module, "module") \
     macro(multiline, multiline, "multiline") \
     macro(name, name, "name") \
     macro(NaN, NaN, "NaN") \
     macro(next, next, "next") \
     macro(noSuchMethod, noSuchMethod, "__noSuchMethod__") \
     macro(NumberFormat, NumberFormat, "NumberFormat") \
-    macro(NumberFormatFormat, NumberFormatFormat, "Intl_NumberFormat_format") \
+    macro(NumberFormatFormatGet, NumberFormatFormatGet, "Intl_NumberFormat_format_get") \
     macro(objectNull, objectNull, "[object Null]") \
     macro(objectUndefined, objectUndefined, "[object Undefined]") \
     macro(of, of, "of") \
     macro(offset, offset, "offset") \
     macro(parseFloat, parseFloat, "parseFloat") \
     macro(parseInt, parseInt, "parseInt") \
     macro(propertyIsEnumerable, propertyIsEnumerable, "propertyIsEnumerable") \
     macro(proto, proto, "__proto__") \