summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/runtime/RegExpConstructor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/runtime/RegExpConstructor.cpp')
-rw-r--r--Source/JavaScriptCore/runtime/RegExpConstructor.cpp307
1 files changed, 307 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp
new file mode 100644
index 000000000..ee1d8b3fc
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003, 2007, 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2009 Torch Mobile, Inc.
+ *
+ * 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 "RegExpConstructor.h"
+
+#include "Error.h"
+#include "JSCInlines.h"
+#include "RegExpMatchesArray.h"
+#include "RegExpPrototype.h"
+
+namespace JSC {
+
+static EncodedJSValue regExpConstructorInput(ExecState*, JSObject*, EncodedJSValue, PropertyName);
+static EncodedJSValue regExpConstructorMultiline(ExecState*, JSObject*, EncodedJSValue, PropertyName);
+static EncodedJSValue regExpConstructorLastMatch(ExecState*, JSObject*, EncodedJSValue, PropertyName);
+static EncodedJSValue regExpConstructorLastParen(ExecState*, JSObject*, EncodedJSValue, PropertyName);
+static EncodedJSValue regExpConstructorLeftContext(ExecState*, JSObject*, EncodedJSValue, PropertyName);
+static EncodedJSValue regExpConstructorRightContext(ExecState*, JSObject*, EncodedJSValue, PropertyName);
+static EncodedJSValue regExpConstructorDollar1(ExecState*, JSObject*, EncodedJSValue, PropertyName);
+static EncodedJSValue regExpConstructorDollar2(ExecState*, JSObject*, EncodedJSValue, PropertyName);
+static EncodedJSValue regExpConstructorDollar3(ExecState*, JSObject*, EncodedJSValue, PropertyName);
+static EncodedJSValue regExpConstructorDollar4(ExecState*, JSObject*, EncodedJSValue, PropertyName);
+static EncodedJSValue regExpConstructorDollar5(ExecState*, JSObject*, EncodedJSValue, PropertyName);
+static EncodedJSValue regExpConstructorDollar6(ExecState*, JSObject*, EncodedJSValue, PropertyName);
+static EncodedJSValue regExpConstructorDollar7(ExecState*, JSObject*, EncodedJSValue, PropertyName);
+static EncodedJSValue regExpConstructorDollar8(ExecState*, JSObject*, EncodedJSValue, PropertyName);
+static EncodedJSValue regExpConstructorDollar9(ExecState*, JSObject*, EncodedJSValue, PropertyName);
+
+static void setRegExpConstructorInput(ExecState*, JSObject*, EncodedJSValue, EncodedJSValue);
+static void setRegExpConstructorMultiline(ExecState*, JSObject*, EncodedJSValue, EncodedJSValue);
+
+} // namespace JSC
+
+#include "RegExpConstructor.lut.h"
+
+namespace JSC {
+
+const ClassInfo RegExpConstructor::s_info = { "Function", &InternalFunction::s_info, &regExpConstructorTable, CREATE_METHOD_TABLE(RegExpConstructor) };
+
+/* Source for RegExpConstructor.lut.h
+@begin regExpConstructorTable
+ input regExpConstructorInput None
+ $_ regExpConstructorInput DontEnum
+ multiline regExpConstructorMultiline None
+ $* regExpConstructorMultiline DontEnum
+ lastMatch regExpConstructorLastMatch DontDelete|ReadOnly
+ $& regExpConstructorLastMatch DontDelete|ReadOnly|DontEnum
+ lastParen regExpConstructorLastParen DontDelete|ReadOnly
+ $+ regExpConstructorLastParen DontDelete|ReadOnly|DontEnum
+ leftContext regExpConstructorLeftContext DontDelete|ReadOnly
+ $` regExpConstructorLeftContext DontDelete|ReadOnly|DontEnum
+ rightContext regExpConstructorRightContext DontDelete|ReadOnly
+ $' regExpConstructorRightContext DontDelete|ReadOnly|DontEnum
+ $1 regExpConstructorDollar1 DontDelete|ReadOnly
+ $2 regExpConstructorDollar2 DontDelete|ReadOnly
+ $3 regExpConstructorDollar3 DontDelete|ReadOnly
+ $4 regExpConstructorDollar4 DontDelete|ReadOnly
+ $5 regExpConstructorDollar5 DontDelete|ReadOnly
+ $6 regExpConstructorDollar6 DontDelete|ReadOnly
+ $7 regExpConstructorDollar7 DontDelete|ReadOnly
+ $8 regExpConstructorDollar8 DontDelete|ReadOnly
+ $9 regExpConstructorDollar9 DontDelete|ReadOnly
+@end
+*/
+
+RegExpConstructor::RegExpConstructor(VM& vm, Structure* structure, RegExpPrototype* regExpPrototype)
+ : InternalFunction(vm, structure)
+ , m_cachedResult(vm, this, regExpPrototype->regExp())
+ , m_multiline(false)
+{
+}
+
+void RegExpConstructor::finishCreation(VM& vm, RegExpPrototype* regExpPrototype)
+{
+ Base::finishCreation(vm, regExpPrototype->classInfo()->className);
+ ASSERT(inherits(info()));
+
+ // ECMA 15.10.5.1 RegExp.prototype
+ putDirectWithoutTransition(vm, vm.propertyNames->prototype, regExpPrototype, DontEnum | DontDelete | ReadOnly);
+
+ // no. of arguments for constructor
+ putDirectWithoutTransition(vm, vm.propertyNames->length, jsNumber(2), ReadOnly | DontDelete | DontEnum);
+}
+
+void RegExpConstructor::destroy(JSCell* cell)
+{
+ static_cast<RegExpConstructor*>(cell)->RegExpConstructor::~RegExpConstructor();
+}
+
+void RegExpConstructor::visitChildren(JSCell* cell, SlotVisitor& visitor)
+{
+ RegExpConstructor* thisObject = jsCast<RegExpConstructor*>(cell);
+ ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+ Base::visitChildren(thisObject, visitor);
+ thisObject->m_cachedResult.visitChildren(visitor);
+}
+
+JSValue RegExpConstructor::getBackref(ExecState* exec, unsigned i)
+{
+ JSArray* array = m_cachedResult.lastResult(exec, this);
+
+ if (i < array->length()) {
+ JSValue result = JSValue(array).get(exec, i);
+ ASSERT(result.isString() || result.isUndefined());
+ if (!result.isUndefined())
+ return result;
+ }
+ return jsEmptyString(exec);
+}
+
+JSValue RegExpConstructor::getLastParen(ExecState* exec)
+{
+ JSArray* array = m_cachedResult.lastResult(exec, this);
+ unsigned length = array->length();
+ if (length > 1) {
+ JSValue result = JSValue(array).get(exec, length - 1);
+ ASSERT(result.isString() || result.isUndefined());
+ if (!result.isUndefined())
+ return result;
+ }
+ return jsEmptyString(exec);
+}
+
+JSValue RegExpConstructor::getLeftContext(ExecState* exec)
+{
+ return m_cachedResult.leftContext(exec, this);
+}
+
+JSValue RegExpConstructor::getRightContext(ExecState* exec)
+{
+ return m_cachedResult.rightContext(exec, this);
+}
+
+bool RegExpConstructor::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
+{
+ return getStaticValueSlot<RegExpConstructor, InternalFunction>(exec, regExpConstructorTable, jsCast<RegExpConstructor*>(object), propertyName, slot);
+}
+
+EncodedJSValue regExpConstructorDollar1(ExecState* exec, JSObject* slotBase, EncodedJSValue, PropertyName)
+{
+ return JSValue::encode(asRegExpConstructor(slotBase)->getBackref(exec, 1));
+}
+
+EncodedJSValue regExpConstructorDollar2(ExecState* exec, JSObject* slotBase, EncodedJSValue, PropertyName)
+{
+ return JSValue::encode(asRegExpConstructor(slotBase)->getBackref(exec, 2));
+}
+
+EncodedJSValue regExpConstructorDollar3(ExecState* exec, JSObject* slotBase, EncodedJSValue, PropertyName)
+{
+ return JSValue::encode(asRegExpConstructor(slotBase)->getBackref(exec, 3));
+}
+
+EncodedJSValue regExpConstructorDollar4(ExecState* exec, JSObject* slotBase, EncodedJSValue, PropertyName)
+{
+ return JSValue::encode(asRegExpConstructor(slotBase)->getBackref(exec, 4));
+}
+
+EncodedJSValue regExpConstructorDollar5(ExecState* exec, JSObject* slotBase, EncodedJSValue, PropertyName)
+{
+ return JSValue::encode(asRegExpConstructor(slotBase)->getBackref(exec, 5));
+}
+
+EncodedJSValue regExpConstructorDollar6(ExecState* exec, JSObject* slotBase, EncodedJSValue, PropertyName)
+{
+ return JSValue::encode(asRegExpConstructor(slotBase)->getBackref(exec, 6));
+}
+
+EncodedJSValue regExpConstructorDollar7(ExecState* exec, JSObject* slotBase, EncodedJSValue, PropertyName)
+{
+ return JSValue::encode(asRegExpConstructor(slotBase)->getBackref(exec, 7));
+}
+
+EncodedJSValue regExpConstructorDollar8(ExecState* exec, JSObject* slotBase, EncodedJSValue, PropertyName)
+{
+ return JSValue::encode(asRegExpConstructor(slotBase)->getBackref(exec, 8));
+}
+
+EncodedJSValue regExpConstructorDollar9(ExecState* exec, JSObject* slotBase, EncodedJSValue, PropertyName)
+{
+ return JSValue::encode(asRegExpConstructor(slotBase)->getBackref(exec, 9));
+}
+
+EncodedJSValue regExpConstructorInput(ExecState*, JSObject* slotBase, EncodedJSValue, PropertyName)
+{
+ return JSValue::encode(asRegExpConstructor(slotBase)->input());
+}
+
+EncodedJSValue regExpConstructorMultiline(ExecState*, JSObject* slotBase, EncodedJSValue, PropertyName)
+{
+ return JSValue::encode(jsBoolean(asRegExpConstructor(slotBase)->multiline()));
+}
+
+EncodedJSValue regExpConstructorLastMatch(ExecState* exec, JSObject* slotBase, EncodedJSValue, PropertyName)
+{
+ return JSValue::encode(asRegExpConstructor(slotBase)->getBackref(exec, 0));
+}
+
+EncodedJSValue regExpConstructorLastParen(ExecState* exec, JSObject* slotBase, EncodedJSValue, PropertyName)
+{
+ return JSValue::encode(asRegExpConstructor(slotBase)->getLastParen(exec));
+}
+
+EncodedJSValue regExpConstructorLeftContext(ExecState* exec, JSObject* slotBase, EncodedJSValue, PropertyName)
+{
+ return JSValue::encode(asRegExpConstructor(slotBase)->getLeftContext(exec));
+}
+
+EncodedJSValue regExpConstructorRightContext(ExecState* exec, JSObject* slotBase, EncodedJSValue, PropertyName)
+{
+ return JSValue::encode(asRegExpConstructor(slotBase)->getRightContext(exec));
+}
+
+void setRegExpConstructorInput(ExecState* exec, JSObject* baseObject, EncodedJSValue, EncodedJSValue value)
+{
+ if (auto constructor = jsDynamicCast<RegExpConstructor*>(baseObject))
+ constructor->setInput(exec, JSValue::decode(value).toString(exec));
+}
+
+void setRegExpConstructorMultiline(ExecState* exec, JSObject* baseObject, EncodedJSValue, EncodedJSValue value)
+{
+ if (auto constructor = jsDynamicCast<RegExpConstructor*>(baseObject))
+ constructor->setMultiline(JSValue::decode(value).toBoolean(exec));
+}
+
+// ECMA 15.10.4
+JSObject* constructRegExp(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args, bool callAsConstructor)
+{
+ JSValue arg0 = args.at(0);
+ JSValue arg1 = args.at(1);
+
+ if (arg0.inherits(RegExpObject::info())) {
+ if (!arg1.isUndefined())
+ return exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Cannot supply flags when constructing one RegExp from another.")));
+ // If called as a function, this just returns the first argument (see 15.10.3.1).
+ if (callAsConstructor) {
+ RegExp* regExp = static_cast<RegExpObject*>(asObject(arg0))->regExp();
+ return RegExpObject::create(exec->vm(), globalObject->regExpStructure(), regExp);
+ }
+ return asObject(arg0);
+ }
+
+ String pattern = arg0.isUndefined() ? emptyString() : arg0.toString(exec)->value(exec);
+ if (exec->hadException())
+ return 0;
+
+ RegExpFlags flags = NoFlags;
+ if (!arg1.isUndefined()) {
+ flags = regExpFlags(arg1.toString(exec)->value(exec));
+ if (exec->hadException())
+ return 0;
+ if (flags == InvalidFlags)
+ return exec->vm().throwException(exec, createSyntaxError(exec, ASCIILiteral("Invalid flags supplied to RegExp constructor.")));
+ }
+
+ VM& vm = exec->vm();
+ RegExp* regExp = RegExp::create(vm, pattern, flags);
+ if (!regExp->isValid())
+ return vm.throwException(exec, createSyntaxError(exec, regExp->errorMessage()));
+ return RegExpObject::create(vm, globalObject->regExpStructure(), regExp);
+}
+
+static EncodedJSValue JSC_HOST_CALL constructWithRegExpConstructor(ExecState* exec)
+{
+ ArgList args(exec);
+ return JSValue::encode(constructRegExp(exec, asInternalFunction(exec->callee())->globalObject(), args, true));
+}
+
+ConstructType RegExpConstructor::getConstructData(JSCell*, ConstructData& constructData)
+{
+ constructData.native.function = constructWithRegExpConstructor;
+ return ConstructTypeHost;
+}
+
+// ECMA 15.10.3
+static EncodedJSValue JSC_HOST_CALL callRegExpConstructor(ExecState* exec)
+{
+ ArgList args(exec);
+ return JSValue::encode(constructRegExp(exec, asInternalFunction(exec->callee())->globalObject(), args));
+}
+
+CallType RegExpConstructor::getCallData(JSCell*, CallData& callData)
+{
+ callData.native.function = callRegExpConstructor;
+ return CallTypeHost;
+}
+
+} // namespace JSC