[INTL] Implement Intl.DateTimeFormat.prototype.resolvedOptions ()
[WebKit.git] / Source / JavaScriptCore / runtime / IntlDateTimeFormatPrototype.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 #include "config.h"
27 #include "IntlDateTimeFormatPrototype.h"
28
29 #if ENABLE(INTL)
30
31 #include "DateConstructor.h"
32 #include "Error.h"
33 #include "IntlDateTimeFormat.h"
34 #include "IntlObject.h"
35 #include "JSBoundFunction.h"
36 #include "JSCJSValueInlines.h"
37 #include "JSCellInlines.h"
38 #include "JSObject.h"
39 #include "StructureInlines.h"
40
41 namespace JSC {
42
43 static EncodedJSValue JSC_HOST_CALL IntlDateTimeFormatPrototypeGetterFormat(ExecState*);
44 static EncodedJSValue JSC_HOST_CALL IntlDateTimeFormatPrototypeFuncResolvedOptions(ExecState*);
45
46 }
47
48 #include "IntlDateTimeFormatPrototype.lut.h"
49
50 namespace JSC {
51
52 const ClassInfo IntlDateTimeFormatPrototype::s_info = { "Object", &IntlDateTimeFormat::s_info, &dateTimeFormatPrototypeTable, CREATE_METHOD_TABLE(IntlDateTimeFormatPrototype) };
53
54 /* Source for IntlDateTimeFormatPrototype.lut.h
55 @begin dateTimeFormatPrototypeTable
56   format           IntlDateTimeFormatPrototypeGetterFormat         DontEnum|Accessor
57   resolvedOptions  IntlDateTimeFormatPrototypeFuncResolvedOptions  DontEnum|Function 0
58 @end
59 */
60
61 IntlDateTimeFormatPrototype* IntlDateTimeFormatPrototype::create(VM& vm, JSGlobalObject*, Structure* structure)
62 {
63     IntlDateTimeFormatPrototype* object = new (NotNull, allocateCell<IntlDateTimeFormatPrototype>(vm.heap)) IntlDateTimeFormatPrototype(vm, structure);
64     object->finishCreation(vm, structure);
65     return object;
66 }
67
68 Structure* IntlDateTimeFormatPrototype::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
69 {
70     return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
71 }
72
73 IntlDateTimeFormatPrototype::IntlDateTimeFormatPrototype(VM& vm, Structure* structure)
74     : IntlDateTimeFormat(vm, structure)
75 {
76 }
77
78 void IntlDateTimeFormatPrototype::finishCreation(VM& vm, Structure*)
79 {
80     Base::finishCreation(vm);
81 }
82
83 bool IntlDateTimeFormatPrototype::getOwnPropertySlot(JSObject* object, ExecState* state, PropertyName propertyName, PropertySlot& slot)
84 {
85     return getStaticFunctionSlot<JSObject>(state, dateTimeFormatPrototypeTable, jsCast<IntlDateTimeFormatPrototype*>(object), propertyName, slot);
86 }
87
88 static EncodedJSValue JSC_HOST_CALL IntlDateTimeFormatFuncFormatDateTime(ExecState* state)
89 {
90     // 12.3.4 DateTime Format Functions (ECMA-402 2.0)
91     // 1. Let dtf be the this value.
92     // 2. Assert: Type(dtf) is Object and dtf has an [[initializedDateTimeFormat]] internal slot whose value is true.
93     IntlDateTimeFormat* format = jsCast<IntlDateTimeFormat*>(state->thisValue());
94
95     JSValue date = state->argument(0);
96     double value;
97
98     // 3. If date is not provided or is undefined, then
99     if (date.isUndefined()) {
100         // a. Let x be %Date_now%().
101         value = JSValue::decode(dateNow(state)).toNumber(state);
102     } else {
103         // 4. Else
104         // a. Let x be ToNumber(date).
105         value = date.toNumber(state);
106         // b. ReturnIfAbrupt(x).
107         if (state->hadException())
108             return JSValue::encode(jsUndefined());
109     }
110
111     // 5. Return FormatDateTime(dtf, x).
112     return JSValue::encode(format->format(*state, value));
113 }
114
115 EncodedJSValue JSC_HOST_CALL IntlDateTimeFormatPrototypeGetterFormat(ExecState* state)
116 {
117     // 12.3.3 Intl.DateTimeFormat.prototype.format (ECMA-402 2.0)
118     // 1. Let dtf be this DateTimeFormat object.
119     IntlDateTimeFormat* dtf = jsDynamicCast<IntlDateTimeFormat*>(state->thisValue());
120     // 2. ReturnIfAbrupt(dtf).
121     if (!dtf)
122         return JSValue::encode(throwTypeError(state, ASCIILiteral("Intl.DateTimeFormat.prototype.format called on value that's not an object initialized as a DateTimeFormat")));
123
124     JSBoundFunction* boundFormat = dtf->boundFormat();
125     // 3. If the [[boundFormat]] internal slot of this DateTimeFormat object is undefined,
126     if (!boundFormat) {
127         VM& vm = state->vm();
128         JSGlobalObject* globalObject = dtf->globalObject();
129         // a. Let F be a new built-in function object as defined in 12.3.4.
130         // b. The value of F’s length property is 1. (Note: F’s length property was 0 in ECMA-402 1.0)
131         JSFunction* targetObject = JSFunction::create(vm, globalObject, 1, ASCIILiteral("format"), IntlDateTimeFormatFuncFormatDateTime, NoIntrinsic);
132         JSArray* boundArgs = JSArray::tryCreateUninitialized(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithUndecided), 0);
133         if (!boundArgs)
134             return JSValue::encode(throwOutOfMemoryError(state));
135
136         // c. Let bf be BoundFunctionCreate(F, «this value»).
137         boundFormat = JSBoundFunction::create(vm, globalObject, targetObject, dtf, boundArgs, 1, ASCIILiteral("format"));
138         // d. Set dtf.[[boundFormat]] to bf.
139         dtf->setBoundFormat(vm, boundFormat);
140     }
141     // 4. Return dtf.[[boundFormat]].
142     return JSValue::encode(boundFormat);
143 }
144
145 EncodedJSValue JSC_HOST_CALL IntlDateTimeFormatPrototypeFuncResolvedOptions(ExecState* state)
146 {
147     // 12.3.5 Intl.DateTimeFormat.prototype.resolvedOptions() (ECMA-402 2.0)
148     IntlDateTimeFormat* dateTimeFormat = jsDynamicCast<IntlDateTimeFormat*>(state->thisValue());
149     if (!dateTimeFormat)
150         return JSValue::encode(throwTypeError(state, ASCIILiteral("Intl.DateTimeFormat.prototype.resolvedOptions called on value that's not an object initialized as a DateTimeFormat")));
151
152     return JSValue::encode(dateTimeFormat->resolvedOptions(*state));
153 }
154
155 } // namespace JSC
156
157 #endif // ENABLE(INTL)