diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-10-15 09:45:50 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-10-15 09:45:50 +0000 |
commit | e15dd966d523731101f70ccf768bba12435a0208 (patch) | |
tree | ae9cb828a24ded2585a41af3f21411523b47897d /Source/JavaScriptCore/runtime/RegExpObject.cpp | |
download | WebKitGtk-tarball-e15dd966d523731101f70ccf768bba12435a0208.tar.gz |
webkitgtk-2.10.2webkitgtk-2.10.2
Diffstat (limited to 'Source/JavaScriptCore/runtime/RegExpObject.cpp')
-rw-r--r-- | Source/JavaScriptCore/runtime/RegExpObject.cpp | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/runtime/RegExpObject.cpp b/Source/JavaScriptCore/runtime/RegExpObject.cpp new file mode 100644 index 000000000..60a26ef67 --- /dev/null +++ b/Source/JavaScriptCore/runtime/RegExpObject.cpp @@ -0,0 +1,201 @@ +/* + * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) + * Copyright (C) 2003, 2007, 2008, 2012 Apple Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "config.h" +#include "RegExpObject.h" + +#include "ButterflyInlines.h" +#include "CopiedSpaceInlines.h" +#include "Error.h" +#include "ExceptionHelpers.h" +#include "JSArray.h" +#include "JSGlobalObject.h" +#include "JSString.h" +#include "Lookup.h" +#include "JSCInlines.h" +#include "RegExpConstructor.h" +#include "RegExpMatchesArray.h" +#include "RegExpPrototype.h" +#include <wtf/text/StringBuilder.h> + +namespace JSC { + +STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(RegExpObject); + +const ClassInfo RegExpObject::s_info = { "RegExp", &Base::s_info, nullptr, CREATE_METHOD_TABLE(RegExpObject) }; + +RegExpObject::RegExpObject(VM& vm, Structure* structure, RegExp* regExp) + : JSNonFinalObject(vm, structure) + , m_regExp(vm, this, regExp) + , m_lastIndexIsWritable(true) +{ + m_lastIndex.setWithoutWriteBarrier(jsNumber(0)); +} + +void RegExpObject::finishCreation(VM& vm) +{ + Base::finishCreation(vm); + ASSERT(inherits(info())); +} + +void RegExpObject::visitChildren(JSCell* cell, SlotVisitor& visitor) +{ + RegExpObject* thisObject = jsCast<RegExpObject*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, info()); + Base::visitChildren(thisObject, visitor); + visitor.append(&thisObject->m_regExp); + visitor.append(&thisObject->m_lastIndex); +} + +bool RegExpObject::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot) +{ + if (propertyName == exec->propertyNames().lastIndex) { + RegExpObject* regExp = asRegExpObject(object); + unsigned attributes = regExp->m_lastIndexIsWritable ? DontDelete | DontEnum : DontDelete | DontEnum | ReadOnly; + slot.setValue(regExp, attributes, regExp->getLastIndex()); + return true; + } + return Base::getOwnPropertySlot(object, exec, propertyName, slot); +} + +bool RegExpObject::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName) +{ + if (propertyName == exec->propertyNames().lastIndex) + return false; + return Base::deleteProperty(cell, exec, propertyName); +} + +void RegExpObject::getOwnNonIndexPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) +{ + if (mode.includeDontEnumProperties()) + propertyNames.add(exec->propertyNames().lastIndex); + Base::getOwnNonIndexPropertyNames(object, exec, propertyNames, mode); +} + +void RegExpObject::getPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) +{ + if (mode.includeDontEnumProperties()) + propertyNames.add(exec->propertyNames().lastIndex); + Base::getPropertyNames(object, exec, propertyNames, mode); +} + +void RegExpObject::getGenericPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) +{ + if (mode.includeDontEnumProperties()) + propertyNames.add(exec->propertyNames().lastIndex); + Base::getGenericPropertyNames(object, exec, propertyNames, mode); +} + +static bool reject(ExecState* exec, bool throwException, const char* message) +{ + if (throwException) + throwTypeError(exec, ASCIILiteral(message)); + return false; +} + +bool RegExpObject::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool shouldThrow) +{ + if (propertyName == exec->propertyNames().lastIndex) { + RegExpObject* regExp = asRegExpObject(object); + if (descriptor.configurablePresent() && descriptor.configurable()) + return reject(exec, shouldThrow, "Attempting to change configurable attribute of unconfigurable property."); + if (descriptor.enumerablePresent() && descriptor.enumerable()) + return reject(exec, shouldThrow, "Attempting to change enumerable attribute of unconfigurable property."); + if (descriptor.isAccessorDescriptor()) + return reject(exec, shouldThrow, "Attempting to change access mechanism for an unconfigurable property."); + if (!regExp->m_lastIndexIsWritable) { + if (descriptor.writablePresent() && descriptor.writable()) + return reject(exec, shouldThrow, "Attempting to change writable attribute of unconfigurable property."); + if (!sameValue(exec, regExp->getLastIndex(), descriptor.value())) + return reject(exec, shouldThrow, "Attempting to change value of a readonly property."); + return true; + } + if (descriptor.writablePresent() && !descriptor.writable()) + regExp->m_lastIndexIsWritable = false; + if (descriptor.value()) + regExp->setLastIndex(exec, descriptor.value(), false); + return true; + } + + return Base::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow); +} + +static void regExpObjectSetLastIndexStrict(ExecState* exec, JSObject* slotBase, EncodedJSValue, EncodedJSValue value) +{ + asRegExpObject(slotBase)->setLastIndex(exec, JSValue::decode(value), true); +} + +static void regExpObjectSetLastIndexNonStrict(ExecState* exec, JSObject* slotBase, EncodedJSValue, EncodedJSValue value) +{ + asRegExpObject(slotBase)->setLastIndex(exec, JSValue::decode(value), false); +} + +void RegExpObject::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot) +{ + if (propertyName == exec->propertyNames().lastIndex) { + asRegExpObject(cell)->setLastIndex(exec, value, slot.isStrictMode()); + slot.setCustomProperty(asRegExpObject(cell), slot.isStrictMode() + ? regExpObjectSetLastIndexStrict + : regExpObjectSetLastIndexNonStrict); + return; + } + Base::put(cell, exec, propertyName, value, slot); +} + +JSValue RegExpObject::exec(ExecState* exec, JSString* string) +{ + if (MatchResult result = match(exec, string)) + return createRegExpMatchesArray(exec, string, regExp(), result); + return jsNull(); +} + +// Shared implementation used by test and exec. +MatchResult RegExpObject::match(ExecState* exec, JSString* string) +{ + RegExp* regExp = this->regExp(); + RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); + String input = string->value(exec); + VM& vm = exec->vm(); + if (!regExp->global()) + return regExpConstructor->performMatch(vm, regExp, string, input, 0); + + JSValue jsLastIndex = getLastIndex(); + unsigned lastIndex; + if (LIKELY(jsLastIndex.isUInt32())) { + lastIndex = jsLastIndex.asUInt32(); + if (lastIndex > input.length()) { + setLastIndex(exec, 0); + return MatchResult::failed(); + } + } else { + double doubleLastIndex = jsLastIndex.toInteger(exec); + if (doubleLastIndex < 0 || doubleLastIndex > input.length()) { + setLastIndex(exec, 0); + return MatchResult::failed(); + } + lastIndex = static_cast<unsigned>(doubleLastIndex); + } + + MatchResult result = regExpConstructor->performMatch(vm, regExp, string, input, lastIndex); + setLastIndex(exec, result.end); + return result; +} + +} // namespace JSC |