/ runtime / ErrorPrototype.cpp
ErrorPrototype.cpp
  1  /*
  2   *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
  3   *  Copyright (C) 2003-2020 Apple Inc. All rights reserved.
  4   *
  5   *  This library is free software; you can redistribute it and/or
  6   *  modify it under the terms of the GNU Lesser General Public
  7   *  License as published by the Free Software Foundation; either
  8   *  version 2 of the License, or (at your option) any later version.
  9   *
 10   *  This library is distributed in the hope that it will be useful,
 11   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 12   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13   *  Lesser General Public License for more details.
 14   *
 15   *  You should have received a copy of the GNU Lesser General Public
 16   *  License along with this library; if not, write to the Free Software
 17   *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 18   *
 19   */
 20  
 21  #include "config.h"
 22  #include "ErrorPrototype.h"
 23  
 24  #include "IntegrityInlines.h"
 25  #include "JSCInlines.h"
 26  #include "StringRecursionChecker.h"
 27  
 28  namespace JSC {
 29  
 30  STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(ErrorPrototypeBase);
 31  STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(ErrorPrototype);
 32  
 33  static JSC_DECLARE_HOST_FUNCTION(errorProtoFuncToString);
 34  
 35  }
 36  
 37  #include "ErrorPrototype.lut.h"
 38  
 39  namespace JSC {
 40  
 41  const ClassInfo ErrorPrototype::s_info = { "Object", &Base::s_info, &errorPrototypeTable, nullptr, CREATE_METHOD_TABLE(ErrorPrototype) };
 42  
 43  /* Source for ErrorPrototype.lut.h
 44  @begin errorPrototypeTable
 45    toString          errorProtoFuncToString         DontEnum|Function 0
 46  @end
 47  */
 48  
 49  ErrorPrototypeBase::ErrorPrototypeBase(VM& vm, Structure* structure)
 50      : Base(vm, structure)
 51  {
 52  }
 53  
 54  void ErrorPrototypeBase::finishCreation(VM& vm, const String& name)
 55  {
 56      Base::finishCreation(vm);
 57      ASSERT(inherits(vm, info()));
 58      putDirectWithoutTransition(vm, vm.propertyNames->name, jsString(vm, name), static_cast<unsigned>(PropertyAttribute::DontEnum));
 59      putDirectWithoutTransition(vm, vm.propertyNames->message, jsEmptyString(vm), static_cast<unsigned>(PropertyAttribute::DontEnum));
 60  }
 61  
 62  ErrorPrototype::ErrorPrototype(VM& vm, Structure* structure)
 63      : Base(vm, structure)
 64  {
 65  }
 66  
 67  // ------------------------------ Functions ---------------------------
 68  
 69  // ECMA-262 5.1, 15.11.4.4
 70  JSC_DEFINE_HOST_FUNCTION(errorProtoFuncToString, (JSGlobalObject* globalObject, CallFrame* callFrame))
 71  {
 72      VM& vm = globalObject->vm();
 73      auto scope = DECLARE_THROW_SCOPE(vm);
 74  
 75      // 1. Let O be the this value.
 76      JSValue thisValue = callFrame->thisValue().toThis(globalObject, ECMAMode::strict());
 77  
 78      // 2. If Type(O) is not Object, throw a TypeError exception.
 79      if (!thisValue.isObject())
 80          return throwVMTypeError(globalObject, scope);
 81      JSObject* thisObj = asObject(thisValue);
 82      Integrity::auditStructureID(vm, thisObj->structureID());
 83  
 84      // Guard against recursion!
 85      StringRecursionChecker checker(globalObject, thisObj);
 86      EXCEPTION_ASSERT(!scope.exception() || checker.earlyReturnValue());
 87      if (JSValue earlyReturnValue = checker.earlyReturnValue())
 88          return JSValue::encode(earlyReturnValue);
 89  
 90      // 3. Let name be the result of calling the [[Get]] internal method of O with argument "name".
 91      JSValue name = thisObj->get(globalObject, vm.propertyNames->name);
 92      RETURN_IF_EXCEPTION(scope, encodedJSValue());
 93  
 94      // 4. If name is undefined, then let name be "Error"; else let name be ToString(name).
 95      String nameString;
 96      if (name.isUndefined())
 97          nameString = "Error"_s;
 98      else {
 99          nameString = name.toWTFString(globalObject);
100          RETURN_IF_EXCEPTION(scope, encodedJSValue());
101      }
102  
103      // 5. Let msg be the result of calling the [[Get]] internal method of O with argument "message".
104      JSValue message = thisObj->get(globalObject, vm.propertyNames->message);
105      RETURN_IF_EXCEPTION(scope, encodedJSValue());
106  
107      // (sic)
108      // 6. If msg is undefined, then let msg be the empty String; else let msg be ToString(msg).
109      // 7. If msg is undefined, then let msg be the empty String; else let msg be ToString(msg).
110      String messageString;
111      if (message.isUndefined())
112          messageString = String();
113      else {
114          messageString = message.toWTFString(globalObject);
115          RETURN_IF_EXCEPTION(scope, encodedJSValue());
116      }
117  
118      // 8. If name is the empty String, return msg.
119      if (!nameString.length())
120          return JSValue::encode(message.isString() ? message : jsString(vm, messageString));
121  
122      // 9. If msg is the empty String, return name.
123      if (!messageString.length())
124          return JSValue::encode(name.isString() ? name : jsString(vm, nameString));
125  
126      // 10. Return the result of concatenating name, ":", a single space character, and msg.
127      RELEASE_AND_RETURN(scope, JSValue::encode(jsMakeNontrivialString(globalObject, nameString, ": ", messageString)));
128  }
129  
130  } // namespace JSC