Use the reject() helper function for conditionally throwing TypeErrors.
authormark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 17 Oct 2016 16:59:06 +0000 (16:59 +0000)
committermark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 17 Oct 2016 16:59:06 +0000 (16:59 +0000)
https://bugs.webkit.org/show_bug.cgi?id=163491

Reviewed by Filip Pizlo.

Source/JavaScriptCore:

In some places where we may conditionally throw a TypeError (e.g. when in strict
mode), we already use the reject() helper function to conditionally throw the
TypeError.  Doing so makes the code mode compact.  This patch applies this idiom
consistently in all places that throws TypeError where appropriate.

This patch also does the following:
1. Make the reject() helper function take an ASCIILiteral instead of a const char*
   because we always pass it a literal string anyway.
2. Change the reject helper() to take a ThrowScope&.  This allows the thrown
   error to be attributed to its caller.
3. When an error message string is instantiated repeatedly in more than 1 place,
   create a common copy of that literal string in JSObject.cpp (if one doesn't
   already exist) and use that common string in all those places.
4. Since I was auditing call sites of throwTypeError() to check if they should be
   using the reject() helper instead, I also fixed those up to pass the error
   message as an ASCIILiteral where appropriate.
5. In functions that I touched, change the code to not recompute the VM& when it
   is already available.

* jit/JITOperations.cpp:
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* runtime/ArrayPrototype.cpp:
(JSC::shift):
(JSC::unshift):
(JSC::arrayProtoFuncPop):
(JSC::arrayProtoFuncReverse):
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
* runtime/GetterSetter.cpp:
(JSC::callSetter):
* runtime/JSArray.cpp:
(JSC::JSArray::defineOwnProperty):
(JSC::JSArray::setLengthWithArrayStorage):
(JSC::JSArray::pop):
* runtime/JSArrayBuffer.cpp:
(JSC::JSArrayBuffer::put):
(JSC::JSArrayBuffer::defineOwnProperty):
* runtime/JSCJSValue.cpp:
(JSC::JSValue::putToPrimitive):
(JSC::JSValue::putToPrimitiveByIndex):
* runtime/JSDataView.cpp:
(JSC::JSDataView::put):
(JSC::JSDataView::defineOwnProperty):
* runtime/JSFunction.cpp:
(JSC::JSFunction::put):
(JSC::JSFunction::defineOwnProperty):
* runtime/JSGenericTypedArrayView.h:
(JSC::JSGenericTypedArrayView::setIndex):
* runtime/JSGenericTypedArrayViewInlines.h:
(JSC::JSGenericTypedArrayView<Adaptor>::defineOwnProperty):
(JSC::JSGenericTypedArrayView<Adaptor>::deleteProperty):
* runtime/JSGenericTypedArrayViewPrototypeFunctions.h:
(JSC::speciesConstruct):
(JSC::genericTypedArrayViewPrivateFuncSubarrayCreate):
* runtime/JSModuleNamespaceObject.cpp:
(JSC::JSModuleNamespaceObject::defineOwnProperty):
* runtime/JSObject.cpp:
(JSC::ordinarySetSlow):
(JSC::JSObject::putInlineSlow):
(JSC::JSObject::setPrototypeWithCycleCheck):
(JSC::JSObject::defineOwnIndexedProperty):
(JSC::JSObject::putByIndexBeyondVectorLengthWithArrayStorage):
(JSC::JSObject::putDirectIndexBeyondVectorLengthWithArrayStorage):
(JSC::validateAndApplyPropertyDescriptor):
* runtime/JSObject.h:
* runtime/JSObjectInlines.h:
(JSC::JSObject::putInline):
* runtime/JSProxy.cpp:
(JSC::JSProxy::setPrototype):
* runtime/JSSymbolTableObject.h:
(JSC::symbolTablePut):
* runtime/Lookup.h:
(JSC::putEntry):
* runtime/RegExpObject.cpp:
(JSC::RegExpObject::defineOwnProperty):
* runtime/RegExpObject.h:
(JSC::RegExpObject::setLastIndex):
* runtime/Reject.h:
(JSC::reject):
* runtime/SparseArrayValueMap.cpp:
(JSC::SparseArrayValueMap::putEntry):
(JSC::SparseArrayValueMap::putDirect):
(JSC::SparseArrayEntry::put):
* runtime/StringObject.cpp:
(JSC::StringObject::put):
(JSC::StringObject::putByIndex):
* runtime/SymbolConstructor.cpp:
(JSC::symbolConstructorKeyFor):

Source/WebCore:

No new tests because this patch does not introduce new behavior.

* bindings/js/JSCryptoAlgorithmDictionary.cpp:
(WebCore::createRsaKeyGenParams):
* bindings/js/JSIDBDatabaseCustom.cpp:
(WebCore::JSIDBDatabase::createObjectStore):
* bridge/c/c_instance.cpp:
(JSC::Bindings::CInstance::invokeMethod):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207411 268f45cc-cd09-0410-ab3c-d52691b4dbfc

31 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/jit/JITOperations.cpp
Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
Source/JavaScriptCore/runtime/ArrayPrototype.cpp
Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
Source/JavaScriptCore/runtime/GetterSetter.cpp
Source/JavaScriptCore/runtime/JSArray.cpp
Source/JavaScriptCore/runtime/JSArrayBuffer.cpp
Source/JavaScriptCore/runtime/JSCJSValue.cpp
Source/JavaScriptCore/runtime/JSDataView.cpp
Source/JavaScriptCore/runtime/JSFunction.cpp
Source/JavaScriptCore/runtime/JSGenericTypedArrayView.h
Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h
Source/JavaScriptCore/runtime/JSGenericTypedArrayViewPrototypeFunctions.h
Source/JavaScriptCore/runtime/JSModuleNamespaceObject.cpp
Source/JavaScriptCore/runtime/JSObject.cpp
Source/JavaScriptCore/runtime/JSObject.h
Source/JavaScriptCore/runtime/JSObjectInlines.h
Source/JavaScriptCore/runtime/JSProxy.cpp
Source/JavaScriptCore/runtime/JSSymbolTableObject.h
Source/JavaScriptCore/runtime/Lookup.h
Source/JavaScriptCore/runtime/RegExpObject.cpp
Source/JavaScriptCore/runtime/RegExpObject.h
Source/JavaScriptCore/runtime/Reject.h
Source/JavaScriptCore/runtime/SparseArrayValueMap.cpp
Source/JavaScriptCore/runtime/StringObject.cpp
Source/JavaScriptCore/runtime/SymbolConstructor.cpp
Source/WebCore/ChangeLog
Source/WebCore/bindings/js/JSCryptoAlgorithmDictionary.cpp
Source/WebCore/bindings/js/JSIDBDatabaseCustom.cpp
Source/WebCore/bridge/c/c_instance.cpp

index 695620a..217d486 100644 (file)
@@ -1,3 +1,100 @@
+2016-10-17  Mark Lam  <mark.lam@apple.com>
+
+        Use the reject() helper function for conditionally throwing TypeErrors.
+        https://bugs.webkit.org/show_bug.cgi?id=163491
+
+        Reviewed by Filip Pizlo.
+
+        In some places where we may conditionally throw a TypeError (e.g. when in strict
+        mode), we already use the reject() helper function to conditionally throw the
+        TypeError.  Doing so makes the code mode compact.  This patch applies this idiom
+        consistently in all places that throws TypeError where appropriate.
+
+        This patch also does the following:
+        1. Make the reject() helper function take an ASCIILiteral instead of a const char*
+           because we always pass it a literal string anyway.
+        2. Change the reject helper() to take a ThrowScope&.  This allows the thrown
+           error to be attributed to its caller.
+        3. When an error message string is instantiated repeatedly in more than 1 place,
+           create a common copy of that literal string in JSObject.cpp (if one doesn't
+           already exist) and use that common string in all those places.
+        4. Since I was auditing call sites of throwTypeError() to check if they should be
+           using the reject() helper instead, I also fixed those up to pass the error
+           message as an ASCIILiteral where appropriate.
+        5. In functions that I touched, change the code to not recompute the VM& when it
+           is already available.
+
+        * jit/JITOperations.cpp:
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        * runtime/ArrayPrototype.cpp:
+        (JSC::shift):
+        (JSC::unshift):
+        (JSC::arrayProtoFuncPop):
+        (JSC::arrayProtoFuncReverse):
+        * runtime/CommonSlowPaths.cpp:
+        (JSC::SLOW_PATH_DECL):
+        * runtime/GetterSetter.cpp:
+        (JSC::callSetter):
+        * runtime/JSArray.cpp:
+        (JSC::JSArray::defineOwnProperty):
+        (JSC::JSArray::setLengthWithArrayStorage):
+        (JSC::JSArray::pop):
+        * runtime/JSArrayBuffer.cpp:
+        (JSC::JSArrayBuffer::put):
+        (JSC::JSArrayBuffer::defineOwnProperty):
+        * runtime/JSCJSValue.cpp:
+        (JSC::JSValue::putToPrimitive):
+        (JSC::JSValue::putToPrimitiveByIndex):
+        * runtime/JSDataView.cpp:
+        (JSC::JSDataView::put):
+        (JSC::JSDataView::defineOwnProperty):
+        * runtime/JSFunction.cpp:
+        (JSC::JSFunction::put):
+        (JSC::JSFunction::defineOwnProperty):
+        * runtime/JSGenericTypedArrayView.h:
+        (JSC::JSGenericTypedArrayView::setIndex):
+        * runtime/JSGenericTypedArrayViewInlines.h:
+        (JSC::JSGenericTypedArrayView<Adaptor>::defineOwnProperty):
+        (JSC::JSGenericTypedArrayView<Adaptor>::deleteProperty):
+        * runtime/JSGenericTypedArrayViewPrototypeFunctions.h:
+        (JSC::speciesConstruct):
+        (JSC::genericTypedArrayViewPrivateFuncSubarrayCreate):
+        * runtime/JSModuleNamespaceObject.cpp:
+        (JSC::JSModuleNamespaceObject::defineOwnProperty):
+        * runtime/JSObject.cpp:
+        (JSC::ordinarySetSlow):
+        (JSC::JSObject::putInlineSlow):
+        (JSC::JSObject::setPrototypeWithCycleCheck):
+        (JSC::JSObject::defineOwnIndexedProperty):
+        (JSC::JSObject::putByIndexBeyondVectorLengthWithArrayStorage):
+        (JSC::JSObject::putDirectIndexBeyondVectorLengthWithArrayStorage):
+        (JSC::validateAndApplyPropertyDescriptor):
+        * runtime/JSObject.h:
+        * runtime/JSObjectInlines.h:
+        (JSC::JSObject::putInline):
+        * runtime/JSProxy.cpp:
+        (JSC::JSProxy::setPrototype):
+        * runtime/JSSymbolTableObject.h:
+        (JSC::symbolTablePut):
+        * runtime/Lookup.h:
+        (JSC::putEntry):
+        * runtime/RegExpObject.cpp:
+        (JSC::RegExpObject::defineOwnProperty):
+        * runtime/RegExpObject.h:
+        (JSC::RegExpObject::setLastIndex):
+        * runtime/Reject.h:
+        (JSC::reject):
+        * runtime/SparseArrayValueMap.cpp:
+        (JSC::SparseArrayValueMap::putEntry):
+        (JSC::SparseArrayValueMap::putDirect):
+        (JSC::SparseArrayEntry::put):
+        * runtime/StringObject.cpp:
+        (JSC::StringObject::put):
+        (JSC::StringObject::putByIndex):
+        * runtime/SymbolConstructor.cpp:
+        (JSC::symbolConstructorKeyFor):
+
 2016-10-16  Filip Pizlo  <fpizlo@apple.com>
 
         Air::IRC needs to place all Tmps on some worklist, even if they have no interference edges
