Bug 120108

Summary: method compile for regexp class doesn't exist in KJS
Product: [Applications] konqueror Reporter: Sergio Cambra <sergio>
Component: kjsAssignee: Konqueror Developers <konq-bugs>
Status: RESOLVED FIXED    
Severity: normal CC: maksim, paranoid_
Priority: NOR    
Version: unspecified   
Target Milestone: ---   
Platform: Ubuntu   
OS: Linux   
Latest Commit: Version Fixed In:
Sentry Crash Report:

Description Sergio Cambra 2006-01-14 16:41:06 UTC
Version:            (using KDE KDE 3.5.0)
Installed from:    Ubuntu Packages

In www.noxtrum.com, when you do five searchs you can send a SMS, but they have a javascript code which use the method compile and it doesn't exist in KJS, so I can't use that service with konqueror.

The link to send a SMS (enviar un sms gratis) is in a left box which is shown when you change the konqueror identification to firefox. The javascript code is in http://www.noxtrum.com/javascript/aspects.sms.js
Comment 1 Maksim Orlovich 2006-02-22 14:26:39 UTC
*** Bug 122469 has been marked as a duplicate of this bug. ***
Comment 2 Maksim Orlovich 2006-02-27 00:32:36 UTC
SVN commit 513944 by orlovich:

- Support .compile on regexpen  (#120108)
- Error out if flags are invalid
- Don't leak RegExp objects on errors.
Reviewed by Harri
BUG: 120108


 M  +75 -28    regexp_object.cpp  
 M  +9 -2      regexp_object.h  


--- branches/KDE/3.5/kdelibs/kjs/regexp_object.cpp #513943:513944
@@ -59,6 +59,9 @@
 	    new RegExpProtoFuncImp(exec,funcProto,RegExpProtoFuncImp::Test,     0, testPropertyName), DontEnum);
   putDirect(toStringPropertyName,
 	    new RegExpProtoFuncImp(exec,funcProto,RegExpProtoFuncImp::ToString, 0, toStringPropertyName), DontEnum);
+  static const Identifier compilePropertyName("compile");
+  putDirect(compilePropertyName,
+            new RegExpProtoFuncImp(exec,funcProto,RegExpProtoFuncImp::Compile,  1, compilePropertyName), DontEnum);
 }
 
 // ------------------------------ RegExpProtoFuncImp ---------------------------
@@ -152,7 +155,15 @@
       str += "m";
     }
     return String(str);
+  case Compile: {
+      RegExp* newEngine = RegExpObjectImp::makeEngine(exec, args[0].toString(exec), args[1]);
+      if (!newEngine)
+        return exec->exception();
+      reimp->setRegExp(newEngine);
+      return Value(reimp);
+    }
   }
+  
 
   return Undefined();
 }
@@ -171,6 +182,23 @@
   delete reg;
 }
 
+void RegExpImp::setRegExp(RegExp *r)
+{
+  delete reg;
+  reg = r;
+
+  Object protect(this);//Protect self from GC (we are allocating a StringImp, and may be new)
+  putDirect("global", (r->flags() & RegExp::Global) ? BooleanImp::staticTrue : BooleanImp::staticFalse, 
+            DontDelete | ReadOnly | DontEnum);
+  putDirect("ignoreCase", (r->flags() & RegExp::IgnoreCase) ? BooleanImp::staticTrue : BooleanImp::staticFalse, 
+            DontDelete | ReadOnly | DontEnum);
+  putDirect("multiline", (r->flags() & RegExp::Multiline) ? BooleanImp::staticTrue : BooleanImp::staticFalse, 
+            DontDelete | ReadOnly | DontEnum);
+
+  putDirect("source", new StringImp(r->pattern()), DontDelete | ReadOnly | DontEnum);
+  putDirect("lastIndex", NumberImp::zero(), DontDelete | DontEnum);
+}
+
 // ------------------------------ RegExpObjectImp ------------------------------
 
 RegExpObjectImp::RegExpObjectImp(ExecState * /*exec*/,
@@ -243,6 +271,49 @@
   return true;
 }
 
