/ runtime / IntlCollatorPrototype.cpp
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