]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - runtime/RegExpConstructor.h
JavaScriptCore-1097.13.tar.gz
[apple/javascriptcore.git] / runtime / RegExpConstructor.h
index 6823f3fb709801be9300064eb40a8ec7adf3821b..0093f9484d9ffb2088526995b7490aed50f77501 100644 (file)
 #define RegExpConstructor_h
 
 #include "InternalFunction.h"
+#include "RegExp.h"
+#include "RegExpCachedResult.h"
+#include "RegExpObject.h"
 #include <wtf/OwnPtr.h>
 
+
 namespace JSC {
 
-    class RegExp;
     class RegExpPrototype;
-    struct RegExpConstructorPrivate;
 
     class RegExpConstructor : public InternalFunction {
     public:
-        RegExpConstructor(ExecState*, PassRefPtr<Structure>, RegExpPrototype*);
+        typedef InternalFunction Base;
 
-        static PassRefPtr<Structure> createStructure(JSValue prototype)
+        static RegExpConstructor* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, RegExpPrototype* regExpPrototype)
         {
-            return Structure::create(prototype, TypeInfo(ObjectType, ImplementsHasInstance));
+            RegExpConstructor* constructor = new (NotNull, allocateCell<RegExpConstructor>(*exec->heap())) RegExpConstructor(globalObject, structure, regExpPrototype);
+            constructor->finishCreation(exec, regExpPrototype);
+            return constructor;
         }
 
-        virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
-        virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
+        static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
+        {
+            return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
+        }
 
-        static const ClassInfo info;
+        static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
 
-        void performMatch(RegExp*, const UString&, int startOffset, int& position, int& length, int** ovector = 0);
-        JSObject* arrayOfMatches(ExecState*) const;
+        static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier& propertyName, PropertySlot&);
+        static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
 
-        void setInput(const UString&);
-        const UString& input() const;
+        static const ClassInfo s_info;
 
-        void setMultiline(bool);
-        bool multiline() const;
+        MatchResult performMatch(JSGlobalData&, RegExp*, JSString*, const UString&, int startOffset, int** ovector);
+        MatchResult performMatch(JSGlobalData&, RegExp*, JSString*, const UString&, int startOffset);
 
-        JSValue getBackref(ExecState*, unsigned) const;
-        JSValue getLastParen(ExecState*) const;
-        JSValue getLeftContext(ExecState*) const;
-        JSValue getRightContext(ExecState*) const;
+        void setMultiline(bool multiline) { m_multiline = multiline; }
+        bool multiline() const { return m_multiline; }
 
-    private:
-        virtual ConstructType getConstructData(ConstructData&);
-        virtual CallType getCallData(CallData&);
+        JSValue getBackref(ExecState*, unsigned);
+        JSValue getLastParen(ExecState*);
+        JSValue getLeftContext(ExecState*);
+        JSValue getRightContext(ExecState*);
+
+        void setInput(ExecState* exec, JSString* string) { m_cachedResult.setInput(exec, this, string); }
+        JSString* input() { return m_cachedResult.input(); }
 
-        virtual const ClassInfo* classInfo() const { return &info; }
+        static void visitChildren(JSCell*, SlotVisitor&);
 
-        OwnPtr<RegExpConstructorPrivate> d;
+    protected:
+        void finishCreation(ExecState*, RegExpPrototype*);
+        static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | Base::StructureFlags;
+
+    private:
+        RegExpConstructor(JSGlobalObject*, Structure*, RegExpPrototype*);
+        static void destroy(JSCell*);
+        static ConstructType getConstructData(JSCell*, ConstructData&);
+        static CallType getCallData(JSCell*, CallData&);
+
+        RegExpCachedResult m_cachedResult;
+        bool m_multiline;
+        Vector<int, 32> m_ovector;
     };
 
     RegExpConstructor* asRegExpConstructor(JSValue);
 
-    JSObject* constructRegExp(ExecState*, const ArgList&);
+    JSObject* constructRegExp(ExecState*, JSGlobalObject*, const ArgList&, bool callAsConstructor = false);
 
     inline RegExpConstructor* asRegExpConstructor(JSValue value)
     {
-        ASSERT(asObject(value)->inherits(&RegExpConstructor::info));
+        ASSERT(asObject(value)->inherits(&RegExpConstructor::s_info));
         return static_cast<RegExpConstructor*>(asObject(value));
     }
 
+    /* 
+      To facilitate result caching, exec(), test(), match(), search(), and replace() dipatch regular
+      expression matching through the performMatch function. We use cached results to calculate, 
+      e.g., RegExp.lastMatch and RegExp.leftParen.
+    */
+    ALWAYS_INLINE MatchResult RegExpConstructor::performMatch(JSGlobalData& globalData, RegExp* regExp, JSString* string, const UString& input, int startOffset, int** ovector)
+    {
+        int position = regExp->match(globalData, input, startOffset, m_ovector);
+
+        if (ovector)
+            *ovector = m_ovector.data();
+
+        if (position == -1)
+            return MatchResult::failed();
+
+        ASSERT(!m_ovector.isEmpty());
+        ASSERT(m_ovector[0] == position);
+        ASSERT(m_ovector[1] >= position);
+        size_t end = m_ovector[1];
+
+        m_cachedResult.record(globalData, this, regExp, string, MatchResult(position, end));
+
+        return MatchResult(position, end);
+    }
+    ALWAYS_INLINE MatchResult RegExpConstructor::performMatch(JSGlobalData& globalData, RegExp* regExp, JSString* string, const UString& input, int startOffset)
+    {
+        MatchResult result = regExp->match(globalData, input, startOffset);
+        if (result)
+            m_cachedResult.record(globalData, this, regExp, string, result);
+        return result;
+    }
+
 } // namespace JSC
 
 #endif // RegExpConstructor_h