+RegExp* RegExpObjectImp::makeEngine(ExecState *exec, const UString &p, const Value &flagsInput)
+{
+  UString flags = flagsInput.type() == UndefinedType ? UString("") : flagsInput.toString(exec);
+
+  // Check for validity of flags
+  for (int pos = 0; pos < flags.size(); ++pos) {
+    switch (flags[pos].unicode()) {
+    case 'g':
+    case 'i':
+    case 'm':
+      break;
+    default: {
+        Object err = Error::create(exec, SyntaxError,
+                    "Invalid regular expression flags");
+        exec->setException(err);
+        return 0;
+      }
+    }
+  }
+
+  bool global = (flags.find("g") >= 0);
+  bool ignoreCase = (flags.find("i") >= 0);
+  bool multiline = (flags.find("m") >= 0);
+
+  int reflags = RegExp::None;
+  if (global)
+      reflags |= RegExp::Global;
+  if (ignoreCase)
+      reflags |= RegExp::IgnoreCase;
+  if (multiline)
+      reflags |= RegExp::Multiline;
+
+  RegExp *re = new RegExp(p, reflags);
+  if (!re->isValid()) {
+    Object err = Error::create(exec, SyntaxError,
+                               "Invalid regular expression");
+    exec->setException(err);
+    delete re;
+    return 0;
+  }
+  return re;
+}
+
 // ECMA 15.10.4
 Object RegExpObjectImp::construct(ExecState *exec, const List &args)
 {
@@ -264,38 +335,14 @@
       p = a0.toString(exec);
     }
   }
-  UString flags = args[1].type() == UndefinedType ? UString("") : args[1].toString(exec);
 
+  RegExp* re = makeEngine(exec, p, args[1]);
+  if (!re)
+    return exec->exception().toObject(exec);
+
   RegExpPrototypeImp *proto = static_cast<RegExpPrototypeImp*>(exec->lexicalInterpreter()->builtinRegExpPrototype().imp());
   RegExpImp *dat = new RegExpImp(proto);
   Object obj(dat); // protect from GC
-
-  bool global = (flags.find("g") >= 0);
-  bool ignoreCase = (flags.find("i") >= 0);
-  bool multiline = (flags.find("m") >= 0);
-  // TODO: throw a syntax error on invalid flags
-
-  dat->putDirect("global", global ? BooleanImp::staticTrue : BooleanImp::staticFalse, DontDelete | ReadOnly | DontEnum);
-  dat->putDirect("ignoreCase", ignoreCase ? BooleanImp::staticTrue : BooleanImp::staticFalse, DontDelete | ReadOnly | DontEnum);
-  dat->putDirect("multiline", multiline ? BooleanImp::staticTrue : BooleanImp::staticFalse, DontDelete | ReadOnly | DontEnum);
-
-  dat->putDirect("source", new StringImp(p), DontDelete | ReadOnly | DontEnum);
-  dat->putDirect("lastIndex", NumberImp::zero(), DontDelete | DontEnum);
-
-  int reflags = RegExp::None;
-  if (global)
-      reflags |= RegExp::Global;
-  if (ignoreCase)
-      reflags |= RegExp::IgnoreCase;
-  if (multiline)
-      reflags |= RegExp::Multiline;
-  RegExp *re = new RegExp(p, reflags);
-  if (!re->isValid()) {
-    Object err = Error::create(exec, SyntaxError,
-                               "Invalid regular expression");
-    exec->setException(err);
-    return err;
-  }
   dat->setRegExp(re);
 
   return obj;
--- branches/KDE/3.5/kdelibs/kjs/regexp_object.h #513943:513944
@@ -45,7 +45,7 @@
     virtual bool implementsCall() const;
     virtual Value call(ExecState *exec, Object &thisObj, const List &args);
 
-    enum { Exec, Test, ToString };
+    enum { Exec, Test, ToString, Compile };
   private:
     int id;
   };
@@ -54,7 +54,7 @@
   public:
     RegExpImp(RegExpPrototypeImp *regexpProto);
     ~RegExpImp();
-    void setRegExp(RegExp *r) { reg = r; }
+    void setRegExp(RegExp *r);
     RegExp* regExp() { return reg; }
 
     virtual const ClassInfo *classInfo() const { return &info; }
@@ -78,6 +78,13 @@
     int ** registerRegexp( const RegExp* re, const UString& s );
     void setSubPatterns(int num) { lastNrSubPatterns = num; }
     Object arrayOfMatches(ExecState *exec, const UString &result) const;
+
+    /*
+     Attempts to create a new regular expression engine for the string p
+     and the flags stored in flagsInput. If this succeeds, it returns the 
+     engine. If not, it returns 0, and raises an exception in exec
+    */
+    static RegExp* makeEngine(ExecState *exec, const UString &p, const Value &flagsInput);
   private:
     UString lastString;
     int *lastOvector;
Comment 3 Maksim Orlovich 2006-02-27 00:34:16 UTC
SVN commit 513946 by orlovich:

Testcase for #120108. And now back to grading..
CCBUG:120108


 A             baseline/js/regexp-compile.html-dom  
 AM            baseline/js/regexp-compile.html-dump.png  
 A             baseline/js/regexp-compile.html-render  
 A             tests/js/regexp-compile.html  


** trunk/tests/khtmltests/regression/baseline/js/regexp-compile.html-dump.png #property svn:mime-type
   + application/octet-stream