index 88cc4d8..8b5269f 100644 (file)
@@ -1866,7 +1866,7 @@ size_t JIT_OPERATION operationDeleteById(ExecState* exec, EncodedJSValue encoded
         return false;
     bool couldDelete = baseObj->methodTable(vm)->deleteProperty(baseObj, exec, Identifier::fromUid(&vm, uid));
     if (!couldDelete && exec->codeBlock()->isStrictMode())
-        throwTypeError(exec, scope, ASCIILiteral("Unable to delete property."));
+        throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError));
     return couldDelete;
 }
 
@@ -1897,7 +1897,7 @@ size_t JIT_OPERATION operationDeleteByVal(ExecState* exec, EncodedJSValue encode
         couldDelete = baseObj->methodTable(vm)->deleteProperty(baseObj, exec, property);
     }
     if (!couldDelete && exec->codeBlock()->isStrictMode())
-        throwTypeError(exec, scope, ASCIILiteral("Unable to delete property."));
+        throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError));
     return couldDelete;
 }
 
index 4cb8da2..00012ac 100644 (file)
@@ -784,7 +784,7 @@ LLINT_SLOW_PATH_DECL(slow_path_del_by_id)
     bool couldDelete = baseObject->methodTable()->deleteProperty(baseObject, exec, codeBlock->identifier(pc[3].u.operand));
     LLINT_CHECK_EXCEPTION();
     if (!couldDelete && codeBlock->isStrictMode())
-        LLINT_THROW(createTypeError(exec, "Unable to delete property."));
+        LLINT_THROW(createTypeError(exec, UnableToDeletePropertyError));
     LLINT_RETURN(jsBoolean(couldDelete));
 }
 
@@ -915,7 +915,7 @@ LLINT_SLOW_PATH_DECL(slow_path_del_by_val)
     }
     
     if (!couldDelete && exec->codeBlock()->isStrictMode())
-        LLINT_THROW(createTypeError(exec, "Unable to delete property."));
+        LLINT_THROW(createTypeError(exec, UnableToDeletePropertyError));
     
     LLINT_RETURN(jsBoolean(couldDelete));
 }
index b705967..cae4f8e 100644 (file)
@@ -299,13 +299,13 @@ void shift(ExecState* exec, JSObject* thisObj, unsigned header, unsigned current
             thisObj->putByIndexInline(exec, to, value, true);
             RETURN_IF_EXCEPTION(scope, void());
         } else if (!thisObj->methodTable(vm)->deletePropertyByIndex(thisObj, exec, to)) {
-            throwTypeError(exec, scope, ASCIILiteral("Unable to delete property."));
+            throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError));
             return;
         }
     }
     for (unsigned k = length; k > length - count; --k) {
         if (!thisObj->methodTable(vm)->deletePropertyByIndex(thisObj, exec, k - 1)) {
-            throwTypeError(exec, scope, ASCIILiteral("Unable to delete property."));
+            throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError));
             return;
         }
     }
@@ -342,7 +342,7 @@ void unshift(ExecState* exec, JSObject* thisObj, unsigned header, unsigned curre
             RETURN_IF_EXCEPTION(scope, void());
             thisObj->putByIndexInline(exec, to, value, true);
         } else if (!thisObj->methodTable(vm)->deletePropertyByIndex(thisObj, exec, to)) {
-            throwTypeError(exec, scope, ASCIILiteral("Unable to delete property."));
+            throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError));
             return;
         }
         RETURN_IF_EXCEPTION(scope, void());
@@ -692,7 +692,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncPop(ExecState* exec)
         result = thisObj->get(exec, length - 1);
         RETURN_IF_EXCEPTION(scope, encodedJSValue());
         if (!thisObj->methodTable(vm)->deletePropertyByIndex(thisObj, exec, length - 1)) {
-            throwTypeError(exec, scope, ASCIILiteral("Unable to delete property."));
+            throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError));
             return JSValue::encode(jsUndefined());
         }
         putLength(exec, vm, thisObj, jsNumber(length - 1));
@@ -805,7 +805,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReverse(ExecState* exec)
             RETURN_IF_EXCEPTION(scope, encodedJSValue());
         } else if (!thisObject->methodTable(vm)->deletePropertyByIndex(thisObject, exec, lower)) {
             if (!scope.exception())
-                throwTypeError(exec, scope, ASCIILiteral("Unable to delete property."));
+                throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError));
             return JSValue::encode(JSValue());
         }
 
@@ -814,7 +814,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReverse(ExecState* exec)
             RETURN_IF_EXCEPTION(scope, encodedJSValue());
         } else if (!thisObject->methodTable(vm)->deletePropertyByIndex(thisObject, exec, upper)) {
             if (!scope.exception())
-                throwTypeError(exec, scope, ASCIILiteral("Unable to delete property."));
+                throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError));
             return JSValue::encode(JSValue());
         }
     }
index 2610588..947ae86 100644 (file)
@@ -631,16 +631,16 @@ SLOW_PATH_DECL(slow_path_del_by_val)
     
     uint32_t i;
     if (subscript.getUInt32(i))
-        couldDelete = baseObject->methodTable()->deletePropertyByIndex(baseObject, exec, i);
+        couldDelete = baseObject->methodTable(vm)->deletePropertyByIndex(baseObject, exec, i);
     else {
         CHECK_EXCEPTION();
         auto property = subscript.toPropertyKey(exec);
         CHECK_EXCEPTION();
-        couldDelete = baseObject->methodTable()->deleteProperty(baseObject, exec, property);
+        couldDelete = baseObject->methodTable(vm)->deleteProperty(baseObject, exec, property);
     }
     
     if (!couldDelete && exec->codeBlock()->isStrictMode())
-        THROW(createTypeError(exec, "Unable to delete property."));
+        THROW(createTypeError(exec, UnableToDeletePropertyError));
     
     RETURN(jsBoolean(couldDelete));
 }
