[INTL] Implement supportedLocalesOf on Intl Constructors
[WebKit.git] / Source / JavaScriptCore / runtime / IntlNumberFormatConstructor.cpp
1 /*
2  * Copyright (C) 2015 Andy VanWagoner (thetalecrafter@gmail.com)
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26
27 #include "config.h"
28 #include "IntlNumberFormatConstructor.h"
29
30 #if ENABLE(INTL)
31
32 #include "Error.h"
33 #include "IntlNumberFormat.h"
34 #include "IntlNumberFormatPrototype.h"
35 #include "IntlObject.h"
36 #include "JSCJSValueInlines.h"
37 #include "JSCellInlines.h"
38 #include "Lookup.h"
39 #include "SlotVisitorInlines.h"
40 #include "StructureInlines.h"
41
42 namespace JSC {
43
44 STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(IntlNumberFormatConstructor);
45
46 static EncodedJSValue JSC_HOST_CALL IntlNumberFormatConstructorFuncSupportedLocalesOf(ExecState*);
47
48 }
49
50 #include "IntlNumberFormatConstructor.lut.h"
51
52 namespace JSC {
53
54 const ClassInfo IntlNumberFormatConstructor::s_info = { "Function", &Base::s_info, &numberFormatConstructorTable, CREATE_METHOD_TABLE(IntlNumberFormatConstructor) };
55
56 /* Source for IntlNumberFormatConstructor.lut.h
57 @begin numberFormatConstructorTable
58   supportedLocalesOf             IntlNumberFormatConstructorFuncSupportedLocalesOf             DontEnum|Function 1
59 @end
60 */
61
62 IntlNumberFormatConstructor* IntlNumberFormatConstructor::create(VM& vm, Structure* structure, IntlNumberFormatPrototype* numberFormatPrototype, Structure* numberFormatStructure)
63 {
64     IntlNumberFormatConstructor* constructor = new (NotNull, allocateCell<IntlNumberFormatConstructor>(vm.heap)) IntlNumberFormatConstructor(vm, structure);
65     constructor->finishCreation(vm, numberFormatPrototype, numberFormatStructure);
66     return constructor;
67 }
68
69 Structure* IntlNumberFormatConstructor::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
70 {
71     return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
72 }
73
74 IntlNumberFormatConstructor::IntlNumberFormatConstructor(VM& vm, Structure* structure)
75     : InternalFunction(vm, structure)
76 {
77 }
78
79 void IntlNumberFormatConstructor::finishCreation(VM& vm, IntlNumberFormatPrototype* numberFormatPrototype, Structure* numberFormatStructure)
80 {
81     Base::finishCreation(vm, ASCIILiteral("NumberFormat"));
82     putDirectWithoutTransition(vm, vm.propertyNames->prototype, numberFormatPrototype, DontEnum | DontDelete | ReadOnly);
83     putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(0), ReadOnly | DontEnum | DontDelete);
84     m_numberFormatStructure.set(vm, this, numberFormatStructure);
85 }
86
87 EncodedJSValue JSC_HOST_CALL constructIntlNumberFormat(ExecState* exec)
88 {
89     // 11.1.2 Intl.NumberFormat ([locales [, options]]) (ECMA-402 2.0)
90     // 1. If NewTarget is undefined, let newTarget be the active function object, else let newTarget be NewTarget.
91     JSValue newTarget = exec->newTarget();
92     if (!newTarget || newTarget.isUndefined())
93         newTarget = exec->callee();
94
95     // 2. Let numberFormat be OrdinaryCreateFromConstructor(newTarget, %NumberFormatPrototype%).
96     VM& vm = exec->vm();
97     IntlNumberFormat* numberFormat = IntlNumberFormat::create(vm, jsCast<IntlNumberFormatConstructor*>(exec->callee()));
98     if (numberFormat && !jsDynamicCast<IntlNumberFormatConstructor*>(newTarget)) {
99         JSValue proto = asObject(newTarget)->getDirect(vm, vm.propertyNames->prototype);
100         asObject(numberFormat)->setPrototypeWithCycleCheck(exec, proto);
101     }
102
103     // 3. ReturnIfAbrupt(numberFormat).
104     ASSERT(numberFormat);
105
106     // 4. Return InitializeNumberFormat(numberFormat, locales, options).
107     // FIXME: return JSValue::encode(InitializeNumberFormat(numberFormat, locales, options));
108
109     return JSValue::encode(numberFormat);
110 }
111
112 EncodedJSValue JSC_HOST_CALL callIntlNumberFormat(ExecState* exec)
113 {
114     // 11.1.2 Intl.NumberFormat ([locales [, options]]) (ECMA-402 2.0)
115     // 1. If NewTarget is undefined, let newTarget be the active function object, else let newTarget be NewTarget.
116     // NewTarget is always undefined when called as a function.
117
118     // 2. Let numberFormat be OrdinaryCreateFromConstructor(newTarget, %NumberFormatPrototype%).
119     VM& vm = exec->vm();
120     IntlNumberFormat* numberFormat = IntlNumberFormat::create(vm, jsCast<IntlNumberFormatConstructor*>(exec->callee()));
121
122     // 3. ReturnIfAbrupt(numberFormat).
123     ASSERT(numberFormat);
124
125     // 4. Return InitializeNumberFormat(numberFormat, locales, options).
126     // FIXME: return JSValue::encode(InitializeNumberFormat(numberFormat, locales, options));
127
128     return JSValue::encode(numberFormat);
129 }
130
131 ConstructType IntlNumberFormatConstructor::getConstructData(JSCell*, ConstructData& constructData)
132 {
133     constructData.native.function = constructIntlNumberFormat;
134     return ConstructTypeHost;
135 }
136
137 CallType IntlNumberFormatConstructor::getCallData(JSCell*, CallData& callData)
138 {
139     callData.native.function = callIntlNumberFormat;
140     return CallTypeHost;
141 }
142
143 bool IntlNumberFormatConstructor::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
144 {
145     return getStaticFunctionSlot<InternalFunction>(exec, numberFormatConstructorTable, jsCast<IntlNumberFormatConstructor*>(object), propertyName, slot);
146 }
147
148 EncodedJSValue JSC_HOST_CALL IntlNumberFormatConstructorFuncSupportedLocalesOf(ExecState* exec)
149 {
150     // 11.2.2 Intl.NumberFormat.supportedLocalesOf(locales [, options]) (ECMA-402 2.0)
151
152     // 1. Let availableLocales be %NumberFormat%.[[availableLocales]].
153     JSGlobalObject* globalObject = exec->callee()->globalObject();
154     const HashSet<String> availableLocales = globalObject->intlNumberFormatAvailableLocales();
155
156     // 2. Let requestedLocales be CanonicalizeLocaleList(locales).
157     JSArray* requestedLocales = canonicalizeLocaleList(exec, exec->argument(0));
158     if (exec->hadException())
159         return JSValue::encode(jsUndefined());
160
161     // 3. Return SupportedLocales(availableLocales, requestedLocales, options).
162     return JSValue::encode(supportedLocales(exec, availableLocales, requestedLocales, exec->argument(1)));
163 }
164
165 void IntlNumberFormatConstructor::visitChildren(JSCell* cell, SlotVisitor& visitor)
166 {
167     IntlNumberFormatConstructor* thisObject = jsCast<IntlNumberFormatConstructor*>(cell);
168     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
169
170     Base::visitChildren(thisObject, visitor);
171
172     visitor.append(&thisObject->m_numberFormatStructure);
173 }
174
175 } // namespace JSC
176
177 #endif // ENABLE(INTL)