X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/14957cd040308e3eeec43d26bae5d76da13fcd85..HEAD:/runtime/StringObject.cpp diff --git a/runtime/StringObject.cpp b/runtime/StringObject.cpp index 67dc291..eb7430e 100644 --- a/runtime/StringObject.cpp +++ b/runtime/StringObject.cpp @@ -21,82 +21,144 @@ #include "config.h" #include "StringObject.h" +#include "Error.h" +#include "JSGlobalObject.h" +#include "JSCInlines.h" #include "PropertyNameArray.h" namespace JSC { -ASSERT_CLASS_FITS_IN_CELL(StringObject); +STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(StringObject); -const ClassInfo StringObject::s_info = { "String", &JSWrapperObject::s_info, 0, 0 }; +const ClassInfo StringObject::s_info = { "String", &JSWrapperObject::s_info, 0, CREATE_METHOD_TABLE(StringObject) }; -StringObject::StringObject(ExecState* exec, Structure* structure) - : JSWrapperObject(exec->globalData(), structure) +StringObject::StringObject(VM& vm, Structure* structure) + : JSWrapperObject(vm, structure) { - ASSERT(inherits(&s_info)); - setInternalValue(exec->globalData(), jsEmptyString(exec)); } -StringObject::StringObject(JSGlobalData& globalData, Structure* structure, JSString* string) - : JSWrapperObject(globalData, structure) +void StringObject::finishCreation(VM& vm, JSString* string) { - ASSERT(inherits(&s_info)); - setInternalValue(globalData, string); + Base::finishCreation(vm); + ASSERT(inherits(info())); + setInternalValue(vm, string); } -StringObject::StringObject(ExecState* exec, Structure* structure, const UString& string) - : JSWrapperObject(exec->globalData(), structure) +bool StringObject::getOwnPropertySlot(JSObject* cell, ExecState* exec, PropertyName propertyName, PropertySlot& slot) { - ASSERT(inherits(&s_info)); - setInternalValue(exec->globalData(), jsString(exec, string)); -} - -bool StringObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) -{ - if (internalValue()->getStringPropertySlot(exec, propertyName, slot)) + StringObject* thisObject = jsCast(cell); + if (thisObject->internalValue()->getStringPropertySlot(exec, propertyName, slot)) return true; - return JSObject::getOwnPropertySlot(exec, propertyName, slot); + return JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot); } -bool StringObject::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot) +bool StringObject::getOwnPropertySlotByIndex(JSObject* object, ExecState* exec, unsigned propertyName, PropertySlot& slot) { - if (internalValue()->getStringPropertySlot(exec, propertyName, slot)) + StringObject* thisObject = jsCast(object); + if (thisObject->internalValue()->getStringPropertySlot(exec, propertyName, slot)) return true; - return JSObject::getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot); + return JSObject::getOwnPropertySlot(thisObject, exec, Identifier::from(exec, propertyName), slot); } -bool StringObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) +void StringObject::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot) { - if (internalValue()->getStringPropertyDescriptor(exec, propertyName, descriptor)) - return true; - return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor); + if (propertyName == exec->propertyNames().length) { + if (slot.isStrictMode()) + throwTypeError(exec, StrictModeReadonlyPropertyWriteError); + return; + } + JSObject::put(cell, exec, propertyName, value, slot); } -void StringObject::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) +void StringObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue value, bool shouldThrow) { - if (propertyName == exec->propertyNames().length) + StringObject* thisObject = jsCast(cell); + if (thisObject->internalValue()->canGetIndex(propertyName)) { + if (shouldThrow) + throwTypeError(exec, StrictModeReadonlyPropertyWriteError); return; - JSObject::put(exec, propertyName, value, slot); + } + JSObject::putByIndex(cell, exec, propertyName, value, shouldThrow); } -bool StringObject::deleteProperty(ExecState* exec, const Identifier& propertyName) +bool StringObject::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool throwException) { + StringObject* thisObject = jsCast(object); + + if (propertyName == exec->propertyNames().length) { + if (!object->isExtensible()) { + if (throwException) + exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Attempting to define property on object that is not extensible."))); + return false; + } + if (descriptor.configurablePresent() && descriptor.configurable()) { + if (throwException) + exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Attempting to change configurable attribute of unconfigurable property."))); + return false; + } + if (descriptor.enumerablePresent() && descriptor.enumerable()) { + if (throwException) + exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Attempting to change enumerable attribute of unconfigurable property."))); + return false; + } + if (descriptor.isAccessorDescriptor()) { + if (throwException) + exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Attempting to change access mechanism for an unconfigurable property."))); + return false; + } + if (descriptor.writablePresent() && descriptor.writable()) { + if (throwException) + exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Attempting to change writable attribute of unconfigurable property."))); + return false; + } + if (!descriptor.value()) + return true; + if (propertyName == exec->propertyNames().length && sameValue(exec, descriptor.value(), jsNumber(thisObject->internalValue()->length()))) + return true; + if (throwException) + exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Attempting to change value of a readonly property."))); + return false; + } + + return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException); +} + +bool StringObject::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName) +{ + StringObject* thisObject = jsCast(cell); if (propertyName == exec->propertyNames().length) return false; - bool isStrictUInt32; - unsigned i = propertyName.toUInt32(isStrictUInt32); - if (isStrictUInt32 && internalValue()->canGetIndex(i)) + Optional index = parseIndex(propertyName); + if (index && thisObject->internalValue()->canGetIndex(index.value())) { return false; - return JSObject::deleteProperty(exec, propertyName); + } + return JSObject::deleteProperty(thisObject, exec, propertyName); } -void StringObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) +bool StringObject::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned i) { - int size = internalValue()->length(); + StringObject* thisObject = jsCast(cell); + if (thisObject->internalValue()->canGetIndex(i)) + return false; + return JSObject::deletePropertyByIndex(thisObject, exec, i); +} + +void StringObject::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) +{ + StringObject* thisObject = jsCast(object); + int size = thisObject->internalValue()->length(); for (int i = 0; i < size; ++i) - propertyNames.add(Identifier(exec, UString::number(i))); - if (mode == IncludeDontEnumProperties) + propertyNames.add(Identifier::from(exec, i)); + if (mode.includeDontEnumProperties()) propertyNames.add(exec->propertyNames().length); - return JSObject::getOwnPropertyNames(exec, propertyNames, mode); + return JSObject::getOwnPropertyNames(thisObject, exec, propertyNames, mode); +} + +StringObject* constructString(VM& vm, JSGlobalObject* globalObject, JSValue string) +{ + StringObject* object = StringObject::create(vm, globalObject->stringObjectStructure()); + object->setInternalValue(vm, string); + return object; } } // namespace JSC