index c065ca1..e5686fe 100644 (file)
@@ -93,11 +93,8 @@ bool callSetter(ExecState* exec, JSValue base, JSValue getterSetter, JSValue val
 
     GetterSetter* getterSetterObj = jsCast<GetterSetter*>(getterSetter);
 
-    if (getterSetterObj->isSetterNull()) {
-        if (ecmaMode == StrictMode)
-            throwTypeError(exec, scope, ReadonlyPropertyWriteError);
-        return false;
-    }
+    if (getterSetterObj->isSetterNull())
+        return reject(exec, scope, ecmaMode == StrictMode, ASCIILiteral(ReadonlyPropertyWriteError));
 
     JSObject* setter = getterSetterObj->setter();
 
index 8be274a..4f23348 100644 (file)
@@ -129,22 +129,22 @@ bool JSArray::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName
     JSArray* array = jsCast<JSArray*>(object);
 
     // 3. If P is "length", then
-    if (propertyName == exec->propertyNames().length) {
+    if (propertyName == vm.propertyNames->length) {
         // All paths through length definition call the default [[DefineOwnProperty]], hence:
         // from ES5.1 8.12.9 7.a.
         if (descriptor.configurablePresent() && descriptor.configurable())
-            return reject(exec, throwException, "Attempting to change configurable attribute of unconfigurable property.");
+            return reject(exec, scope, throwException, ASCIILiteral(UnconfigurablePropertyChangeConfigurabilityError));
         // from ES5.1 8.12.9 7.b.
         if (descriptor.enumerablePresent() && descriptor.enumerable())
-            return reject(exec, throwException, "Attempting to change enumerable attribute of unconfigurable property.");
+            return reject(exec, scope, throwException, ASCIILiteral(UnconfigurablePropertyChangeEnumerabilityError));
 
         // a. If the [[Value]] field of Desc is absent, then
         // a.i. Return the result of calling the default [[DefineOwnProperty]] internal method (8.12.9) on A passing "length", Desc, and Throw as arguments.
         if (descriptor.isAccessorDescriptor())
-            return reject(exec, throwException, UnconfigurablePropertyChangeAccessMechanismError);
+            return reject(exec, scope, throwException, ASCIILiteral(UnconfigurablePropertyChangeAccessMechanismError));
         // from ES5.1 8.12.9 10.a.
         if (!array->isLengthWritable() && descriptor.writablePresent() && descriptor.writable())
-            return reject(exec, throwException, "Attempting to change writable attribute of unconfigurable property.");
+            return reject(exec, scope, throwException, ASCIILiteral(UnconfigurablePropertyChangeWritabilityError));
         // This descriptor is either just making length read-only, or changing nothing!
         if (!descriptor.value()) {
             if (descriptor.writablePresent())
@@ -174,7 +174,7 @@ bool JSArray::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName
         // f.i. Return the result of calling the default [[DefineOwnProperty]] internal method (8.12.9) on A passing "length", newLenDesc, and Throw as arguments.
         // g. Reject if oldLenDesc.[[Writable]] is false.
         if (!array->isLengthWritable())
-            return reject(exec, throwException, "Attempting to change value of a readonly property.");
+            return reject(exec, scope, throwException, ASCIILiteral(ReadonlyPropertyChangeError));
         
         // h. If newLenDesc.[[Writable]] is absent or has the value true, let newWritable be true.
         // i. Else,
@@ -214,7 +214,7 @@ bool JSArray::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName
         uint32_t index = optionalIndex.value();
         // FIXME: Nothing prevents this from being called on a RuntimeArray, and the length function will always return 0 in that case.
         if (index >= array->length() && !array->isLengthWritable())
-            return reject(exec, throwException, "Attempting to define numeric property on array with non-writable length property.");
+            return reject(exec, scope, throwException, ASCIILiteral("Attempting to define numeric property on array with non-writable length property."));
         // c. Let succeeded be the result of calling the default [[DefineOwnProperty]] internal method (8.12.9) on A passing P, Desc, and false as arguments.
         // d. Reject if succeeded is false.
         // e. If index >= oldLen
@@ -398,6 +398,9 @@ bool JSArray::unshiftCountSlowCase(VM& vm, DeferGC&, bool addToFront, unsigned c
 
 bool JSArray::setLengthWithArrayStorage(ExecState* exec, unsigned newLength, bool throwException, ArrayStorage* storage)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     unsigned length = storage->length();
     
     // If the length is read only then we enter sparse mode, so should enter the following 'if'.
@@ -406,7 +409,7 @@ bool JSArray::setLengthWithArrayStorage(ExecState* exec, unsigned newLength, boo
     if (SparseArrayValueMap* map = storage->m_sparseMap.get()) {
         // Fail if the length is not writable.
         if (map->lengthIsReadOnly())
-            return reject(exec, throwException, ReadonlyPropertyWriteError);
+            return reject(exec, scope, throwException, ASCIILiteral(ReadonlyPropertyWriteError));
 
         if (newLength < length) {
             // Copy any keys we might be interested in into a vector.
@@ -431,7 +434,7 @@ bool JSArray::setLengthWithArrayStorage(ExecState* exec, unsigned newLength, boo
                     ASSERT(it != map->notFound());
                     if (it->value.attributes & DontDelete) {
                         storage->setLength(index + 1);
-                        return reject(exec, throwException, "Unable to delete property.");
+                        return reject(exec, scope, throwException, ASCIILiteral(UnableToDeletePropertyError));
                     }
                     map->remove(it);
                 }
@@ -625,7 +628,7 @@ JSValue JSArray::pop(ExecState* exec)
         unsigned length = storage->length();
         if (!length) {
             if (!isLengthWritable())
-                throwTypeError(exec, scope, ReadonlyPropertyWriteError);
+                throwTypeError(exec, scope, ASCIILiteral(ReadonlyPropertyWriteError));
             return jsUndefined();
         }
 
@@ -656,7 +659,7 @@ JSValue JSArray::pop(ExecState* exec)
     RETURN_IF_EXCEPTION(scope, JSValue());
     // Call the [[Delete]] internal method of O with arguments indx and true.
     if (!deletePropertyByIndex(this, exec, index)) {
-        throwTypeError(exec, scope, ASCIILiteral("Unable to delete property."));
+        throwTypeError(exec, scope, ASCIILiteral(UnableToDeletePropertyError));
         return jsUndefined();
     }
     // Call the [[Put]] internal method of O with arguments "length", indx, and true.
index 3cfabfc..f167908 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -90,13 +90,15 @@ bool JSArrayBuffer::put(
     JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value,
     PutPropertySlot& slot)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSArrayBuffer* thisObject = jsCast<JSArrayBuffer*>(cell);
 
     if (UNLIKELY(isThisValueAltered(slot, thisObject)))
         return ordinarySetSlow(exec, thisObject, propertyName, value, slot.thisValue(), slot.isStrictMode());
     
-    if (propertyName == exec->propertyNames().byteLength)
-        return reject(exec, slot.isStrictMode(), "Attempting to write to a read-only array buffer property.");
+    if (propertyName == vm.propertyNames->byteLength)
+        return reject(exec, scope, slot.isStrictMode(), ASCIILiteral("Attempting to write to a read-only array buffer property."));
     
     return Base::put(thisObject, exec, propertyName, value, slot);
 }
@@ -105,10 +107,12 @@ bool JSArrayBuffer::defineOwnProperty(
     JSObject* object, ExecState* exec, PropertyName propertyName,
     const PropertyDescriptor& descriptor, bool shouldThrow)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSArrayBuffer* thisObject = jsCast<JSArrayBuffer*>(object);
     
-    if (propertyName == exec->propertyNames().byteLength)
-        return reject(exec, shouldThrow, "Attempting to define read-only array buffer property.");
+    if (propertyName == vm.propertyNames->byteLength)
+        return reject(exec, scope, shouldThrow, ASCIILiteral("Attempting to define read-only array buffer property."));
     
     return Base::defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow);
 }
index 84c5eb8..46ee68a 100644 (file)
@@ -158,14 +158,11 @@ bool JSValue::putToPrimitive(ExecState* exec, PropertyName propertyName, JSValue
     if (UNLIKELY(!obj))
         return false;
     JSValue prototype;
-    if (propertyName != exec->propertyNames().underscoreProto) {
+    if (propertyName != vm.propertyNames->underscoreProto) {
         for (; !obj->structure()->hasReadOnlyOrGetterSetterPropertiesExcludingProto(); obj = asObject(prototype)) {
             prototype = obj->getPrototypeDirect();
-            if (prototype.isNull()) {
-                if (slot.isStrictMode())
-                    throwTypeError(exec, scope, ReadonlyPropertyWriteError);
-                return false;
-            }
+            if (prototype.isNull())
+                return reject(exec, scope, slot.isStrictMode(), ASCIILiteral(ReadonlyPropertyWriteError));
         }
     }
 
@@ -173,11 +170,8 @@ bool JSValue::putToPrimitive(ExecState* exec, PropertyName propertyName, JSValue
         unsigned attributes;
         PropertyOffset offset = obj->structure()->get(vm, propertyName, attributes);
         if (offset != invalidOffset) {
-            if (attributes & ReadOnly) {
-                if (slot.isStrictMode())
-                    throwTypeError(exec, scope, ReadonlyPropertyWriteError);
-                return false;
-            }
+            if (attributes & ReadOnly)
+                return reject(exec, scope, slot.isStrictMode(), ASCIILiteral(ReadonlyPropertyWriteError));
 
             JSValue gs = obj->getDirect(offset);
             if (gs.isGetterSetter())
@@ -197,9 +191,7 @@ bool JSValue::putToPrimitive(ExecState* exec, PropertyName propertyName, JSValue
             break;
     }
     
-    if (slot.isStrictMode())
-        throwTypeError(exec, scope, ReadonlyPropertyWriteError);
-    return false;
+    return reject(exec, scope, slot.isStrictMode(), ASCIILiteral(ReadonlyPropertyWriteError));
 }
 
 bool JSValue::putToPrimitiveByIndex(ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow)
@@ -221,9 +213,7 @@ bool JSValue::putToPrimitiveByIndex(ExecState* exec, unsigned propertyName, JSVa
     if (prototype->attemptToInterceptPutByIndexOnHoleForPrototype(exec, *this, propertyName, value, shouldThrow, putResult))
         return putResult;
     
-    if (shouldThrow)
-        throwTypeError(exec, scope, ReadonlyPropertyWriteError);
-    return false;
+    return reject(exec, scope, shouldThrow, ASCIILiteral(ReadonlyPropertyWriteError));
 }
 
 void JSValue::dump(PrintStream& out) const
index c6dbd92..883ef31 100644 (file)
@@ -117,14 +117,16 @@ bool JSDataView::put(
     JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value,
     PutPropertySlot& slot)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSDataView* thisObject = jsCast<JSDataView*>(cell);
 
     if (UNLIKELY(isThisValueAltered(slot, thisObject)))
         return ordinarySetSlow(exec, thisObject, propertyName, value, slot.thisValue(), slot.isStrictMode());
 
-    if (propertyName == exec->propertyNames().byteLength
-        || propertyName == exec->propertyNames().byteOffset)
-        return reject(exec, slot.isStrictMode(), "Attempting to write to read-only typed array property.");
+    if (propertyName == vm.propertyNames->byteLength
+        || propertyName == vm.propertyNames->byteOffset)
+        return reject(exec, scope, slot.isStrictMode(), ASCIILiteral("Attempting to write to read-only typed array property."));
 
     return Base::put(thisObject, exec, propertyName, value, slot);
 }
@@ -133,10 +135,12 @@ bool JSDataView::defineOwnProperty(
     JSObject* object, ExecState* exec, PropertyName propertyName,
     const PropertyDescriptor& descriptor, bool shouldThrow)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSDataView* thisObject = jsCast<JSDataView*>(object);
-    if (propertyName == exec->propertyNames().byteLength
-        || propertyName == exec->propertyNames().byteOffset)
-        return reject(exec, shouldThrow, "Attempting to define read-only typed array property.");
+    if (propertyName == vm.propertyNames->byteLength
+        || propertyName == vm.propertyNames->byteOffset)
+        return reject(exec, scope, shouldThrow, ASCIILiteral("Attempting to define read-only typed array property."));
 
     return Base::defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow);
 }
index 0c00f63..9a33027 100644 (file)
@@ -446,18 +446,15 @@ bool JSFunction::put(JSCell* cell, ExecState* exec, PropertyName propertyName, J
         return Base::put(thisObject, exec, propertyName, value, dontCache);
     }
 
-    if ((thisObject->jsExecutable()->isStrictMode() || thisObject->jsExecutable()->isES6Function()) && (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().caller)) {
+    if ((thisObject->jsExecutable()->isStrictMode() || thisObject->jsExecutable()->isES6Function()) && (propertyName == vm.propertyNames->arguments || propertyName == vm.propertyNames->caller)) {
         // This will trigger the property to be reified, if this is not already the case!
         bool okay = thisObject->hasProperty(exec, propertyName);
         ASSERT_UNUSED(okay, okay);
         scope.release();
         return Base::put(thisObject, exec, propertyName, value, slot);
     }
-    if (propertyName == vm.propertyNames->arguments || propertyName == vm.propertyNames->caller) {
-        if (slot.isStrictMode())
-            throwTypeError(exec, scope, ReadonlyPropertyWriteError);
-        return false;
-    }
+    if (propertyName == vm.propertyNames->arguments || propertyName == vm.propertyNames->caller)
+        return reject(exec, scope, slot.isStrictMode(), ASCIILiteral(ReadonlyPropertyWriteError));
     thisObject->reifyLazyPropertyIfNeeded(vm, exec, propertyName);
     scope.release();
     return Base::put(thisObject, exec, propertyName, value, slot);
@@ -510,7 +507,7 @@ bool JSFunction::defineOwnProperty(JSObject* object, ExecState* exec, PropertyNa
     }
 
     bool valueCheck;
-    if (propertyName == exec->propertyNames().arguments) {
+    if (propertyName == vm.propertyNames->arguments) {
         if (thisObject->jsExecutable()->isClass()) {
             thisObject->reifyLazyPropertyIfNeeded(vm, exec, propertyName);
             return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
@@ -522,7 +519,7 @@ bool JSFunction::defineOwnProperty(JSObject* object, ExecState* exec, PropertyNa
             return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
         }
         valueCheck = !descriptor.value() || sameValue(exec, descriptor.value(), retrieveArguments(exec, thisObject));
-    } else if (propertyName == exec->propertyNames().caller) {
+    } else if (propertyName == vm.propertyNames->caller) {
         if (thisObject->jsExecutable()->isClass()) {
             thisObject->reifyLazyPropertyIfNeeded(vm, exec, propertyName);
             return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
@@ -539,31 +536,16 @@ bool JSFunction::defineOwnProperty(JSObject* object, ExecState* exec, PropertyNa
         return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
     }
      
-    if (descriptor.configurablePresent() && descriptor.configurable()) {
-        if (throwException)
-            throwTypeError(exec, scope, ASCIILiteral("Attempting to change configurable attribute of unconfigurable property."));
-        return false;
-    }
-    if (descriptor.enumerablePresent() && descriptor.enumerable()) {
-        if (throwException)
-            throwTypeError(exec, scope, ASCIILiteral("Attempting to change enumerable attribute of unconfigurable property."));
-        return false;
-    }
-    if (descriptor.isAccessorDescriptor()) {
-        if (throwException)
-            throwTypeError(exec, scope, ASCIILiteral(UnconfigurablePropertyChangeAccessMechanismError));
-        return false;
-    }
-    if (descriptor.writablePresent() && descriptor.writable()) {
-        if (throwException)
-            throwTypeError(exec, scope, ASCIILiteral("Attempting to change writable attribute of unconfigurable property."));
-        return false;
-    }
-    if (!valueCheck) {
-        if (throwException)
-            throwTypeError(exec, scope, ASCIILiteral("Attempting to change value of a readonly property."));
-        return false;
-    }
+    if (descriptor.configurablePresent() && descriptor.configurable())
+        return reject(exec, scope, throwException, ASCIILiteral(UnconfigurablePropertyChangeConfigurabilityError));
+    if (descriptor.enumerablePresent() && descriptor.enumerable())
+        return reject(exec, scope, throwException, ASCIILiteral(UnconfigurablePropertyChangeEnumerabilityError));
+    if (descriptor.isAccessorDescriptor())
+        return reject(exec, scope, throwException, ASCIILiteral(UnconfigurablePropertyChangeAccessMechanismError));
+    if (descriptor.writablePresent() && descriptor.writable())
+        return reject(exec, scope, throwException, ASCIILiteral(UnconfigurablePropertyChangeWritabilityError));
+    if (!valueCheck)
+        return reject(exec, scope, throwException, ASCIILiteral(ReadonlyPropertyChangeError));
     return true;
 }
 
index 5dbb847..198d10c 100644 (file)
@@ -88,7 +88,7 @@ enum class CopyType {
     Unobservable,
 };
 
-static const char* typedArrayBufferHasBeenDetachedErrorMessage = "Underlying ArrayBuffer has been detached from the view";
+static const char* const typedArrayBufferHasBeenDetachedErrorMessage = "Underlying ArrayBuffer has been detached from the view";
 
 template<typename Adaptor>
 class JSGenericTypedArrayView : public JSArrayBufferView {
@@ -176,7 +176,7 @@ public:
         RETURN_IF_EXCEPTION(scope, false);
 
         if (isNeutered()) {
-            throwTypeError(exec, scope, typedArrayBufferHasBeenDetachedErrorMessage);
+            throwTypeError(exec, scope, ASCIILiteral(typedArrayBufferHasBeenDetachedErrorMessage));
             return false;
         }
 
index 9c6cbb1..d595825 100644 (file)
@@ -360,17 +360,19 @@ bool JSGenericTypedArrayView<Adaptor>::defineOwnProperty(
     JSObject* object, ExecState* exec, PropertyName propertyName,
     const PropertyDescriptor& descriptor, bool shouldThrow)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(object);
 
     if (parseIndex(propertyName)) {
         if (descriptor.isAccessorDescriptor())
-            return reject(exec, shouldThrow, "Attempting to store accessor indexed property on a typed array.");
+            return reject(exec, scope, shouldThrow, ASCIILiteral("Attempting to store accessor indexed property on a typed array."));
 
         if (descriptor.configurable())
-            return reject(exec, shouldThrow, "Attempting to configure non-configurable property.");
+            return reject(exec, scope, shouldThrow, ASCIILiteral("Attempting to configure non-configurable property."));
 
         if (!descriptor.enumerable() || !descriptor.writable())
-            return reject(exec, shouldThrow, "Attempting to store non-enumerable or non-writable indexed property on a typed array.");
+            return reject(exec, scope, shouldThrow, ASCIILiteral("Attempting to store non-enumerable or non-writable indexed property on a typed array."));
 
         if (descriptor.value()) {
             PutPropertySlot unused(JSValue(thisObject), shouldThrow);
@@ -386,10 +388,12 @@ template<typename Adaptor>
 bool JSGenericTypedArrayView<Adaptor>::deleteProperty(
     JSCell* cell, ExecState* exec, PropertyName propertyName)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(cell);
 
     if (thisObject->isNeutered())
-        return reject(exec, true, typedArrayBufferHasBeenDetachedErrorMessage);
+        return reject(exec, scope, true, ASCIILiteral(typedArrayBufferHasBeenDetachedErrorMessage));
 
     if (parseIndex(propertyName))
         return false;
index 8165c81..1d5b412 100644 (file)
@@ -49,7 +49,7 @@ inline JSArrayBufferView* speciesConstruct(ExecState* exec, JSObject* exemplar,
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
 
-    JSValue constructor = exemplar->get(exec, exec->propertyNames().constructor);
+    JSValue constructor = exemplar->get(exec, vm.propertyNames->constructor);
     RETURN_IF_EXCEPTION(scope, nullptr);
 
     if (constructor.isUndefined())
@@ -59,7 +59,7 @@ inline JSArrayBufferView* speciesConstruct(ExecState* exec, JSObject* exemplar,
         return nullptr;
     }
 
-    JSValue species = constructor.get(exec, exec->propertyNames().speciesSymbol);
+    JSValue species = constructor.get(exec, vm.propertyNames->speciesSymbol);
     RETURN_IF_EXCEPTION(scope, nullptr);
 
     if (species.isUndefinedOrNull())
@@ -72,7 +72,7 @@ inline JSArrayBufferView* speciesConstruct(ExecState* exec, JSObject* exemplar,
         if (!view->isNeutered())
             return view;
 
-        throwTypeError(exec, scope, typedArrayBufferHasBeenDetachedErrorMessage);
+        throwTypeError(exec, scope, ASCIILiteral(typedArrayBufferHasBeenDetachedErrorMessage));
         return nullptr;
     }
 
@@ -552,7 +552,7 @@ EncodedJSValue JSC_HOST_CALL genericTypedArrayViewPrivateFuncSubarrayCreate(VM&v
     if (jsDynamicCast<JSArrayBufferView*>(result))
         return JSValue::encode(result);
 
-    throwTypeError(exec, scope, "species constructor did not return a TypedArray View");
+    throwTypeError(exec, scope, ASCIILiteral("species constructor did not return a TypedArray View"));
     return JSValue::encode(JSValue());
 }
 
index 1d487e3..9958dca 100644 (file)
@@ -204,7 +204,7 @@ bool JSModuleNamespaceObject::defineOwnProperty(JSObject*, ExecState* exec, Prop
 
     // http://www.ecma-international.org/ecma-262/6.0/#sec-module-namespace-exotic-objects-defineownproperty-p-desc
     if (shouldThrow)
-        throwTypeError(exec, scope, ASCIILiteral("Attempting to define property on object that is not extensible."));
+        throwTypeError(exec, scope, ASCIILiteral(NonExtensibleObjectPropertyDefineError));
     return false;
 }
 
index 2882bc4..72a8a7f 100644 (file)
@@ -61,8 +61,14 @@ static unsigned lastArraySize = 0;
 STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSObject);
 STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSFinalObject);
 
-const char* ReadonlyPropertyWriteError = "Attempted to assign to readonly property.";
-const char* UnconfigurablePropertyChangeAccessMechanismError = "Attempting to change access mechanism for an unconfigurable property.";
+const char* const NonExtensibleObjectPropertyDefineError = "Attempting to define property on object that is not extensible.";
+const char* const ReadonlyPropertyWriteError = "Attempted to assign to readonly property.";
+const char* const ReadonlyPropertyChangeError = "Attempting to change value of a readonly property.";
+const char* const UnableToDeletePropertyError = "Unable to delete property.";
+const char* const UnconfigurablePropertyChangeAccessMechanismError = "Attempting to change access mechanism for an unconfigurable property.";
+const char* const UnconfigurablePropertyChangeConfigurabilityError = "Attempting to change configurable attribute of unconfigurable property.";
+const char* const UnconfigurablePropertyChangeEnumerabilityError = "Attempting to change enumerable attribute of unconfigurable property.";
+const char* const UnconfigurablePropertyChangeWritabilityError = "Attempting to change writable attribute of unconfigurable property.";
 
 const ClassInfo JSObject::s_info = { "Object", 0, 0, CREATE_METHOD_TABLE(JSObject) };
 
@@ -389,11 +395,11 @@ bool ordinarySetSlow(ExecState* exec, JSObject* object, PropertyName propertyNam
     if (ownDescriptor.isDataDescriptor()) {
         // 9.1.9.1-4-a If ownDesc.[[Writable]] is false, return false.
         if (!ownDescriptor.writable())
-            return reject(exec, shouldThrow, ReadonlyPropertyWriteError);
+            return reject(exec, scope, shouldThrow, ASCIILiteral(ReadonlyPropertyWriteError));
 
         // 9.1.9.1-4-b If Type(Receiver) is not Object, return false.
         if (!receiver.isObject())
-            return reject(exec, shouldThrow, ReadonlyPropertyWriteError);
+            return reject(exec, scope, shouldThrow, ASCIILiteral(ReadonlyPropertyWriteError));
 
         // In OrdinarySet, the receiver may not be the same to the object.
         // So, we perform [[GetOwnProperty]] onto the receiver while we already perform [[GetOwnProperty]] onto the object.
@@ -408,11 +414,11 @@ bool ordinarySetSlow(ExecState* exec, JSObject* object, PropertyName propertyNam
         if (existingDescriptorFound) {
             // 9.1.9.1-4-d-i If IsAccessorDescriptor(existingDescriptor) is true, return false.
             if (existingDescriptor.isAccessorDescriptor())
-                return reject(exec, shouldThrow, ReadonlyPropertyWriteError);
+                return reject(exec, scope, shouldThrow, ASCIILiteral(ReadonlyPropertyWriteError));
 
             // 9.1.9.1-4-d-ii If existingDescriptor.[[Writable]] is false, return false.
             if (!existingDescriptor.writable())
-                return reject(exec, shouldThrow, ReadonlyPropertyWriteError);
+                return reject(exec, scope, shouldThrow, ASCIILiteral(ReadonlyPropertyWriteError));
 
             // 9.1.9.1-4-d-iii Let valueDesc be the PropertyDescriptor{[[Value]]: V}.
             PropertyDescriptor valueDescriptor;
@@ -434,7 +440,7 @@ bool ordinarySetSlow(ExecState* exec, JSObject* object, PropertyName propertyNam
     // 9.1.9.1-7 If setter is undefined, return false.
     JSValue setter = ownDescriptor.setter();
     if (!setter.isObject())
-        return reject(exec, shouldThrow, ReadonlyPropertyWriteError);
+        return reject(exec, scope, shouldThrow, ASCIILiteral(ReadonlyPropertyWriteError));
 
     // 9.1.9.1-8 Perform ? Call(setter, Receiver, << V >>).
     JSObject* setterObject = asObject(setter);
@@ -442,7 +448,7 @@ bool ordinarySetSlow(ExecState* exec, JSObject* object, PropertyName propertyNam
     args.append(value);
 
     CallData callData;
-    CallType callType = setterObject->methodTable(exec->vm())->getCallData(setterObject, callData);
+    CallType callType = setterObject->methodTable(vm)->getCallData(setterObject, callData);
     call(exec, setterObject, callType, callData, receiver, args);
 
     // 9.1.9.1-9 Return true.
@@ -460,6 +466,7 @@ bool JSObject::putInlineSlow(ExecState* exec, PropertyName propertyName, JSValue
     ASSERT(!isThisValueAltered(slot, this));
 
     VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
 
     JSObject* obj = this;
     for (;;) {
@@ -467,8 +474,8 @@ bool JSObject::putInlineSlow(ExecState* exec, PropertyName propertyName, JSValue
         PropertyOffset offset = obj->structure(vm)->get(vm, propertyName, attributes);
         if (isValidOffset(offset)) {
             if (attributes & ReadOnly) {
-                ASSERT(structure(vm)->prototypeChainMayInterceptStoreTo(exec->vm(), propertyName) || obj == this);
-                return reject(exec, slot.isStrictMode(), ReadonlyPropertyWriteError);
+                ASSERT(structure(vm)->prototypeChainMayInterceptStoreTo(vm, propertyName) || obj == this);
+                return reject(exec, scope, slot.isStrictMode(), ASCIILiteral(ReadonlyPropertyWriteError));
             }
 
             JSValue gs = obj->getDirect(offset);
@@ -511,9 +518,9 @@ bool JSObject::putInlineSlow(ExecState* exec, PropertyName propertyName, JSValue
         obj = asObject(prototype);
     }
 
-    ASSERT(!structure(vm)->prototypeChainMayInterceptStoreTo(exec->vm(), propertyName) || obj == this);
+    ASSERT(!structure(vm)->prototypeChainMayInterceptStoreTo(vm, propertyName) || obj == this);
     if (!putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot))
-        return reject(exec, slot.isStrictMode(), ReadonlyPropertyWriteError);
+        return reject(exec, scope, slot.isStrictMode(), ASCIILiteral(ReadonlyPropertyWriteError));
     return true;
 }
 
@@ -1295,19 +1302,13 @@ bool JSObject::setPrototypeWithCycleCheck(VM& vm, ExecState* exec, JSValue proto
     bool isExtensible = this->isExtensible(exec);
     RETURN_IF_EXCEPTION(scope, false);
 
-    if (!isExtensible) {
-        if (shouldThrowIfCantSet)
-            throwTypeError(exec, scope, ReadonlyPropertyWriteError);
-        return false;
-    }
+    if (!isExtensible)
+        return reject(exec, scope, shouldThrowIfCantSet, ASCIILiteral(ReadonlyPropertyWriteError));
 
     JSValue nextPrototype = prototype;
     while (nextPrototype && nextPrototype.isObject()) {
-        if (nextPrototype == this) {
-            if (shouldThrowIfCantSet)
-                throwTypeError(exec, scope, ASCIILiteral("cyclic __proto__ value"));
-            return false;
-        }
+        if (nextPrototype == this)
+            return reject(exec, scope, shouldThrowIfCantSet, ASCIILiteral("cyclic __proto__ value"));
         // FIXME: The specification currently says we should check if the [[GetPrototypeOf]] internal method of nextPrototype
         // is not the ordinary object internal method. However, we currently restrict this to Proxy objects as it would allow
         // for cycles with certain HTML objects (WindowProxy, Location) otherwise.
@@ -1987,6 +1988,9 @@ bool JSObject::putIndexedDescriptor(ExecState* exec, SparseArrayEntry* entryInMa
 // Defined in ES5.1 8.12.9
 bool JSObject::defineOwnIndexedProperty(ExecState* exec, unsigned index, const PropertyDescriptor& descriptor, bool throwException)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     ASSERT(index <= MAX_ARRAY_INDEX);
 
     if (!inSparseIndexingMode()) {
@@ -1999,11 +2003,11 @@ bool JSObject::defineOwnIndexedProperty(ExecState* exec, unsigned index, const P
             return putDirectIndex(exec, index, descriptor.value(), 0, throwException ? PutDirectIndexShouldThrow : PutDirectIndexShouldNotThrow);
         }
         
-        ensureArrayStorageExistsAndEnterDictionaryIndexingMode(exec->vm());
+        ensureArrayStorageExistsAndEnterDictionaryIndexingMode(vm);
     }
 
     if (descriptor.attributes() & (ReadOnly | Accessor))
-        notifyPresenceOfIndexedAccessors(exec->vm());
+        notifyPresenceOfIndexedAccessors(vm);
 
     SparseArrayValueMap* map = m_butterfly.get()->arrayStorage()->m_sparseMap.get();
     RELEASE_ASSERT(map);
@@ -2018,7 +2022,7 @@ bool JSObject::defineOwnIndexedProperty(ExecState* exec, unsigned index, const P
     if (result.isNewEntry) {
         if (!isStructureExtensible()) {
             map->remove(result.iterator);
-            return reject(exec, throwException, "Attempting to define property on object that is not extensible.");
+            return reject(exec, scope, throwException, ASCIILiteral(NonExtensibleObjectPropertyDefineError));
         }
 
         // 4.a. If IsGenericDescriptor(Desc) or IsDataDescriptor(Desc) is true, then create an own data property
@@ -2054,10 +2058,10 @@ bool JSObject::defineOwnIndexedProperty(ExecState* exec, unsigned index, const P
     if (!current.configurable()) {
         // 7.a. Reject, if the [[Configurable]] field of Desc is true.
         if (descriptor.configurablePresent() && descriptor.configurable())
-            return reject(exec, throwException, "Attempting to change configurable attribute of unconfigurable property.");
+            return reject(exec, scope, throwException, ASCIILiteral(UnconfigurablePropertyChangeConfigurabilityError));
         // 7.b. Reject, if the [[Enumerable]] field of Desc is present and the [[Enumerable]] fields of current and Desc are the Boolean negation of each other.
         if (descriptor.enumerablePresent() && current.enumerable() != descriptor.enumerable())
-            return reject(exec, throwException, "Attempting to change enumerable attribute of unconfigurable property.");
+            return reject(exec, scope, throwException, ASCIILiteral(UnconfigurablePropertyChangeEnumerabilityError));
     }
 
     // 8. If IsGenericDescriptor(Desc) is true, then no further validation is required.
@@ -2066,7 +2070,7 @@ bool JSObject::defineOwnIndexedProperty(ExecState* exec, unsigned index, const P
         if (current.isDataDescriptor() != descriptor.isDataDescriptor()) {
             // 9.a. Reject, if the [[Configurable]] field of current is false.
             if (!current.configurable())
-                return reject(exec, throwException, UnconfigurablePropertyChangeAccessMechanismError);
+                return reject(exec, scope, throwException, ASCIILiteral(UnconfigurablePropertyChangeAccessMechanismError));
             // 9.b. If IsDataDescriptor(current) is true, then convert the property named P of object O from a
             // data property to an accessor property. Preserve the existing values of the converted property's
             // [[Configurable]] and [[Enumerable]] attributes and set the rest of the property's attributes to
@@ -2080,11 +2084,11 @@ bool JSObject::defineOwnIndexedProperty(ExecState* exec, unsigned index, const P
             if (!current.configurable() && !current.writable()) {
                 // 10.a.i. Reject, if the [[Writable]] field of current is false and the [[Writable]] field of Desc is true.
                 if (descriptor.writable())
-                    return reject(exec, throwException, "Attempting to change writable attribute of unconfigurable property.");
+                    return reject(exec, scope, throwException, ASCIILiteral(UnconfigurablePropertyChangeWritabilityError));
                 // 10.a.ii. If the [[Writable]] field of current is false, then
                 // 10.a.ii.1. Reject, if the [[Value]] field of Desc is present and SameValue(Desc.[[Value]], current.[[Value]]) is false.
                 if (descriptor.value() && !sameValue(exec, descriptor.value(), current.value()))
-                    return reject(exec, throwException, "Attempting to change value of a readonly property.");
+                    return reject(exec, scope, throwException, ASCIILiteral(ReadonlyPropertyChangeError));
             }
             // 10.b. else, the [[Configurable]] field of current is true, so any change is acceptable.
         } else {
@@ -2093,10 +2097,10 @@ bool JSObject::defineOwnIndexedProperty(ExecState* exec, unsigned index, const P
             if (!current.configurable()) {
                 // 11.i. Reject, if the [[Set]] field of Desc is present and SameValue(Desc.[[Set]], current.[[Set]]) is false.
                 if (descriptor.setterPresent() && descriptor.setter() != current.setter())
-                    return reject(exec, throwException, "Attempting to change the setter of an unconfigurable property.");
+                    return reject(exec, scope, throwException, ASCIILiteral("Attempting to change the setter of an unconfigurable property."));
                 // 11.ii. Reject, if the [[Get]] field of Desc is present and SameValue(Desc.[[Get]], current.[[Get]]) is false.
                 if (descriptor.getterPresent() && descriptor.getter() != current.getter())
-                    return reject(exec, throwException, "Attempting to change the getter of an unconfigurable property.");
+                    return reject(exec, scope, throwException, ASCIILiteral("Attempting to change the getter of an unconfigurable property."));
             }
         }
     }
@@ -2262,11 +2266,8 @@ bool JSObject::putByIndexBeyondVectorLengthWithArrayStorage(ExecState* exec, uns
     unsigned length = storage->length();
     if (i >= length) {
         // Prohibit growing the array if length is not writable.
-        if (map->lengthIsReadOnly() || !isStructureExtensible()) {
-            if (shouldThrow)
-                throwTypeError(exec, scope, ReadonlyPropertyWriteError);
-            return false;
-        }
+        if (map->lengthIsReadOnly() || !isStructureExtensible())
+            return reject(exec, scope, shouldThrow, ASCIILiteral(ReadonlyPropertyWriteError));
         length = i + 1;
         storage->setLength(length);
     }
@@ -2361,6 +2362,7 @@ bool JSObject::putByIndexBeyondVectorLength(ExecState* exec, unsigned i, JSValue
 bool JSObject::putDirectIndexBeyondVectorLengthWithArrayStorage(ExecState* exec, unsigned i, JSValue value, unsigned attributes, PutDirectIndexMode mode, ArrayStorage* storage)
 {
     VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     
     // i should be a valid array index that is outside of the current vector.
     ASSERT(hasAnyArrayStorage(indexingType()));
@@ -2392,7 +2394,7 @@ bool JSObject::putDirectIndexBeyondVectorLengthWithArrayStorage(ExecState* exec,
             return true;
         }
         // We don't want to, or can't use a vector to hold this property - allocate a sparse map & add the value.
-        map = allocateSparseIndexMap(exec->vm());
+        map = allocateSparseIndexMap(vm);
         return map->putDirect(exec, this, i, value, attributes, mode);
     }
 
@@ -2402,9 +2404,9 @@ bool JSObject::putDirectIndexBeyondVectorLengthWithArrayStorage(ExecState* exec,
         if (mode != PutDirectIndexLikePutDirect) {
             // Prohibit growing the array if length is not writable.
             if (map->lengthIsReadOnly())
-                return reject(exec, mode == PutDirectIndexShouldThrow, ReadonlyPropertyWriteError);
+                return reject(exec, scope, mode == PutDirectIndexShouldThrow, ASCIILiteral(ReadonlyPropertyWriteError));
             if (!isStructureExtensible())
-                return reject(exec, mode == PutDirectIndexShouldThrow, "Attempting to define property on object that is not extensible.");
+                return reject(exec, scope, mode == PutDirectIndexShouldThrow, ASCIILiteral(NonExtensibleObjectPropertyDefineError));
         }
         length = i + 1;
         storage->setLength(length);
@@ -2413,7 +2415,7 @@ bool JSObject::putDirectIndexBeyondVectorLengthWithArrayStorage(ExecState* exec,
     // We are currently using a map - check whether we still want to be doing so.
     // We will continue  to use a sparse map if SparseMode is set, a vector would be too sparse, or if allocation fails.
     unsigned numValuesInArray = storage->m_numValuesInVector + map->size();
-    if (map->sparseMode() || attributes || !isDenseEnoughForVector(length, numValuesInArray) || !increaseVectorLength(exec->vm(), length))
+    if (map->sparseMode() || attributes || !isDenseEnoughForVector(length, numValuesInArray) || !increaseVectorLength(vm, length))
         return map->putDirect(exec, this, i, value, attributes, mode);
 
     // Reread m_storage after increaseVectorLength, update m_numValuesInVector.
@@ -2916,11 +2918,8 @@ bool validateAndApplyPropertyDescriptor(ExecState* exec, JSObject* object, Prope
     if (!isCurrentDefined) {
         // unless extensions are prevented!
         // Step 2.a
-        if (!isExtensible) {
-            if (throwException)
-                throwTypeError(exec, scope, ASCIILiteral("Attempting to define property on object that is not extensible."));
-            return false;
-        }
+        if (!isExtensible)
+            return reject(exec, scope, throwException, ASCIILiteral(NonExtensibleObjectPropertyDefineError));
         if (!object)
             return true;
         // Step 2.c/d
@@ -2939,16 +2938,10 @@ bool validateAndApplyPropertyDescriptor(ExecState* exec, JSObject* object, Prope
     // Step 5.
     // Filter out invalid changes
     if (!current.configurable()) {
-        if (descriptor.configurable()) {
-            if (throwException)
-                throwTypeError(exec, scope, ASCIILiteral("Attempting to change configurable attribute of unconfigurable property."));
-            return false;
-        }
-        if (descriptor.enumerablePresent() && descriptor.enumerable() != current.enumerable()) {
-            if (throwException)
-                throwTypeError(exec, scope, ASCIILiteral("Attempting to change enumerable attribute of unconfigurable property."));
-            return false;
-        }
+        if (descriptor.configurable())
+            return reject(exec, scope, throwException, ASCIILiteral(UnconfigurablePropertyChangeConfigurabilityError));
+        if (descriptor.enumerablePresent() && descriptor.enumerable() != current.enumerable())
+            return reject(exec, scope, throwException, ASCIILiteral(UnconfigurablePropertyChangeEnumerabilityError));
     }
     
     // Step 6.
@@ -2964,11 +2957,8 @@ bool validateAndApplyPropertyDescriptor(ExecState* exec, JSObject* object, Prope
     // Step 7.
     // Changing between a normal property or an accessor property
     if (descriptor.isDataDescriptor() != current.isDataDescriptor()) {
-        if (!current.configurable()) {
-            if (throwException)
-                throwTypeError(exec, scope, ASCIILiteral(UnconfigurablePropertyChangeAccessMechanismError));
-            return false;
-        }
+        if (!current.configurable())
+            return reject(exec, scope, throwException, ASCIILiteral(UnconfigurablePropertyChangeAccessMechanismError));
 
         if (!object)
             return true;
@@ -2981,17 +2971,11 @@ bool validateAndApplyPropertyDescriptor(ExecState* exec, JSObject* object, Prope
     // Changing the value and attributes of an existing property
     if (descriptor.isDataDescriptor()) {
         if (!current.configurable()) {
-            if (!current.writable() && descriptor.writable()) {
-                if (throwException)
-                    throwTypeError(exec, scope, ASCIILiteral("Attempting to change writable attribute of unconfigurable property."));
-                return false;
-            }
+            if (!current.writable() && descriptor.writable())
+                return reject(exec, scope, throwException, ASCIILiteral(UnconfigurablePropertyChangeWritabilityError));
             if (!current.writable()) {
-                if (descriptor.value() && !sameValue(exec, current.value(), descriptor.value())) {
-                    if (throwException)
-                        throwTypeError(exec, scope, ASCIILiteral("Attempting to change value of a readonly property."));
-                    return false;
-                }
+                if (descriptor.value() && !sameValue(exec, current.value(), descriptor.value()))
+                    return reject(exec, scope, throwException, ASCIILiteral(ReadonlyPropertyChangeError));
             }
         }
         if (current.attributesEqual(descriptor) && !descriptor.value())
@@ -3006,21 +2990,12 @@ bool validateAndApplyPropertyDescriptor(ExecState* exec, JSObject* object, Prope
     // Changing the accessor functions of an existing accessor property
     ASSERT(descriptor.isAccessorDescriptor());
     if (!current.configurable()) {
-        if (descriptor.setterPresent() && !(current.setterPresent() && JSValue::strictEqual(exec, current.setter(), descriptor.setter()))) {
-            if (throwException)
-                throwTypeError(exec, scope, ASCIILiteral("Attempting to change the setter of an unconfigurable property."));
-            return false;
-        }
-        if (descriptor.getterPresent() && !(current.getterPresent() && JSValue::strictEqual(exec, current.getter(), descriptor.getter()))) {
-            if (throwException)
-                throwTypeError(exec, scope, ASCIILiteral("Attempting to change the getter of an unconfigurable property."));
-            return false;
-        }
-        if (current.attributes() & CustomAccessor) {
-            if (throwException)
-                throwTypeError(exec, scope, ASCIILiteral(UnconfigurablePropertyChangeAccessMechanismError));
-            return false;
-        }
+        if (descriptor.setterPresent() && !(current.setterPresent() && JSValue::strictEqual(exec, current.setter(), descriptor.setter())))
+            return reject(exec, scope, throwException, ASCIILiteral("Attempting to change the setter of an unconfigurable property."));
+        if (descriptor.getterPresent() && !(current.getterPresent() && JSValue::strictEqual(exec, current.getter(), descriptor.getter())))
+            return reject(exec, scope, throwException, ASCIILiteral("Attempting to change the getter of an unconfigurable property."));
+        if (current.attributes() & CustomAccessor)
+            return reject(exec, scope, throwException, ASCIILiteral(UnconfigurablePropertyChangeAccessMechanismError));
     }
 
     // Step 10/11.
index 0aeb821..b96a63c 100644 (file)
@@ -68,8 +68,14 @@ struct HashTable;
 struct HashTableValue;
 
 JS_EXPORT_PRIVATE JSObject* throwTypeError(ExecState*, ThrowScope&, const String&);
-extern JS_EXPORTDATA const char* ReadonlyPropertyWriteError;
-extern JS_EXPORTDATA const char* UnconfigurablePropertyChangeAccessMechanismError;
+extern JS_EXPORTDATA const char* const NonExtensibleObjectPropertyDefineError;
+extern JS_EXPORTDATA const char* const ReadonlyPropertyWriteError;
+extern JS_EXPORTDATA const char* const ReadonlyPropertyChangeError;
+extern JS_EXPORTDATA const char* const UnableToDeletePropertyError;
+extern JS_EXPORTDATA const char* const UnconfigurablePropertyChangeAccessMechanismError;
+extern JS_EXPORTDATA const char* const UnconfigurablePropertyChangeConfigurabilityError;
+extern JS_EXPORTDATA const char* const UnconfigurablePropertyChangeEnumerabilityError;
+extern JS_EXPORTDATA const char* const UnconfigurablePropertyChangeWritabilityError;
 
 COMPILE_ASSERT(None < FirstInternalAttribute, None_is_below_FirstInternalAttribute);
 COMPILE_ASSERT(ReadOnly < FirstInternalAttribute, ReadOnly_is_below_FirstInternalAttribute);
index 7e9ccbc..81be41e 100644 (file)
@@ -177,11 +177,8 @@ ALWAYS_INLINE bool JSObject::putInline(JSCell* cell, ExecState* exec, PropertyNa
 
     if (thisObject->canPerformFastPutInline(exec, vm, propertyName)) {
         ASSERT(!thisObject->structure(vm)->prototypeChainMayInterceptStoreTo(vm, propertyName));
-        if (!thisObject->putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot)) {
-            if (slot.isStrictMode())
-                throwTypeError(exec, scope, ASCIILiteral(ReadonlyPropertyWriteError));
-            return false;
-        }
+        if (!thisObject->putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot))
+            return reject(exec, scope, slot.isStrictMode(), ASCIILiteral(ReadonlyPropertyWriteError));
         return true;
     }
 
index 9f5d985..59ca1f3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2011-2012, 2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -150,10 +150,7 @@ bool JSProxy::setPrototype(JSObject*, ExecState* exec, JSValue, bool shouldThrow
 {
     auto scope = DECLARE_THROW_SCOPE(exec->vm());
 
-    if (shouldThrowIfCantSet)
-        throwTypeError(exec, scope, ASCIILiteral("Cannot set prototype of this object"));
-
-    return false;
+    return reject(exec, scope, shouldThrowIfCantSet, ASCIILiteral("Cannot set prototype of this object"));
 }
 
 JSValue JSProxy::getPrototype(JSObject* object, ExecState* exec)
index d82b618..e65f54f 100644 (file)
@@ -183,7 +183,7 @@ inline bool symbolTablePut(SymbolTableObjectType* object, ExecState* exec, Prope
         ASSERT(!fastEntry.isNull());
         if (fastEntry.isReadOnly() && !ignoreReadOnlyErrors) {
             if (shouldThrowReadOnlyError)
-                throwTypeError(exec, scope, ReadonlyPropertyWriteError);
+                throwTypeError(exec, scope, ASCIILiteral(ReadonlyPropertyWriteError));
             putResult = false;
             return true;
         }
index 6ce8955..ce40cd4 100644 (file)
@@ -254,19 +254,22 @@ inline bool replaceStaticPropertySlot(VM& vm, JSObject* thisObject, PropertyName
 // 'slot.thisValue()' is the object the put was originally performed on (in the case of a proxy, the proxy itself).
 inline bool putEntry(ExecState* exec, const HashTableValue* entry, JSObject* base, JSObject* thisValue, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
     if (entry->attributes() & BuiltinOrFunctionOrLazyProperty) {
         if (!(entry->attributes() & ReadOnly)) {
             // If this is a function or lazy property put then we just do the put because
             // logically the object already had the property, so this is just a replace.
             if (JSObject* thisObject = jsDynamicCast<JSObject*>(thisValue))
-                thisObject->putDirect(exec->vm(), propertyName, value);
+                thisObject->putDirect(vm, propertyName, value);
             return true;
         }
-        return reject(exec, slot.isStrictMode(), ReadonlyPropertyWriteError);
+        return reject(exec, scope, slot.isStrictMode(), ASCIILiteral(ReadonlyPropertyWriteError));
     }
 
     if (entry->attributes() & Accessor)
-        return reject(exec, slot.isStrictMode(), ReadonlyPropertyWriteError);
+        return reject(exec, scope, slot.isStrictMode(), ASCIILiteral(ReadonlyPropertyWriteError));
 
     if (!(entry->attributes() & ReadOnly)) {
         ASSERT_WITH_MESSAGE(!(entry->attributes() & DOMJITAttribute), "DOMJITAttribute supports readonly attributes currently.");
@@ -280,7 +283,7 @@ inline bool putEntry(ExecState* exec, const HashTableValue* entry, JSObject* bas
         return result;
     }
 
-    return reject(exec, slot.isStrictMode(), ReadonlyPropertyWriteError);
+    return reject(exec, scope, slot.isStrictMode(), ASCIILiteral(ReadonlyPropertyWriteError));
 }
 
 /**
index 05dac5c..21359a4 100644 (file)
@@ -101,19 +101,22 @@ void RegExpObject::getGenericPropertyNames(JSObject* object, ExecState* exec, Pr
 
 bool RegExpObject::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool shouldThrow)
 {
-    if (propertyName == exec->propertyNames().lastIndex) {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    if (propertyName == vm.propertyNames->lastIndex) {
         RegExpObject* regExp = asRegExpObject(object);
         if (descriptor.configurablePresent() && descriptor.configurable())
-            return reject(exec, shouldThrow, "Attempting to change configurable attribute of unconfigurable property.");
+            return reject(exec, scope, shouldThrow, ASCIILiteral(UnconfigurablePropertyChangeConfigurabilityError));
         if (descriptor.enumerablePresent() && descriptor.enumerable())
-            return reject(exec, shouldThrow, "Attempting to change enumerable attribute of unconfigurable property.");
+            return reject(exec, scope, shouldThrow, ASCIILiteral(UnconfigurablePropertyChangeEnumerabilityError));
         if (descriptor.isAccessorDescriptor())
-            return reject(exec, shouldThrow, UnconfigurablePropertyChangeAccessMechanismError);
+            return reject(exec, scope, shouldThrow, ASCIILiteral(UnconfigurablePropertyChangeAccessMechanismError));
         if (!regExp->m_lastIndexIsWritable) {
             if (descriptor.writablePresent() && descriptor.writable())
-                return reject(exec, shouldThrow, "Attempting to change writable attribute of unconfigurable property.");
+                return reject(exec, scope, shouldThrow, ASCIILiteral(UnconfigurablePropertyChangeWritabilityError));
             if (!sameValue(exec, regExp->getLastIndex(), descriptor.value()))
-                return reject(exec, shouldThrow, "Attempting to change value of a readonly property.");
+                return reject(exec, scope, shouldThrow, ASCIILiteral(ReadonlyPropertyChangeError));
             return true;
         }
         if (descriptor.value())
index 65a97a3..1351274 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "JSObject.h"
 #include "RegExp.h"
+#include "Reject.h"
 #include "ThrowScope.h"
 
 namespace JSC {
@@ -50,7 +51,7 @@ public:
             m_lastIndex.setWithoutWriteBarrier(jsNumber(lastIndex));
             return true;
         }
-        throwTypeError(exec, scope, ReadonlyPropertyWriteError);
+        throwTypeError(exec, scope, ASCIILiteral(ReadonlyPropertyWriteError));
         return false;
     }
     bool setLastIndex(ExecState* exec, JSValue lastIndex, bool shouldThrow)
@@ -59,13 +60,11 @@ public:
         auto scope = DECLARE_THROW_SCOPE(vm);
 
         if (LIKELY(m_lastIndexIsWritable)) {
-            m_lastIndex.set(exec->vm(), this, lastIndex);
+            m_lastIndex.set(vm, this, lastIndex);
             return true;
         }
 
-        if (shouldThrow)
-            throwTypeError(exec, scope, ReadonlyPropertyWriteError);
-        return false;
+        return reject(exec, scope, shouldThrow, ASCIILiteral(ReadonlyPropertyWriteError));
     }
     JSValue getLastIndex() const
     {
index 27a0642..961bec2 100644 (file)
 
 namespace JSC {
 
-inline bool reject(ExecState* exec, bool throwException, const char* message)
+inline bool reject(ExecState* exec, ThrowScope& scope, bool throwException, ASCIILiteral message)
 {
-    VM& vm = exec->vm();
-    auto scope = DECLARE_THROW_SCOPE(vm);
     if (throwException)
         throwTypeError(exec, scope, message);
     return false;
index 990c6c2..f6b2079 100644 (file)
@@ -102,9 +102,7 @@ bool SparseArrayValueMap::putEntry(ExecState* exec, JSObject* array, unsigned i,
     // extensible, this is not the right thing to have done - so remove again.
     if (result.isNewEntry && !array->isStructureExtensible()) {
         remove(result.iterator);
-        if (shouldThrow)
-            throwTypeError(exec, scope, ReadonlyPropertyWriteError);
-        return false;
+        return reject(exec, scope, shouldThrow, ASCIILiteral(ReadonlyPropertyWriteError));
     }
     
     return entry.put(exec, array, this, value, shouldThrow);
@@ -112,8 +110,12 @@ bool SparseArrayValueMap::putEntry(ExecState* exec, JSObject* array, unsigned i,
 
 bool SparseArrayValueMap::putDirect(ExecState* exec, JSObject* array, unsigned i, JSValue value, unsigned attributes, PutDirectIndexMode mode)
 {
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
     ASSERT(value);
     
+    bool shouldThrow = (mode == PutDirectIndexShouldThrow);
+
     AddResult result = add(array, i);
     SparseArrayEntry& entry = result.iterator->value;
 
@@ -123,13 +125,13 @@ bool SparseArrayValueMap::putDirect(ExecState* exec, JSObject* array, unsigned i
         // extensible, this is not the right thing to have done - so remove again.
         if (result.isNewEntry) {
             remove(result.iterator);
-            return reject(exec, mode == PutDirectIndexShouldThrow, "Attempting to define property on object that is not extensible.");
+            return reject(exec, scope, shouldThrow, ASCIILiteral(NonExtensibleObjectPropertyDefineError));
         }
         if (entry.attributes & ReadOnly)
-            return reject(exec, mode == PutDirectIndexShouldThrow, ReadonlyPropertyWriteError);
+            return reject(exec, scope, shouldThrow, ASCIILiteral(ReadonlyPropertyWriteError));
     }
     entry.attributes = attributes;
-    entry.set(exec->vm(), this, value);
+    entry.set(vm, this, value);
     return true;
 }
 
@@ -157,11 +159,8 @@ bool SparseArrayEntry::put(ExecState* exec, JSValue thisValue, SparseArrayValueM
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     if (!(attributes & Accessor)) {
-        if (attributes & ReadOnly) {
-            if (shouldThrow)
-                throwTypeError(exec, scope, ReadonlyPropertyWriteError);
-            return false;
-        }
+        if (attributes & ReadOnly)
+            return reject(exec, scope, shouldThrow, ASCIILiteral(ReadonlyPropertyWriteError));
 
         set(vm, map, value);
         return true;
index 38d22f2..b32ac09 100644 (file)
@@ -70,11 +70,8 @@ bool StringObject::put(JSCell* cell, ExecState* exec, PropertyName propertyName,
     if (UNLIKELY(isThisValueAltered(slot, thisObject)))
         return ordinarySetSlow(exec, thisObject, propertyName, value, slot.thisValue(), slot.isStrictMode());
 
-    if (propertyName == exec->propertyNames().length) {
-        if (slot.isStrictMode())
-            throwTypeError(exec, scope, ReadonlyPropertyWriteError);
-        return false;
-    }
+    if (propertyName == vm.propertyNames->length)
+        return reject(exec, scope, slot.isStrictMode(), ASCIILiteral(ReadonlyPropertyWriteError));
     if (Optional<uint32_t> index = parseIndex(propertyName))
         return putByIndex(cell, exec, index.value(), value, slot.isStrictMode());
     return JSObject::put(cell, exec, propertyName, value, slot);
@@ -86,11 +83,8 @@ bool StringObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyNa
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     StringObject* thisObject = jsCast<StringObject*>(cell);
-    if (thisObject->internalValue()->canGetIndex(propertyName)) {
-        if (shouldThrow)
-            throwTypeError(exec, scope, ReadonlyPropertyWriteError);
-        return false;
-    }
+    if (thisObject->internalValue()->canGetIndex(propertyName))
+        return reject(exec, scope, shouldThrow, ASCIILiteral(ReadonlyPropertyWriteError));
     return JSObject::putByIndex(cell, exec, propertyName, value, shouldThrow);
 }
 
index 4fcf546..beade31 100644 (file)
@@ -107,7 +107,7 @@ EncodedJSValue JSC_HOST_CALL symbolConstructorFor(ExecState* exec)
     return JSValue::encode(Symbol::create(exec->vm(), exec->vm().symbolRegistry().symbolForKey(string)));
 }
 
-const char* SymbolKeyForTypeError = "Symbol.keyFor requires that the first argument be a symbol";
+const char* const SymbolKeyForTypeError = "Symbol.keyFor requires that the first argument be a symbol";
 
 EncodedJSValue JSC_HOST_CALL symbolConstructorKeyFor(ExecState* exec)
 {
@@ -116,7 +116,7 @@ EncodedJSValue JSC_HOST_CALL symbolConstructorKeyFor(ExecState* exec)
 
     JSValue symbolValue = exec->argument(0);
     if (!symbolValue.isSymbol())
-        return JSValue::encode(throwTypeError(exec, scope, SymbolKeyForTypeError));
+        return JSValue::encode(throwTypeError(exec, scope, ASCIILiteral(SymbolKeyForTypeError)));
 
     SymbolImpl& uid = asSymbol(symbolValue)->privateName().uid();
     if (!uid.symbolRegistry())
index dc008e6..58b9c43 100644 (file)
@@ -1,3 +1,19 @@
+2016-10-17  Mark Lam  <mark.lam@apple.com>
+
+        Use the reject() helper function for conditionally throwing TypeErrors.
+        https://bugs.webkit.org/show_bug.cgi?id=163491
+
+        Reviewed by Filip Pizlo.
+
+        No new tests because this patch does not introduce new behavior.
+
+        * bindings/js/JSCryptoAlgorithmDictionary.cpp:
+        (WebCore::createRsaKeyGenParams):
+        * bindings/js/JSIDBDatabaseCustom.cpp:
+        (WebCore::JSIDBDatabase::createObjectStore):
+        * bridge/c/c_instance.cpp:
+        (JSC::Bindings::CInstance::invokeMethod):
+
 2016-10-17  Miguel Gomez  <magomez@igalia.com>
 
         [GTK] Several tests crashing on debug bot in (anonymous namespace)::MediaPlayerPrivateGStreamerBase::repaint
index 6c2a5a8..2c1084c 100644 (file)
@@ -244,7 +244,7 @@ static RefPtr<CryptoAlgorithmParametersDeprecated> createRsaKeyGenParams(ExecSta
 
     RefPtr<Uint8Array> publicExponentArray = toUint8Array(publicExponentValue);
     if (!publicExponentArray) {
-        throwTypeError(&state, scope, "Expected a Uint8Array in publicExponent");
+        throwTypeError(&state, scope, ASCIILiteral("Expected a Uint8Array in publicExponent"));
         return nullptr;
     }
     result->publicExponent.append(publicExponentArray->data(), publicExponentArray->byteLength());
index 9f85396..626ac2f 100644 (file)
@@ -59,7 +59,7 @@ JSValue JSIDBDatabase::createObjectStore(ExecState& state)
 
     JSValue optionsValue = state.argument(1);
     if (!optionsValue.isUndefinedOrNull() && !optionsValue.isObject())
-        return throwTypeError(&state, scope, "Not an object.");
+        return throwTypeError(&state, scope, ASCIILiteral("Not an object."));
 
     IDBKeyPath keyPath;
     bool autoIncrement = false;
index ddbd3e8..065ce36 100644 (file)
@@ -160,7 +160,7 @@ JSValue CInstance::invokeMethod(ExecState* exec, RuntimeMethod* runtimeMethod)
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     if (!asObject(runtimeMethod)->inherits(CRuntimeMethod::info()))
-        return throwTypeError(exec, scope, "Attempt to invoke non-plug-in method on plug-in object.");
+        return throwTypeError(exec, scope, ASCIILiteral("Attempt to invoke non-plug-in method on plug-in object."));
 
     CMethod* method = static_cast<CMethod*>(runtimeMethod->method());
     ASSERT(method);