summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/runtime/RegExpObject.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2015-10-15 09:45:50 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2015-10-15 09:45:50 +0000
commite15dd966d523731101f70ccf768bba12435a0208 (patch)
treeae9cb828a24ded2585a41af3f21411523b47897d /Source/JavaScriptCore/runtime/RegExpObject.cpp
downloadWebKitGtk-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.cpp201
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