summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/runtime/RegExpObject.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-03-12 14:11:15 +0100
committerSimon Hausmann <simon.hausmann@nokia.com>2012-03-12 14:11:15 +0100
commitdd91e772430dc294e3bf478c119ef8d43c0a3358 (patch)
tree6f33ce4d5872a5691e0291eb45bf6ab373a5f567 /Source/JavaScriptCore/runtime/RegExpObject.cpp
parentad0d549d4cc13433f77c1ac8f0ab379c83d93f28 (diff)
downloadqtwebkit-dd91e772430dc294e3bf478c119ef8d43c0a3358.tar.gz
Imported WebKit commit 3db4eb1820ac8fb03065d7ea73a4d9db1e8fea1a (http://svn.webkit.org/repository/webkit/trunk@110422)
This includes build fixes for the latest qtbase/qtdeclarative as well as the final QML2 API.
Diffstat (limited to 'Source/JavaScriptCore/runtime/RegExpObject.cpp')
-rw-r--r--Source/JavaScriptCore/runtime/RegExpObject.cpp121
1 files changed, 91 insertions, 30 deletions
diff --git a/Source/JavaScriptCore/runtime/RegExpObject.cpp b/Source/JavaScriptCore/runtime/RegExpObject.cpp
index 4c192ff90..a81799c46 100644
--- a/Source/JavaScriptCore/runtime/RegExpObject.cpp
+++ b/Source/JavaScriptCore/runtime/RegExpObject.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2007, 2008 Apple Inc. All Rights Reserved.
+ * 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
@@ -40,8 +40,6 @@ static JSValue regExpObjectGlobal(ExecState*, JSValue, const Identifier&);
static JSValue regExpObjectIgnoreCase(ExecState*, JSValue, const Identifier&);
static JSValue regExpObjectMultiline(ExecState*, JSValue, const Identifier&);
static JSValue regExpObjectSource(ExecState*, JSValue, const Identifier&);
-static JSValue regExpObjectLastIndex(ExecState*, JSValue, const Identifier&);
-static void setRegExpObjectLastIndex(ExecState*, JSObject*, JSValue);
} // namespace JSC
@@ -59,14 +57,15 @@ const ClassInfo RegExpObject::s_info = { "RegExp", &JSNonFinalObject::s_info, 0,
ignoreCase regExpObjectIgnoreCase DontDelete|ReadOnly|DontEnum
multiline regExpObjectMultiline DontDelete|ReadOnly|DontEnum
source regExpObjectSource DontDelete|ReadOnly|DontEnum
- lastIndex regExpObjectLastIndex DontDelete|DontEnum
@end
*/
RegExpObject::RegExpObject(JSGlobalObject* globalObject, Structure* structure, RegExp* regExp)
: JSNonFinalObject(globalObject->globalData(), structure)
- , d(adoptPtr(new RegExpObjectData(globalObject->globalData(), this, regExp)))
+ , m_regExp(globalObject->globalData(), this, regExp)
+ , m_lastIndexIsWritable(true)
{
+ m_lastIndex.setWithoutWriteBarrier(jsNumber(0));
}
void RegExpObject::finishCreation(JSGlobalObject* globalObject)
@@ -75,11 +74,6 @@ void RegExpObject::finishCreation(JSGlobalObject* globalObject)
ASSERT(inherits(&s_info));
}
-void RegExpObject::destroy(JSCell* cell)
-{
- jsCast<RegExpObject*>(cell)->RegExpObject::~RegExpObject();
-}
-
void RegExpObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
{
RegExpObject* thisObject = jsCast<RegExpObject*>(cell);
@@ -87,22 +81,87 @@ void RegExpObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
Base::visitChildren(thisObject, visitor);
- if (thisObject->d->regExp)
- visitor.append(&thisObject->d->regExp);
- if (UNLIKELY(!thisObject->d->lastIndex.get().isInt32()))
- visitor.append(&thisObject->d->lastIndex);
+ if (thisObject->m_regExp)
+ visitor.append(&thisObject->m_regExp);
+ if (UNLIKELY(!thisObject->m_lastIndex.get().isInt32()))
+ visitor.append(&thisObject->m_lastIndex);
}
bool RegExpObject::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
{
+ if (propertyName == exec->propertyNames().lastIndex) {
+ RegExpObject* regExp = asRegExpObject(cell);
+ slot.setValue(regExp, regExp->getLastIndex());
+ return true;
+ }
return getStaticValueSlot<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), jsCast<RegExpObject*>(cell), propertyName, slot);
}
bool RegExpObject::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
{
+ if (propertyName == exec->propertyNames().lastIndex) {
+ RegExpObject* regExp = asRegExpObject(object);
+ descriptor.setDescriptor(regExp->getLastIndex(), regExp->m_lastIndexIsWritable ? DontDelete | DontEnum : DontDelete | DontEnum | ReadOnly);
+ return true;
+ }
return getStaticValueDescriptor<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), jsCast<RegExpObject*>(object), propertyName, descriptor);
}
+bool RegExpObject::deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName)
+{
+ if (propertyName == exec->propertyNames().lastIndex)
+ return false;
+ return Base::deleteProperty(cell, exec, propertyName);
+}
+
+void RegExpObject::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+{
+ if (mode == IncludeDontEnumProperties)
+ propertyNames.add(exec->propertyNames().lastIndex);
+ Base::getOwnPropertyNames(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);
+}
+
+static bool reject(ExecState* exec, bool throwException, const char* message)
+{
+ if (throwException)
+ throwTypeError(exec, message);
+ return false;
+}
+
+bool RegExpObject::defineOwnProperty(JSObject* object, ExecState* exec, const Identifier& propertyName, 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);
+}
+
JSValue regExpObjectGlobal(ExecState*, JSValue slotBase, const Identifier&)
{
return jsBoolean(asRegExpObject(slotBase)->regExp()->global());
@@ -127,6 +186,14 @@ JSValue regExpObjectSource(ExecState* exec, JSValue slotBase, const Identifier&)
bool inBrackets = false;
bool shouldEscape = false;
+ // 15.10.6.4 specifies that RegExp.prototype.toString must return '/' + source + '/',
+ // and also states that the result must be a valid RegularExpressionLiteral. '//' is
+ // not a valid RegularExpressionLiteral (since it is a single line comment), and hence
+ // source cannot ever validly be "". If the source is empty, return a different Pattern
+ // that would match the same thing.
+ if (!length)
+ return jsString(exec, "(?:)");
+
// early return for strings that don't contain a forwards slash and LineTerminator
for (unsigned i = 0; i < length; ++i) {
UChar ch = characters[i];
@@ -200,21 +267,15 @@ JSValue regExpObjectSource(ExecState* exec, JSValue slotBase, const Identifier&)
return jsString(exec, result.toUString());
}
-JSValue regExpObjectLastIndex(ExecState*, JSValue slotBase, const Identifier&)
-{
- return asRegExpObject(slotBase)->getLastIndex();
-}
-
void RegExpObject::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
{
+ if (propertyName == exec->propertyNames().lastIndex) {
+ asRegExpObject(cell)->setLastIndex(exec, value, slot.isStrictMode());
+ return;
+ }
lookupPut<RegExpObject, JSObject>(exec, propertyName, value, ExecState::regExpTable(exec), jsCast<RegExpObject*>(cell), slot);
}
-void setRegExpObjectLastIndex(ExecState* exec, JSObject* baseObject, JSValue value)
-{
- asRegExpObject(baseObject)->setLastIndex(exec->globalData(), value);
-}
-
JSValue RegExpObject::test(ExecState* exec)
{
return jsBoolean(match(exec));
@@ -236,7 +297,7 @@ bool RegExpObject::match(ExecState* exec)
if (!regExp()->global()) {
int position;
int length;
- regExpConstructor->performMatch(*globalData, d->regExp.get(), input, 0, position, length);
+ regExpConstructor->performMatch(*globalData, m_regExp.get(), input, 0, position, length);
return position >= 0;
}
@@ -245,13 +306,13 @@ bool RegExpObject::match(ExecState* exec)
if (LIKELY(jsLastIndex.isUInt32())) {
lastIndex = jsLastIndex.asUInt32();
if (lastIndex > input.length()) {
- setLastIndex(0);
+ setLastIndex(exec, 0);
return false;
}
} else {
double doubleLastIndex = jsLastIndex.toInteger(exec);
if (doubleLastIndex < 0 || doubleLastIndex > input.length()) {
- setLastIndex(0);
+ setLastIndex(exec, 0);
return false;
}
lastIndex = static_cast<unsigned>(doubleLastIndex);
@@ -259,13 +320,13 @@ bool RegExpObject::match(ExecState* exec)
int position;
int length = 0;
- regExpConstructor->performMatch(*globalData, d->regExp.get(), input, lastIndex, position, length);
+ regExpConstructor->performMatch(*globalData, m_regExp.get(), input, lastIndex, position, length);
if (position < 0) {
- setLastIndex(0);
+ setLastIndex(exec, 0);
return false;
}
- setLastIndex(position + length);
+ setLastIndex(exec, position + length);
return true;
}