IntlCollatorPrototype.cpp
1 /* 2 * Copyright (C) 2015 Andy VanWagoner (andy@vanwagoner.family) 3 * Copyright (C) 2016-2019 Apple Inc. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 18 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 24 * THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include "config.h" 28 #include "IntlCollatorPrototype.h" 29 30 #include "IntlCollator.h" 31 #include "JSBoundFunction.h" 32 #include "JSCInlines.h" 33 34 namespace JSC { 35 36 static JSC_DECLARE_HOST_FUNCTION(IntlCollatorPrototypeGetterCompare); 37 static JSC_DECLARE_HOST_FUNCTION(IntlCollatorPrototypeFuncResolvedOptions); 38 static JSC_DECLARE_HOST_FUNCTION(IntlCollatorFuncCompare); 39 40 } 41 42 #include "IntlCollatorPrototype.lut.h" 43 44 namespace JSC { 45 46 const ClassInfo IntlCollatorPrototype::s_info = { "Intl.Collator", &Base::s_info, &collatorPrototypeTable, nullptr, CREATE_METHOD_TABLE(IntlCollatorPrototype) }; 47 48 /* Source for IntlCollatorPrototype.lut.h 49 @begin collatorPrototypeTable 50 compare IntlCollatorPrototypeGetterCompare DontEnum|Accessor 51 resolvedOptions IntlCollatorPrototypeFuncResolvedOptions DontEnum|Function 0 52 @end 53 */ 54 55 IntlCollatorPrototype* IntlCollatorPrototype::create(VM& vm, JSGlobalObject*, Structure* structure) 56 { 57 IntlCollatorPrototype* object = new (NotNull, allocateCell<IntlCollatorPrototype>(vm.heap)) IntlCollatorPrototype(vm, structure); 58 object->finishCreation(vm); 59 return object; 60 } 61 62 Structure* IntlCollatorPrototype::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) 63 { 64 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info()); 65 } 66 67 IntlCollatorPrototype::IntlCollatorPrototype(VM& vm, Structure* structure) 68 : Base(vm, structure) 69 { 70 } 71 72 void IntlCollatorPrototype::finishCreation(VM& vm) 73 { 74 Base::finishCreation(vm); 75 ASSERT(inherits(vm, info())); 76 JSC_TO_STRING_TAG_WITHOUT_TRANSITION(); 77 } 78 79 JSC_DEFINE_HOST_FUNCTION(IntlCollatorFuncCompare, (JSGlobalObject* globalObject, CallFrame* callFrame)) 80 { 81 VM& vm = globalObject->vm(); 82 auto scope = DECLARE_THROW_SCOPE(vm); 83 // 10.3.4 Collator Compare Functions (ECMA-402 2.0) 84 // 1. Let collator be the this value. 85 // 2. Assert: Type(collator) is Object and collator has an [[initializedCollator]] internal slot whose value is true. 86 IntlCollator* collator = jsCast<IntlCollator*>(callFrame->thisValue()); 87 88 // 3. If x is not provided, let x be undefined. 89 // 4. If y is not provided, let y be undefined. 90 // 5. Let X be ToString(x). 91 JSString* x = callFrame->argument(0).toString(globalObject); 92 // 6. ReturnIfAbrupt(X). 93 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 94 95 // 7. Let Y be ToString(y). 96 JSString* y = callFrame->argument(1).toString(globalObject); 97 // 8. ReturnIfAbrupt(Y). 98 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 99 100 // 9. Return CompareStrings(collator, X, Y). 101 auto xViewWithString = x->viewWithUnderlyingString(globalObject); 102 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 103 auto yViewWithString = y->viewWithUnderlyingString(globalObject); 104 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 105 RELEASE_AND_RETURN(scope, JSValue::encode(collator->compareStrings(globalObject, xViewWithString.view, yViewWithString.view))); 106 } 107 108 JSC_DEFINE_HOST_FUNCTION(IntlCollatorPrototypeGetterCompare, (JSGlobalObject* globalObject, CallFrame* callFrame)) 109 { 110 VM& vm = globalObject->vm(); 111 auto scope = DECLARE_THROW_SCOPE(vm); 112 113 // 10.3.3 Intl.Collator.prototype.compare (ECMA-402 2.0) 114 // 1. Let collator be this Collator object. 115 IntlCollator* collator = jsDynamicCast<IntlCollator*>(vm, callFrame->thisValue()); 116 if (!collator) 117 return JSValue::encode(throwTypeError(globalObject, scope, "Intl.Collator.prototype.compare called on value that's not an object initialized as a Collator"_s)); 118 119 JSBoundFunction* boundCompare = collator->boundCompare(); 120 // 2. If collator.[[boundCompare]] is undefined, 121 if (!boundCompare) { 122 JSGlobalObject* globalObject = collator->globalObject(vm); 123 // a. Let F be a new built-in function object as defined in 11.3.4. 124 // b. The value of F’s length property is 2. 125 JSFunction* targetObject = JSFunction::create(vm, globalObject, 2, "compare"_s, IntlCollatorFuncCompare, NoIntrinsic); 126 127 // c. Let bc be BoundFunctionCreate(F, «this value»). 128 boundCompare = JSBoundFunction::create(vm, globalObject, targetObject, collator, nullptr, 2, nullptr); 129 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 130 // d. Set collator.[[boundCompare]] to bc. 131 collator->setBoundCompare(vm, boundCompare); 132 } 133 // 3. Return collator.[[boundCompare]]. 134 return JSValue::encode(boundCompare); 135 } 136 137 JSC_DEFINE_HOST_FUNCTION(IntlCollatorPrototypeFuncResolvedOptions, (JSGlobalObject* globalObject, CallFrame* callFrame)) 138 { 139 VM& vm = globalObject->vm(); 140 auto scope = DECLARE_THROW_SCOPE(vm); 141 142 // 10.3.5 Intl.Collator.prototype.resolvedOptions() (ECMA-402 2.0) 143 IntlCollator* collator = jsDynamicCast<IntlCollator*>(vm, callFrame->thisValue()); 144 if (!collator) 145 return JSValue::encode(throwTypeError(globalObject, scope, "Intl.Collator.prototype.resolvedOptions called on value that's not an object initialized as a Collator"_s)); 146 147 RELEASE_AND_RETURN(scope, JSValue::encode(collator->resolvedOptions(globalObject))); 148 } 149 150 } // namespace JSC