2005-07-17 Florian Gross <flgr@ccan.de>
authorCésar Natarén <cesar@mono-cvs.ximian.com>
Sun, 24 Jul 2005 00:50:44 +0000 (00:50 -0000)
committerCésar Natarén <cesar@mono-cvs.ximian.com>
Sun, 24 Jul 2005 00:50:44 +0000 (00:50 -0000)
* DateConstructor.cs: Implemented UTC
* ScriptObject.cs: Implemented GetMethod, CallMethod
* JSObject.cs: Implemented fallback ToString, more ClassName cases and
fallback GetDefaultValue
* ArrayPrototype.cs: Fixed concat, join and added splice
* RegExpPrototype.cs: Implemented compile, exec, test
* expression.cs: Emit JS undef instead of JS null for missing args
* StringPrototype.cs: changed lastIndexOf to be compatible with JSC.
Implemented match, replace (no replacement closure), search, split.
No longer uses assert_type for ensuring right type of thisObj
* ArrayObject.cs: Better length argument handling in constructor. Added
SpliceSlowly
* DatePrototype.cs: Added setDate, setFullYear, setHours, setMinutes,
setMilliseconds, setMonth, setSeconds, setTime, setUTCDate,
setUTCFullYear, setUTCHours, setUTCMinutes, setUTCMilliseconds,
setUTCMonth, setUTCSeconds, setYear
* FunctionObject.cs: Moved MethodAttributes to ScriptFunction. Added
MethodInfo-taking constructor
* Convert.cs: Added IsNumber, IsString, ToRegExp. More cases in
ToNumber. Refactored ToString
* ScriptEquality.cs: More cases
* LateBindings.cs: Big refactoring. Introduced assemble_args. Handles
missing arguments. build_args can pass null as engine. More CallValue,
GetNonMissingValue cases
* Plus.cs: Heavily refactored EvaluatePlus from 90 to 12 lines
* GlobalObject.cs: Added CollectGarbage
* NumberPrototype.cs: No longer uses assert_type for unsuring right
type of thisObj
* RegExpObject: Added lastIndex, Initialize, stores compiled Regex
* SemanticAnalizer: Added missing prototypes. Made assert_type work
with derived types
* ScriptFunction.cs: Moved MethodAttributes from FunctionObject. Added
MethodInfo. Implemented Invoke for built-in functions.

svn path=/trunk/mcs/; revision=47598

28 files changed:
mcs/class/Microsoft.JScript/Microsoft.JScript/ArrayConstructor.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/ArrayObject.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/ArrayPrototype.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/ChangeLog
mcs/class/Microsoft.JScript/Microsoft.JScript/Convert.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/DateConstructor.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/DatePrototype.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/ErrorConstructor.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/FunctionConstructor.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/FunctionDeclaration.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/FunctionObject.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/GlobalObject.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/JSFunctionAttributeEnum.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/JSObject.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/JScriptException.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/LateBinding.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/NumberPrototype.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/Plus.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/PostOrPrefixOperator.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/RegExpObject.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/RegExpPrototype.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/ScriptFunction.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/ScriptObject.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/SemanticAnalizer.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/StrictEquality.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/StringPrototype.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/TypeOf.cs
mcs/class/Microsoft.JScript/Microsoft.JScript/expression.cs

index f1821b154259f52338e2bd32b73d5cad79d0cbf5..90f1d79db257b5af403e2725403db2eb3725a664 100644 (file)
@@ -61,7 +61,7 @@ namespace Microsoft.JScript {
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasVarArgs)]
                public ArrayObject Invoke (params Object [] args)
                {
-                       return (ArrayObject) GetMethod ("CreateInstance", BindingFlags.Static | BindingFlags.Public).Invoke (null, args);
+                       return CreateInstance (args);
                }
        }
 }
index d4870163df5553bf65865288fd563ee5b46e7868..302f71016e1ae3254b0ef39f8b98f59ad27904e9 100644 (file)
@@ -50,10 +50,10 @@ namespace Microsoft.JScript {
                internal ArrayObject (object o)
                {
                        IConvertible ic = o as IConvertible;
-                       TypeCode tc = ic.GetTypeCode ();
+                       TypeCode tc = Convert.GetTypeCode (o, ic);
 
                        try {
-                               if (tc == TypeCode.Int32 || ic.ToDouble (null) < Int32.MaxValue) {
+                               if (Convert.IsNumberTypeCode (tc)) {
                                        int size = ic.ToInt32 (null);
                                        if (size > 0) {
                                                length = o;
@@ -90,7 +90,7 @@ namespace Microsoft.JScript {
 
                protected void SpliceSlowly (uint start, uint deleteCount, object [] args, ArrayObject outArray, uint oldLength, uint newLength)
                {
-                       throw new NotImplementedException ();
+                       ArrayPrototype.splice (outArray, null, start, deleteCount, args);
                }
 
                internal override object GetDefaultValue (Type hint)
index e0a5f0a583b9ba4f81afe30f9f9292991adaad4d..08760d648751477c53fba4c05f396d0dc9d7df43 100644 (file)
@@ -38,7 +38,8 @@ namespace Microsoft.JScript {
 
        public class ArrayPrototype : ArrayObject {
                
-               [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject | JSFunctionAttributeEnum.HasVarArgs | JSFunctionAttributeEnum.HasEngine, JSBuiltin.Array_concat)]
+               [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject | JSFunctionAttributeEnum.HasEngine |
+                       JSFunctionAttributeEnum.HasVarArgs, JSBuiltin.Array_concat)]
                public static ArrayObject concat (object thisObj, VsaEngine engine,
                                                  params object [] args)
                {
@@ -52,18 +53,22 @@ namespace Microsoft.JScript {
                        object cur_obj = thisObj;
 
                        ArrayObject cur_ary;
-                       while (arg_idx < arg_count) {
+                       while (cur_obj != null) {
                                if (cur_obj is ArrayObject) {
                                        cur_ary = (ArrayObject) cur_obj;
 
                                        int n = (int) cur_ary.length;
                                        for (int j = 0; j < n; j++, i++)
-                                               result [i] = cur_ary [j];
-
-                                       cur_obj = args [arg_idx++];
+                                               result.elems [i] = cur_ary.elems [j];
                                } else
-                                       result [++i] = cur_obj;
+                                       result.elems [i++] = cur_obj;
+
+                               arg_idx++;
+                               cur_obj = arg_idx < arg_count ? args [arg_idx] : null;
                        }
+
+                       result.length = i;
+
                        return result;
                }
 
@@ -84,15 +89,18 @@ namespace Microsoft.JScript {
                        else
                                _separator = Convert.ToString (separator);
 
-                       Hashtable elems = array_obj.Elements;
+                       Hashtable elems = array_obj.elems;
+                       int n = (int) array_obj.length;
                        StringBuilder str = new StringBuilder ();
                        bool first = true;
 
-                       foreach (DictionaryEntry entry in elems) {
+                       for (int i = 0; i < n; i++) {
                                if (!first)
                                        str.Append (_separator);
                                first = false;
-                               str.Append (Convert.ToString (entry.Value));
+                               object elem = elems [i];
+                               if (elem != null)
+                                       str.Append (Convert.ToString (elem));
                        }
                        return str.ToString ();
                }
@@ -201,7 +209,7 @@ namespace Microsoft.JScript {
                        if (end == null)
                                _end = array_len;
                        else {
-                               _end = (int) (double) end;
+                               _end = Convert.ToInt32 (end);
 
                                if (_end < 0)
                                        _end += array_len;
@@ -232,7 +240,76 @@ namespace Microsoft.JScript {
                                                  double start, double deleteCnt, 
                                                  params object [] args)
                {
-                       throw new NotImplementedException ();
+                       // TODO: Shouldn't this be generic!?
+                       SemanticAnalyser.assert_type (thisObj, typeof (ArrayObject));
+                       ArrayObject array_obj = (ArrayObject) thisObj;
+                       ArrayObject result = new ArrayObject ();
+                       Hashtable elems = array_obj.elems;
+                       Hashtable del_elems = result.elems;
+
+                       int old_length = (int) array_obj.length;
+                       start = (int) start;
+                       if (start < 0)
+                               start = Math.Max (start + old_length, 0);
+                       else
+                               start = Math.Min (old_length, start);
+
+                       deleteCnt = (int) deleteCnt;
+                       deleteCnt = Math.Min (Math.Max (deleteCnt, 0), old_length - start);
+
+                       int arg_length = args.Length;
+                       int add_length = arg_length - (int) deleteCnt;
+                       add_length = Math.Max (add_length, -old_length);
+                       int del_length = -add_length;
+                       int new_length = old_length + add_length;
+
+                       int i, j, m;
+                       // First let's make some free space for the new items (if needed)
+                       if (add_length > 0) {
+                               i = old_length - 1;
+                               j = i + add_length;
+                               for (; i >= start; i--, j--)
+                                       elems [j] = elems [i];
+                       }
+
+                       // Then insert the new items in the now free space / replace existing ones
+                       j = m = 0;
+                       int old_start = (int) start + add_length;
+                       for (i = (int) start; j < arg_length; i++, j++) {
+                               if (i >= old_start && elems.ContainsKey (i)) {
+                                       del_elems [m] = elems [i];
+                                       m++;
+                                       elems.Remove (i);
+                               }
+
+                               if (j < arg_length)
+                                       elems [i] = args [j];
+                       }
+
+                       // Finally, delete elements which have no replacement elements
+                       if (add_length < 0) {
+                               int last_elem_idx = i + del_length;
+                               for (int k = 0; k < del_length; i++, j++, k++) {
+                                       if (elems.ContainsKey (i)) {
+                                               del_elems [m] = elems [i];
+                                               m++;
+                                               elems.Remove (i);
+                                       }
+                               }
+
+                               // And move up trailing elements
+                               int l = last_elem_idx - del_length;
+                               for (int k = last_elem_idx; l < old_length; k++, l++) {
+                                       if (elems.ContainsKey (k))
+                                               elems [l] = elems [k];
+                                       else if (elems.ContainsKey (l))
+                                               elems.Remove (l);
+                               }
+                       }
+
+                       array_obj.length = new_length;
+                       result.length = (int) deleteCnt;
+                       return result;
                }
 
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Array_toLocaleString)]
index 500f720ffe6b10cc9968ae8756585d8f07c49611..9d95f28aeaed776e64994905d5df058cf197524e 100644 (file)
@@ -1,3 +1,38 @@
+2005-07-17  Florian Gross  <flgr@ccan.de>
+       * DateConstructor.cs: Implemented UTC
+       * ScriptObject.cs: Implemented GetMethod, CallMethod
+       * JSObject.cs: Implemented fallback ToString, more ClassName cases and
+       fallback GetDefaultValue
+       * ArrayPrototype.cs: Fixed concat, join and added splice
+       * RegExpPrototype.cs: Implemented compile, exec, test
+       * expression.cs: Emit JS undef instead of JS null for missing args
+       * StringPrototype.cs: changed lastIndexOf to be compatible with JSC.
+       Implemented match, replace (no replacement closure), search, split.
+       No longer uses assert_type for ensuring right type of thisObj
+       * ArrayObject.cs: Better length argument handling in constructor. Added
+       SpliceSlowly
+       * DatePrototype.cs: Added setDate, setFullYear, setHours, setMinutes,
+       setMilliseconds, setMonth, setSeconds, setTime, setUTCDate,
+       setUTCFullYear, setUTCHours, setUTCMinutes, setUTCMilliseconds,
+       setUTCMonth, setUTCSeconds, setYear
+       * FunctionObject.cs: Moved MethodAttributes to ScriptFunction. Added
+       MethodInfo-taking constructor
+       * Convert.cs: Added IsNumber, IsString, ToRegExp. More cases in
+       ToNumber. Refactored ToString
+       * ScriptEquality.cs: More cases
+       * LateBindings.cs: Big refactoring. Introduced assemble_args. Handles
+       missing arguments. build_args can pass null as engine. More CallValue,
+       GetNonMissingValue cases
+       * Plus.cs: Heavily refactored EvaluatePlus from 90 to 12 lines
+       * GlobalObject.cs: Added CollectGarbage
+       * NumberPrototype.cs: No longer uses assert_type for unsuring right
+       type of thisObj
+       * RegExpObject: Added lastIndex, Initialize, stores compiled Regex
+       * SemanticAnalizer: Added missing prototypes. Made assert_type work
+       with derived types
+       * ScriptFunction.cs: Moved MethodAttributes from FunctionObject. Added
+       MethodInfo. Implemented Invoke for built-in functions.
+
 2005-07-07  Florian Gross  <flgr@ccan.de>
 
        * MathObject.cs: Implemented max and min (untested)
index fc9da06b539cd2e01350a7f1530689e8e348b569..478b92d67f27c2baa59f38a74db457388612b9a4 100644 (file)
@@ -43,6 +43,50 @@ namespace Microsoft.JScript {
                        throw new NotImplementedException ();
                }
 
+               internal static bool IsNumber (object value)
+               {
+                       IConvertible ic = value as IConvertible;
+                       TypeCode tc = Convert.GetTypeCode (value, ic);
+
+                       switch (tc) {
+                       case TypeCode.Char:
+                       case TypeCode.Byte:
+                       case TypeCode.SByte:
+                       case TypeCode.UInt16:
+                       case TypeCode.UInt32:
+                       case TypeCode.Int16:
+                       case TypeCode.Int32:
+                       case TypeCode.Single:
+                       case TypeCode.Double:
+                               return true;
+
+                       case TypeCode.Object:
+                               if (value is NumberObject)
+                                       return true;
+                               break;
+                       }
+
+                       return false;
+               }
+
+               internal static bool IsString (object value)
+               {
+                       IConvertible ic = value as IConvertible;
+                       TypeCode tc = Convert.GetTypeCode (value, ic);
+
+                       switch (tc) {
+                       case TypeCode.String:
+                               return true;
+
+                       case TypeCode.Object:
+                               if (value is StringObject)
+                                       return true;
+                               break;
+                       }
+
+                       return false;
+               }
+
                internal static bool IsNumberTypeCode (TypeCode tc)
                {
                        switch (tc) {
@@ -190,7 +234,6 @@ namespace Microsoft.JScript {
                        throw new NotImplementedException ();
                }
 
-
                public static int ToInt32 (object value)
                {
                        IConvertible ic = value as IConvertible;
@@ -257,7 +300,7 @@ namespace Microsoft.JScript {
                        case TypeCode.UInt32:
                        case TypeCode.Int16:
                        case TypeCode.Int32:
-                               return (double) value;
+                               return ic.ToDouble (null);
 
                        case TypeCode.Single:
                        case TypeCode.Double:
@@ -266,11 +309,13 @@ namespace Microsoft.JScript {
                        case TypeCode.String:
                                return GlobalObject.parseFloat (value);
 
-                       default:
-                               Console.WriteLine ("\nToNumber: value.GetType = {0}", value.GetType ());
+                       case TypeCode.Object:
+                               if (value is NumberObject)
+                                       return ((NumberObject) value).value;
                                break;
                        }
 
+                       Console.WriteLine ("\nToNumber: value.GetType = {0}", value.GetType ());
                        throw new NotImplementedException ();
                }
 
@@ -335,7 +380,7 @@ namespace Microsoft.JScript {
 
                        switch (tc) {
                        case TypeCode.Empty:
-                               return "";
+                               return "undefined";
 
                        case TypeCode.DBNull:
                                return "null";
@@ -350,46 +395,38 @@ namespace Microsoft.JScript {
                        case TypeCode.Char:
                                return ic.ToInt16 (null).ToString ();
 
-                       case TypeCode.Byte:
-                       case TypeCode.SByte:
-                       case TypeCode.UInt16:
-                       case TypeCode.UInt32:
-                       case TypeCode.Int16:
-                       case TypeCode.Int32:
                        case TypeCode.String:
-                       case TypeCode.Double:
-                               return ic.ToString (CultureInfo.InvariantCulture);
+                               return ic.ToString (null);
 
                        case TypeCode.Object:
-                               if (value is ArrayObject)
-                                       return ArrayPrototype.toString (value);
-                               else if (value is BooleanObject)
-                                       return BooleanPrototype.toString (value);
-                               else if (value is DateObject)
-                                       return DatePrototype.toString (value);
-                               else if (value is ErrorObject)
-                                       return ErrorPrototype.toString (value);
-                               else if (value is FunctionObject)
-                                       return FunctionPrototype.toString (value);
-                               else if (value is NumberObject)
-                                       return NumberPrototype.toString (value, 10);
-                               else if (value is ObjectPrototype)
-                                       return ObjectPrototype.toString (value);
-                               else if (value is RegExpObject)
-                                       return RegExpPrototype.toString (value);
-                               else if (value is StringObject)
-                                       return StringPrototype.toString (value);
-                               else if (value is FunctionWrapper)
-                                       return FunctionPrototype.toString (value);
+                               if (value is StringObject)
+                                       return ((StringObject) value).value;
+                               else if (value is Closure)
+                                       return FunctionPrototype.toString (((Closure) value).func);
+                               else if (value is ScriptObject)
+                                       return (string) ((ScriptObject) value).CallMethod ("toString");
+
                                Console.WriteLine ("value.GetType = {0}", value.GetType ());
                                throw new NotImplementedException ();
+
                        default:
+                               if (IsNumberTypeCode (tc))
+                                       return ic.ToString (CultureInfo.InvariantCulture);
+
                                Console.WriteLine ("tc = {0}", tc);
                                throw new NotImplementedException ();
                        }
                }
 
 
+               internal static RegExpObject ToRegExp (object regExp)
+               {
+                       if (regExp is RegExpObject)
+                               return (RegExpObject) regExp;
+                       else
+                               return RegExpConstructor.Ctr.Invoke (regExp);
+               }
+
                public static string ToString (bool b)
                {
                        return b ? "true" : "false";
index ff43db794ff2e2de0a7efafcd524006eee90b25b..0e74cf6ff372c29003e0d8c17a0780c7cf98c6e2 100644 (file)
@@ -368,7 +368,7 @@ done:
                //
                // find UTC time from given date... no 1900 correction!
                //
-               static double msec_from_date (double year, double mon, double mday, double hour, double min, double sec, double msec)
+               internal static double msec_from_date (double year, double mon, double mday, double hour, double min, double sec, double msec)
                {
                        double day, time, result;
                        day = MakeDay (year, mon, mday);
@@ -377,7 +377,7 @@ done:
                        return result;
                }
 
-               static double MakeDay (double year, double month, double date)
+               internal static double MakeDay (double year, double month, double date)
                {
                        year += Math.Floor (month / 12);
                        month = month % 12;
@@ -390,27 +390,27 @@ done:
                        return year_day + month_day + date - 1;
                }
 
-               static double MakeTime (double hour, double min, double sec, double ms)
+               internal static double MakeTime (double hour, double min, double sec, double ms)
                {
                        return ((hour * MINUTES_PER_HOUR + min) * SECONDS_PER_MINUTE + sec) * MS_PER_SECOND + ms;
                }
 
-               static double MakeDate (double day, double time)
+               internal static double MakeDate (double day, double time)
                {
                        return day * MS_PER_DAY + time;
                }
 
-               static double TimeFromYear (double y)
+               internal static double TimeFromYear (double y)
                {
                        return DayFromYear (y) * MS_PER_DAY;
                }
 
-               static double DayFromYear (double y)
+               internal static double DayFromYear (double y)
                {
                        return ((365 * ((y) - 1970) + Math.Floor (((y) - 1969) / 4.0) - Math.Floor(((y) - 1901) / 100.0) + Math.Floor (((y) - 1601) / 400.0)));
                }
 
-               static double DayFromMonth (int m , int year)
+               internal static double DayFromMonth (int m, int year)
                {
                        int day = m * 30;
 
@@ -427,7 +427,7 @@ done:
                        return day;
                }
 
-               static bool IsLeapYear (int year)
+               internal static bool IsLeapYear (int year)
                {
                        return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
                }
@@ -436,7 +436,48 @@ done:
                public static double UTC (Object year, Object month, Object date, 
                                          Object hours, Object minutes, Object seconds, Object ms)
                {
-                       throw new NotImplementedException ();
+                       double _year = 0, _month = 0, _date = 1, _hours = 0, _minutes = 0, _seconds = 0, _ms = 0;
+
+                       if (year == null && month == null) {
+                               DateTime now = DateTime.Now;
+                               _year = now.Year;
+                               _month = now.Month - 1;
+                               _date = now.Day;
+                               _hours = now.Hour;
+                               _minutes = now.Minute;
+                               _seconds = now.Second;
+                               _ms = now.Millisecond;
+                               _ms -= TimeZone.CurrentTimeZone.GetUtcOffset (now).TotalMilliseconds;
+                               goto done;
+                       }
+
+                       _year = Convert.ToNumber (year);
+                       if (month != null)
+                               _month = Convert.ToNumber (month);
+                       if (date != null)
+                               _date = Convert.ToNumber (date);
+                       if (hours != null)
+                               _hours = Convert.ToNumber (hours);
+                       if (minutes != null)
+                               _minutes = Convert.ToNumber (minutes);
+                       if (seconds != null)
+                               _seconds = Convert.ToNumber (seconds);
+                       if (ms != null)
+                               _ms = Convert.ToNumber (ms);
+
+                       if (!Double.IsNaN (_year) && _year >= 0 && _year <= 99)
+                               _year += 1900;
+
+done:
+                       return TimeClip (msec_from_date (_year, _month, _date, _hours, _minutes, _seconds, _ms));
+               }
+
+               internal static double TimeClip (double p)
+               {
+                       if (Double.IsInfinity (p) || Double.IsNaN (p) || Math.Abs (p) > 8.64e15)
+                               return Double.NaN;
+                       else
+                               return p;
                }
 
                /* Ported from Rhino. */
@@ -666,5 +707,17 @@ done:
                        DateTime dt = new DateTime (year, month + 1, date, hours, minutes, seconds);
                        return t + TimeZone.CurrentTimeZone.GetUtcOffset (dt).TotalMilliseconds;
                }
+
+               internal static double ToUTC (double t)
+               {
+                       int year = YearFromTime (t);
+                       int month = MonthFromTime (t);
+                       int date = DateFromTime (t);
+                       int hours = HourFromTime (t);
+                       int minutes = MinFromTime (t);
+                       int seconds = SecFromTime (t);
+                       DateTime dt = new DateTime (year, month + 1, date, hours, minutes, seconds);
+                       return t - TimeZone.CurrentTimeZone.GetUtcOffset (dt).TotalMilliseconds;
+               }
        }
 }
index 8acbd6e5ff76c4ca40065faccb042ebea24e1e8c..3fac0d43ca496d44fdd644ebf671add25251a6ca 100644 (file)
@@ -318,104 +318,331 @@ namespace Microsoft.JScript {
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_setDate)]
                public static double setDate (object thisObj, double ddate)
                {
-                       throw new NotImplementedException ();
+                       SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
+                       DateObject date = (DateObject) thisObj;
+                       double t = DateConstructor.LocalTime (date.ms);
+                       double day = DateConstructor.MakeDay ((double) DateConstructor.YearFromTime (t),
+                               (double) DateConstructor.MonthFromTime (t), ddate);
+                       double new_val = DateConstructor.ToUTC (DateConstructor.MakeDate (day, t % DateConstructor.MS_PER_DAY));
+                       date.ms = DateConstructor.TimeClip (new_val);
+                       return date.ms;
                }
 
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_setFullYear)]
                public static double setFullYear (object thisObj, double dyear,
                                                  object month, object date)
                {
-                       throw new NotImplementedException ();
+                       SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
+                       DateObject dt = (DateObject) thisObj;
+                       double t = DateConstructor.LocalTime (dt.ms);
+                       if (Double.IsNaN (t))
+                               t = 0;
+
+                       double new_month;
+                       if (month == null)
+                               new_month = DateConstructor.MonthFromTime (t);
+                       else
+                               new_month = Convert.ToNumber (month);
+
+                       double new_date;
+                       if (date == null)
+                               new_date = DateConstructor.DateFromTime (t);
+                       else
+                               new_date = Convert.ToNumber (date);
+
+                       double day = DateConstructor.MakeDay (dyear, new_month, new_date);
+                       double new_val = DateConstructor.ToUTC (DateConstructor.MakeDate (day, t % DateConstructor.MS_PER_DAY));
+                       dt.ms = DateConstructor.TimeClip (new_val);
+                       return dt.ms;
                }
 
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_setHours)]
                public static double setHours (object thisObj, double dhour, object min,
                                               object sec, object msec)
                {
-                       throw new NotImplementedException ();
+                       SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
+                       DateObject date = (DateObject) thisObj;
+                       double t = DateConstructor.LocalTime (date.ms);
+
+                       double new_min;
+                       if (min == null)
+                               new_min = DateConstructor.MinFromTime (t);
+                       else
+                               new_min = Convert.ToNumber (min);
+
+                       double new_sec;
+                       if (sec == null)
+                               new_sec = DateConstructor.SecFromTime (t);
+                       else
+                               new_sec = Convert.ToNumber (sec);
+
+                       double new_ms;
+                       if (msec == null)
+                               new_ms = DateConstructor.msFromTime (t);
+                       else
+                               new_ms = Convert.ToNumber (msec);
+
+                       double time = DateConstructor.MakeTime (dhour, new_min, new_sec, new_ms);
+                       double day = Math.Floor (t / DateConstructor.MS_PER_DAY);
+                       double new_val = DateConstructor.ToUTC (DateConstructor.MakeDate (day, time));
+                       date.ms = DateConstructor.TimeClip (new_val);
+                       return date.ms;
                }
 
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_setMinutes)]
                public static double setMinutes (object thisObj, double dmin,
                                                 object sec, object msec)
                {
-                       throw new NotImplementedException ();
+                       SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
+                       DateObject date = (DateObject) thisObj;
+                       double t = DateConstructor.LocalTime (date.ms);
+
+                       double new_sec;
+                       if (sec == null)
+                               new_sec = DateConstructor.SecFromTime (t);
+                       else
+                               new_sec = Convert.ToNumber (sec);
+
+                       double new_ms;
+                       if (msec == null)
+                               new_ms = DateConstructor.msFromTime (t);
+                       else
+                               new_ms = Convert.ToNumber (msec);
+
+                       double time = DateConstructor.MakeTime (DateConstructor.HourFromTime (t), dmin, new_sec, new_ms);
+                       double day = Math.Floor (t / DateConstructor.MS_PER_DAY);
+                       double new_val = DateConstructor.ToUTC (DateConstructor.MakeDate (day, time));
+                       date.ms = DateConstructor.TimeClip (new_val);
+                       return date.ms;
                }
 
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_setMilliseconds)]
                public static double setMilliseconds (object thisObj, double dmsec)
                {
-                       throw new NotImplementedException ();
+                       SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
+                       DateObject date = (DateObject) thisObj;
+                       double t = DateConstructor.LocalTime (date.ms);
+                       double time = DateConstructor.MakeTime (DateConstructor.HourFromTime (t), DateConstructor.MinFromTime (t),
+                               DateConstructor.SecFromTime (t), dmsec);
+                       double day = Math.Floor (t / DateConstructor.MS_PER_DAY);
+                       double new_val = DateConstructor.ToUTC (DateConstructor.MakeDate (day, time));
+                       date.ms = DateConstructor.TimeClip (new_val);
+                       return date.ms;
                }
 
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_setMonth)]
                public static double setMonth (object thisObj, double dmonth,
                                               object date)
                {
-                       throw new NotImplementedException ();
+                       SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
+                       DateObject dt = (DateObject) thisObj;
+                       double t = DateConstructor.LocalTime (dt.ms);
+
+                       double new_date;
+                       if (date == null)
+                               new_date = DateConstructor.DateFromTime (t);
+                       else
+                               new_date = Convert.ToNumber (date);
+                       
+                       double day = DateConstructor.MakeDay ((double) DateConstructor.YearFromTime (t),
+                               dmonth, new_date);
+                       double new_val = DateConstructor.ToUTC (DateConstructor.MakeDate (day, t % DateConstructor.MS_PER_DAY));
+                       dt.ms = DateConstructor.TimeClip (new_val);
+                       return dt.ms;
                }
 
-               [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_setSeconds)]
+               [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject,
+                       JSBuiltin.Date_setSeconds)]
                public static double setSeconds (object thisObj, double dsec, object msec)
                {
-                       throw new NotImplementedException ();
+                       SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
+                       DateObject date = (DateObject) thisObj;
+                       double t = DateConstructor.LocalTime (date.ms);
+
+                       double new_ms;
+                       if (msec == null)
+                               new_ms = DateConstructor.msFromTime (t);
+                       else
+                               new_ms = Convert.ToNumber (msec);
+
+                       double time = DateConstructor.MakeTime (DateConstructor.HourFromTime (t), DateConstructor.MinFromTime (t),
+                               dsec, new_ms);
+                       double day = Math.Floor (t / DateConstructor.MS_PER_DAY);
+                       double new_val = DateConstructor.ToUTC (DateConstructor.MakeDate (day, time));
+                       date.ms = DateConstructor.TimeClip (new_val);
+                       return date.ms;
                }
 
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_setTime)]
                public static double setTime (object thisObj, double time)
                {
-                       throw new NotImplementedException ();
+                       SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
+                       DateObject date = (DateObject) thisObj;
+                       date.ms = DateConstructor.TimeClip (time);
+                       return date.ms;
                }
 
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_setUTCDate)]
                public static double setUTCDate (object thisObj, double ddate)
                {
-                       throw new NotImplementedException ();
+                       SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
+                       DateObject date = (DateObject) thisObj;
+                       double t = date.ms;
+                       double day = DateConstructor.MakeDay ((double) DateConstructor.YearFromTime (t),
+                               (double) DateConstructor.MonthFromTime (t), ddate);
+                       double new_val = DateConstructor.MakeDate (day, t % DateConstructor.MS_PER_DAY);
+                       date.ms = DateConstructor.TimeClip (new_val);
+                       return date.ms;
                }
 
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_setUTCFullYear)]
                public static double setUTCFullYear (object thisObj, double dyear,      
                                                     object month, object date)
                {
-                       throw new NotImplementedException ();
+                       SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
+                       DateObject dt = (DateObject) thisObj;
+                       double t = dt.ms;
+                       if (Double.IsNaN (t))
+                               t = 0;
+
+                       double new_month;
+                       if (month == null)
+                               new_month = DateConstructor.MonthFromTime (t);
+                       else
+                               new_month = Convert.ToNumber (month);
+
+                       double new_date;
+                       if (date == null)
+                               new_date = DateConstructor.DateFromTime (t);
+                       else
+                               new_date = Convert.ToNumber (date);
+
+                       double day = DateConstructor.MakeDay (dyear, new_month, new_date);
+                       double new_val = DateConstructor.MakeDate (day, t % DateConstructor.MS_PER_DAY);
+                       dt.ms = DateConstructor.TimeClip (new_val);
+                       return dt.ms;
                }
 
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_setUTCHours)]
                public static double setUTCHours (object thisObj, double dhour,
                                                  object min, object sec, object msec)
                {
-                       throw new NotImplementedException ();
+                       SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
+                       DateObject date = (DateObject) thisObj;
+                       double t = date.ms;
+
+                       double new_min;
+                       if (min == null)
+                               new_min = DateConstructor.MinFromTime (t);
+                       else
+                               new_min = Convert.ToNumber (min);
+
+                       double new_sec;
+                       if (sec == null)
+                               new_sec = DateConstructor.SecFromTime (t);
+                       else
+                               new_sec = Convert.ToNumber (sec);
+
+                       double new_ms;
+                       if (msec == null)
+                               new_ms = DateConstructor.msFromTime (t);
+                       else
+                               new_ms = Convert.ToNumber (msec);
+
+                       double time = DateConstructor.MakeTime (dhour, new_min, new_sec, new_ms);
+                       double day = Math.Floor (t / DateConstructor.MS_PER_DAY);
+                       double new_val = DateConstructor.MakeDate (day, time);
+                       date.ms = DateConstructor.TimeClip (new_val);
+                       return date.ms;
                }
 
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_setUTCMinutes)]
                public static double setUTCMinutes (object thisObj, double dmin,
                                                    object sec, object msec)
                {
-                       throw new NotImplementedException ();
+                       SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
+                       DateObject date = (DateObject) thisObj;
+                       double t = date.ms;
+
+                       double new_sec;
+                       if (sec == null)
+                               new_sec = DateConstructor.SecFromTime (t);
+                       else
+                               new_sec = Convert.ToNumber (sec);
+
+                       double new_ms;
+                       if (msec == null)
+                               new_ms = DateConstructor.msFromTime (t);
+                       else
+                               new_ms = Convert.ToNumber (msec);
+
+                       double time = DateConstructor.MakeTime (DateConstructor.HourFromTime (t), dmin, new_sec, new_ms);
+                       double day = Math.Floor (t / DateConstructor.MS_PER_DAY);
+                       double new_val = DateConstructor.MakeDate (day, time);
+                       date.ms = DateConstructor.TimeClip (new_val);
+                       return date.ms;
                }
 
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_setUTCMilliseconds)]
                public static double setUTCMilliseconds (object thisObj, double msec)
                {
-                       throw new NotImplementedException ();
+                       SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
+                       DateObject date = (DateObject) thisObj;
+                       double t = date.ms;
+                       double time = DateConstructor.MakeTime (DateConstructor.HourFromTime (t), DateConstructor.MinFromTime (t),
+                               DateConstructor.SecFromTime (t), msec);
+                       double day = Math.Floor (t / DateConstructor.MS_PER_DAY);
+                       double new_val = DateConstructor.MakeDate (day, time);
+                       date.ms = DateConstructor.TimeClip (new_val);
+                       return date.ms;
                }
 
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_setUTCMonth)]
                public static double setUTCMonth (object thisObj, double dmonth, object date)
                {
-                       throw new NotImplementedException ();
+                       SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
+                       DateObject dt = (DateObject) thisObj;
+                       double t = dt.ms;
+
+                       double new_date;
+                       if (date == null)
+                               new_date = DateConstructor.DateFromTime (t);
+                       else
+                               new_date = Convert.ToNumber (date);
+
+                       double day = DateConstructor.MakeDay ((double) DateConstructor.YearFromTime (t),
+                               dmonth, new_date);
+                       double new_val = DateConstructor.MakeDate (day, t % DateConstructor.MS_PER_DAY);
+                       dt.ms = DateConstructor.TimeClip (new_val);
+                       return dt.ms;
                }
 
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_setUTCSeconds)]
                public static double setUTCSeconds (object thisObj, double dsec, object msec)
                {
-                       throw new NotImplementedException ();
+                       SemanticAnalyser.assert_type (thisObj, typeof (DateObject));
+                       DateObject date = (DateObject) thisObj;
+                       double t = date.ms;
+
+                       double new_ms;
+                       if (msec == null)
+                               new_ms = DateConstructor.msFromTime (t);
+                       else
+                               new_ms = Convert.ToNumber (msec);
+
+                       double time = DateConstructor.MakeTime (DateConstructor.HourFromTime (t), DateConstructor.MinFromTime (t),
+                               dsec, new_ms);
+                       double day = Math.Floor (t / DateConstructor.MS_PER_DAY);
+                       double new_val = DateConstructor.MakeDate (day, time);
+                       date.ms = DateConstructor.TimeClip (new_val);
+                       return date.ms;
                }
 
+               /* Note: See Note for GetYear() for an explanation why we do not emulate obsolete behavior here. */
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_setYear)]
                public static double setYear (object thisObj, double dyear)
                {
-                       throw new NotImplementedException ();
+                       return setFullYear (thisObj, dyear, null, null);
                }
 
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Date_toDateString)]
index f3caf3fdddc8c3c8089660a0a4fd7f637e58832b..d42a8e4afed43c85a81ebd25fc8c4f7e43c2169d 100644 (file)
@@ -71,7 +71,7 @@ namespace Microsoft.JScript {
                [JSFunctionAttribute(JSFunctionAttributeEnum.HasVarArgs)]
                public Object Invoke (params Object [] args)
                {
-                       return GetMethod ("CreateInstance", BindingFlags.Static | BindingFlags.Public).Invoke (null, args);
+                       return CreateInstance (args);
                }
        }
 }
index 051a9ae0542b43442fdab283424f4d9fbd408b1e..f91d766e2ba6477fb6a5acf82a0aac7e2ae6d2a3 100644 (file)
@@ -49,7 +49,7 @@ namespace Microsoft.JScript {
                [JSFunctionAttribute(JSFunctionAttributeEnum.HasVarArgs)]
                public ScriptFunction Invoke(params Object [] args)
                {
-                       return (ScriptFunction) GetMethod ("CreateInstance", BindingFlags.Static | BindingFlags.Public).Invoke (null, args);
+                       return CreateInstance (args);
                }
        }
 }
index d4e442913ea2e7965a7240b0633fcf24a0caecde..428a49def40b765cf6218dee2b3bd5013b6d8a34 100644 (file)
@@ -74,7 +74,7 @@ namespace Microsoft.JScript {
                                                                  bool hasArgumentsObjects, string text, 
                                                                  Object declaringObject, VsaEngine engine)
                {
-                       FunctionObject f = null;
+                       FunctionObject f = new FunctionObject (name, null, null, null);
                        return new Closure (f);
                }
 
index 2bacb7f613bf3412f720e20c3068f4bb8d01b85d..8fdcb5c2f9342f9d1503f5b2483c4a4ffc4d8bf7 100644 (file)
@@ -37,7 +37,6 @@ namespace Microsoft.JScript {
 
        public class FunctionObject : ScriptFunction {
 
-               internal MethodAttributes attr;
                internal string name;
                internal string type_annot;
                internal Type return_type;
@@ -49,6 +48,14 @@ namespace Microsoft.JScript {
                        this.name = name;
                }
 
+               internal FunctionObject (MethodInfo info)
+               {
+                       this.method = info;
+                       this.name = info.Name;
+                       this.attr = info.Attributes;
+                       this.return_type = info.ReturnType;
+               }
+
                internal FunctionObject (string name, FormalParameterList p, string ret_type, Block body)
                {
                        //
index 86c7b440b63d2512e636160152e617e508f86e31..3cc743d997b6d6affba3481a4d5c556e80d39312 100644 (file)
@@ -87,7 +87,7 @@ namespace Microsoft.JScript {
                [JSFunctionAttribute (0, JSBuiltin.Global_CollectGarbage)]
                public static void CollectGarbage ()
                {
-                       throw new NotImplementedException ();
+                       GC.Collect ();
                }
 
                public static DateConstructor Date {
@@ -100,7 +100,7 @@ namespace Microsoft.JScript {
 
                
                //
-               // ECMA 3, 15.1.3 URI hnadling Function Properties
+               // ECMA 3, 15.1.3 URI handling Function Properties
                //
                // The following are implementations of the algorithms
                // given in the ECMA specification for the hidden functions
index 901f4c116078b3d69c7543b170246a8bf5828abe..1e0e5511b7c76860d24f3428af4a221f9bf11d14 100644 (file)
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-namespace Microsoft.JScript {
+using System;
 
+namespace Microsoft.JScript {
+               [FlagsAttribute]
                public enum JSFunctionAttributeEnum {
                        HasArguments    = 0x01,
                        HasThisObject   = 0x02,
index 720a06421090c97609437ff8296cfde8d25bfa17..bf16b9abba133bb55f8f16194e2393b086205df8 100644 (file)
@@ -52,9 +52,7 @@ namespace Microsoft.JScript {
                internal JSFieldInfo GetField (string name)
                {
                        object res = elems [name];
-                       
-                       if (res == null)
-                               throw new Exception ("JSObject.GetField: search somewhere else");
+
                        if (res is JSFieldInfo)
                                return (JSFieldInfo) res;
                        return null;
@@ -110,15 +108,23 @@ namespace Microsoft.JScript {
 
                public override string ToString ()
                {
-                       throw new NotImplementedException ();
+                       return String.Format ("[{0}]", ClassName);
                }
 
                internal string ClassName {
-                       get { 
+                       get {
                                if (this is ObjectPrototype)
-                                       return "Object";                                
+                                       return "Object";
+                               else if (this is ArrayPrototype)
+                                       return "Array";
+                               else if (this is StringPrototype)
+                                       return "String";
+                               else if (this is NumberPrototype)
+                                       return "Number";
+                               else if (this is DatePrototype)
+                                       return "Date";
                                else
-                                       throw new NotImplementedException ();
+                                       return this.GetType ().ToString ();
                        }
                }
 
@@ -143,7 +149,7 @@ namespace Microsoft.JScript {
 
                internal virtual object GetDefaultValue (Type hint)
                {
-                       throw new NotImplementedException ();
+                       return ObjectPrototype.toString (this);
                }
        }
 }
index 9cc234b73c7e0c595a5c644be6de0a0373257c6a..ce35d2ae96d0565a9d2a2c4fa497e9dccfab7ad7 100644 (file)
@@ -108,6 +108,8 @@ namespace Microsoft.JScript {
                                        return "Array length must be zero or a positive integer";
                                else if (error_number == JSError.PrecisionOutOfRange)
                                        return "The number of fractional digits is out of range";
+                               else if (error_number == JSError.RegExpSyntax)
+                                       return "Syntax error in regular expression";
                                else {
                                        Console.WriteLine ("JScriptException:get_Message: unknown error_number {0}", error_number);
                                        throw new NotImplementedException ();
index 47e0ab4d4eab21b32b55ecb380c6f6588ab206f3..ac8bbc5f00c11c96018b22cdb948cb92be8134cc 100644 (file)
@@ -72,62 +72,83 @@ namespace Microsoft.JScript {
                                        if (obj is JSObject)
                                                type = SemanticAnalyser.map_to_prototype ((JSObject) obj);
 
-                                       MethodInfo method = type.GetMethod (right_hand_side, BindingFlags.Public | BindingFlags.Static);
-                                       JSFunctionAttribute [] custom_attrs = (JSFunctionAttribute [])
-                                               method.GetCustomAttributes (typeof (JSFunctionAttribute), true);
-                                       //
-                                       // We need to iterate through the JSFunctionAttributes to find out whether the function wants
-                                       // to get passed the vsaEngine or not so we can pass the right arguments to it.
-                                       //
-                                       object [] args = null;
-                                       bool has_engine = false;
-                                       bool has_var_args = false;
-                                       foreach (JSFunctionAttribute attr in custom_attrs) {
-                                               JSFunctionAttributeEnum flags = attr.GetAttributeValue ();
-                                               if ((flags & JSFunctionAttributeEnum.HasEngine) != 0)
-                                                       has_engine = true;
-                                               if ((flags & JSFunctionAttributeEnum.HasVarArgs) != 0)
-                                                       has_var_args = true;
-                                       }
-
-                                       if (has_var_args) {
-                                               // 1 for length to last idx + 1 for thisObj = 2
-                                               int va_idx = method.GetParameters ().Length - 2;
-                                               if (has_engine)
-                                                       va_idx--;
-                                               int va_count = arguments.Length - va_idx;
-
-                                               ArrayList arg_list = new ArrayList (arguments);
-                                               object [] var_args = arg_list.GetRange (va_idx, va_count).ToArray ();
-                                               arg_list.RemoveRange (va_idx, va_count);
-                                               arg_list.Add (var_args);
-                                               arguments = arg_list.ToArray ();
-                                       }
-
-                                       if (has_engine)
-                                               args = build_args (arguments, engine);
-                                       else
-                                               args = build_args (arguments, null);
-
-                                       // TODO: Debug logging should be removed
-                                       string arg_str = "";
-                                       foreach (object arg in args)
-                                               arg_str += arg.GetType ().ToString () + ", ";
-
-                                       //System.Console.WriteLine("\nInvoking {0}.{1} with args {2}", obj.GetType(), method.Name, arg_str);
+                                       if (type == null)
+                                               Console.WriteLine ("LateBinding:Call: type is null for {0}.{1}!", obj, right_hand_side);
 
+                                       string name = right_hand_side == "lastIndexOf" ? "lastIndexOfGood" : right_hand_side;
+                                       MethodInfo method = type.GetMethod (name, BindingFlags.Public | BindingFlags.Static);
+                                       if (method == null)
+                                               Console.WriteLine ("LateBinding:Call: method is null for {0}.{1}!", obj, right_hand_side);
+
+                                       object [] args = assemble_args (obj, method, arguments, engine);
                                        return method.Invoke (type, args);
                                }
                        }
                        throw new NotImplementedException ();
                }
 
-               private object [] build_args (object [] arguments, VsaEngine engine)
+               internal static object [] assemble_args (object obj, MethodInfo method, object [] arguments, VsaEngine engine)
+               {
+                       JSFunctionAttribute [] custom_attrs = (JSFunctionAttribute [])
+                               method.GetCustomAttributes (typeof (JSFunctionAttribute), true);
+                       //
+                       // We need to iterate through the JSFunctionAttributes to find out whether the function wants
+                       // to get passed the vsaEngine or not so we can pass the right arguments to it.
+                       //
+                       bool has_engine = false;
+                       bool has_var_args = false;
+                       foreach (JSFunctionAttribute attr in custom_attrs) {
+                               JSFunctionAttributeEnum flags = attr.GetAttributeValue ();
+                               if ((flags & JSFunctionAttributeEnum.HasEngine) != 0)
+                                       has_engine = true;
+                               if ((flags & JSFunctionAttributeEnum.HasVarArgs) != 0)
+                                       has_var_args = true;
+                       }
+
+                       return assemble_args (obj, has_var_args, has_engine, method.GetParameters ().Length, arguments, engine);
+               }
+
+               internal static object [] assemble_args (object obj, bool has_var_args, bool has_engine,
+                       int target_argc, object [] arguments, VsaEngine engine)
+               {
+                       ArrayList arg_list = new ArrayList (arguments);
+                       int req_argc = target_argc - 1; /* -1 for thisObj */
+                       if (has_engine)
+                               req_argc--;
+                       if (has_var_args)
+                               req_argc--;
+
+                       int missing_args = req_argc - arg_list.Count;
+                       for (int i = 0; i < missing_args; i++)
+                               arg_list.Add (null);
+
+                       if (has_var_args) {
+                               int va_idx = req_argc;
+                               int va_count = arg_list.Count - va_idx;
+
+                               object [] var_args = new object [va_count];
+
+                               int j = va_idx;
+                               object arg;
+                               for (int i = 0; i < va_count; i++, j++) {
+                                       arg = arg_list [j];
+                                       if (arg != null)
+                                               var_args [i] = arg;
+                               }
+
+                               arg_list.RemoveRange (va_idx, va_count);
+                               arg_list.Add (var_args);
+                       }
+
+                       return build_args (obj, arg_list.ToArray (), engine, has_engine);
+               }
+
+               internal static object [] build_args (object obj, object [] arguments, VsaEngine engine, bool has_engine)
                {
                        ArrayList args = new ArrayList ();
                        if (obj != null)
                                args.Add (obj);
-                       if (engine != null)
+                       if (has_engine)
                                args.Add (engine);
                        foreach (object o in arguments)
                                args.Add (o);
@@ -141,9 +162,7 @@ namespace Microsoft.JScript {
                {
                        if (construct) {
                                if (brackets) {
-                                       throw new NotImplementedException ();
                                }
-                               throw new NotImplementedException ();
                        } else if (brackets) {
                                if (!(val is JSObject))
                                        throw new Exception ("val has to be a JSObject");
@@ -152,12 +171,23 @@ namespace Microsoft.JScript {
                                object res = js_val.GetField (Convert.ToString (arguments [0]));
                                if (res is JSFieldInfo)
                                        return ((JSFieldInfo) res).GetValue (arguments [0]);
-                               else
-                                       throw new NotImplementedException ();
+                               else {
+                                       res = js_val.elems [Convert.ToInt32 (arguments [0])];
+                                       if (res != null)
+                                               return res;
+                               }
+                               if (res == null)
+                                       Console.WriteLine ("res is null!");
                        } else {
-                               Console.WriteLine ("CallValue -- no brackes, no construct, this = {0}, val = {1}", thisObj.GetType(), val);
-                               throw new NotImplementedException ();
+                               if (val is Closure)
+                                       return ((Closure) val).func.Invoke (thisObj, arguments);
+                               else if (val is FunctionObject)
+                                       return ((FunctionObject) val).Invoke (thisObj, arguments);
                        }
+
+                       Console.WriteLine ("CallValue: construct = {0}, brackets = {1}, this = {2}, val = {3} ({4})",
+                               construct, brackets, thisObj.GetType (), val, val.GetType ());
+                       throw new NotImplementedException ();
                }
 
                [DebuggerStepThroughAttribute]
@@ -185,10 +215,18 @@ namespace Microsoft.JScript {
                public object GetNonMissingValue ()
                {
                        Type type = obj.GetType ();
-                       if (obj is JSObject)
-                               type = SemanticAnalyser.map_to_prototype ((JSObject) obj);
 
                        MemberInfo [] members = type.GetMember (right_hand_side);
+                       if (obj is JSObject && members.Length == 0) {
+                               JSObject jsobj = obj as JSObject;
+                               JSFieldInfo field = jsobj.GetField (right_hand_side);
+                               if (field != null)
+                                       return field.GetValue (right_hand_side);
+
+                               type = SemanticAnalyser.map_to_prototype ((JSObject) obj);
+                               members = type.GetMember (right_hand_side);
+                       }
+
                        if (members.Length > 0) {
                                MemberInfo member = members [0];
                                MemberTypes member_type = member.MemberType;
@@ -198,12 +236,15 @@ namespace Microsoft.JScript {
                                        MethodInfo method = ((PropertyInfo) member).GetGetMethod ();
                                        return method.Invoke (obj, new object [] { });
                                case MemberTypes.Method:
-                                       return new FunctionObject (((MethodInfo) member).Name);
+                                       return new FunctionObject ((MethodInfo) member);
                                default:
-                                       System.Console.WriteLine ("GetNonMissingValue: type = {0}, member_type = {1}", type, member_type);
+                                       Console.WriteLine ("GetNonMissingValue: type = {0}, member_type = {1}", type, member_type);
                                        break;
                                }
                        }
+
+                       Console.WriteLine ("members.Length = {0}, obj = {1}, type = {2}, rhs = {3}",
+                               members.Length, obj, type, right_hand_side);
                        throw new NotImplementedException ();
                }
 
index 00e127ff3e2629073e0e38139f628f1bbdf0e97d..0eb31e92d5fbf08963bc734ed777a1ea7c095112 100644 (file)
@@ -49,22 +49,25 @@ namespace Microsoft.JScript {
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Number_toFixed)]
                public static string toFixed (object thisObj, double fractionDigits)
                {
-                       SemanticAnalyser.assert_type (thisObj, typeof (NumberObject));
-                       NumberObject no = thisObj as NumberObject;
+                       if (!Convert.IsNumber (thisObj))
+                               throw new JScriptException (JSError.NumberExpected);
+
+                       double value = Convert.ToNumber (thisObj);
                        int prec = Convert.ToInt32 (fractionDigits);
 
                        if (prec < 0 || prec > 21)
                                throw new JScriptException (JSError.PrecisionOutOfRange);
 
-                       return no.value.ToString ("F" + prec, CultureInfo.InvariantCulture);
+                       return value.ToString ("F" + prec, CultureInfo.InvariantCulture);
                }
 
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Number_toLocaleString)]
                public static string toLocaleString (object thisObj)
                {
-                       SemanticAnalyser.assert_type (thisObj, typeof (NumberObject));
-                       NumberObject no = thisObj as NumberObject;
-                       return no.value.ToString ();
+                       if (!Convert.IsNumber (thisObj))
+                               throw new JScriptException (JSError.NumberExpected);
+                       else
+                               return Convert.ToNumber (thisObj).ToString ();
                }
 
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Number_toPrecision)]
@@ -82,17 +85,16 @@ namespace Microsoft.JScript {
 
 
                //
-               // We aren't 100% compatible to MS JS.NET here,
-               // because we sometimes produce slightly more of the
-               // fractional digits. This shouldn't cause any
-               // trouble.
+               // We aren't 100% compatible to MS JS.NET here, because we sometimes produce slightly more
+               // of the fractional digits. This shouldn't cause any trouble.
                //
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Number_toString)]
                public static string toString (object thisObj, object radix)
                {
-                       SemanticAnalyser.assert_type (thisObj, typeof (NumberObject));
-                       NumberObject no = thisObj as NumberObject;
-                       double value = no.value;
+                       if (!Convert.IsNumber (thisObj))
+                               throw new JScriptException (JSError.NumberExpected);
+
+                       double value = Convert.ToNumber (thisObj);
 
                        if (Double.IsNaN (value))
                                return "NaN";
@@ -161,9 +163,10 @@ namespace Microsoft.JScript {
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Number_valueOf)]
                public static object valueOf (object thisObj)
                {
-                       SemanticAnalyser.assert_type (thisObj, typeof (NumberObject));
-                       NumberObject no = thisObj as NumberObject;
-                       return no.value;
+                       if (!Convert.IsNumber (thisObj))
+                               throw new JScriptException (JSError.NumberExpected);
+                       else
+                               return Convert.ToNumber (thisObj);
                }
        }
 }
index fe967c43a842480b377ddaefe61ade14b60527ca..baae74c104f91e123a18b3904343da50a1005dad 100644 (file)
@@ -45,97 +45,12 @@ namespace Microsoft.JScript {
                [DebuggerHiddenAttribute]
                public object EvaluatePlus (object v1, object v2)
                {
-                       IConvertible ic1 = v1 as IConvertible;
-                       IConvertible ic2 = v2 as IConvertible;
-
-                       TypeCode tc1 = Convert.GetTypeCode (v1, ic1);
-                       TypeCode tc2 = Convert.GetTypeCode (v2, ic2);
-
-                       bool swapped = false;
-                       redo:
-
-                       switch (tc1) {
-                       case TypeCode.Empty:
-                               if (tc2 == TypeCode.Empty)
-                                       return Double.NaN;
-                               break;
-
-                       case TypeCode.DBNull:
-                               if (tc2 == TypeCode.DBNull)
-                                       return 0;
-                               break;
-
-                       case TypeCode.Double:
-                               switch (tc2) {
-                               case TypeCode.Boolean:
-                               case TypeCode.Double:
-                                       return ic1.ToDouble (null) + ic2.ToDouble (null);
-
-                               case TypeCode.String:
-                                       return ic1.ToString (CultureInfo.InvariantCulture) + ic2.ToString (null);
-
-                               case TypeCode.Empty:
-                                       return Double.NaN;
-
-                               case TypeCode.DBNull:
-                                       return ic1.ToDouble (null);
-                               }
-                               break;
-
-                       case TypeCode.String:
-                               switch (tc2) {
-                               case TypeCode.Boolean:
-                                       return ic1.ToString (null) + Convert.ToString (ic2.ToBoolean (null));
-
-                               case TypeCode.Single:
-                               case TypeCode.Double:
-                               case TypeCode.Char:
-                               case TypeCode.Byte:
-                               case TypeCode.SByte:
-                               case TypeCode.Int16:
-                               case TypeCode.UInt16:
-                               case TypeCode.Int32:
-                               case TypeCode.UInt32:
-                               case TypeCode.Int64:
-                               case TypeCode.UInt64:
-                               case TypeCode.String:
-                                       return ic1.ToString (null) + ic2.ToString (CultureInfo.InvariantCulture);
-
-                               case TypeCode.Empty:
-                                       return ic1.ToString (null) + "undefined";
-
-                               case TypeCode.DBNull:
-                                       return ic1.ToString (null) + "null";
-                               }
-                               break;
-                               
-                       case TypeCode.Boolean:
-                               switch (tc2) {
-                               case TypeCode.Double:
-                                       return ic1.ToDouble (null) + ic2.ToDouble (null);
-
-                               case TypeCode.String:
-                                       return Convert.ToString (ic1.ToBoolean (null)) + ic2.ToString (null);
-
-                               case TypeCode.Boolean:
-                                       return ic1.ToInt32 (null) + ic2.ToInt32 (null);
-
-                               case TypeCode.DBNull:
-                                       return ic1.ToInt32 (null);
-                               }
-                               break;
-                       default:
-                               if (!swapped) {
-                                       IConvertible tic = ic1; ic1 = ic2; ic2 = tic;
-                                       TypeCode ttc = tc1; tc1 = tc2; tc2 = ttc;
-                                       swapped = true;
-                                       goto redo;
-                               }
-                               break;
-                       }
-
-                       System.Console.WriteLine ("EvaluatePlus: tc1 = {0}, tc2 = {1}", tc1, tc2);
-                       throw new NotImplementedException ();
+                       object val1 = Convert.ToPrimitive (v1, null);
+                       object val2 = Convert.ToPrimitive (v2, null);
+                       if (Convert.IsString (val1) || Convert.IsString (val2))
+                               return Convert.ToString (val1) + Convert.ToString (val2);
+                       else
+                               return Convert.ToNumber (val1) + Convert.ToNumber (val2);
                }
 
                public static object DoOp (object v1, object v2)
index 7a8c019a96c39d2a69fa3246f53ae8eb48f9e8c1..49a31fe5216ac546a75057e64173d18dbd5abd46 100644 (file)
@@ -57,7 +57,7 @@ namespace Microsoft.JScript {
                {
                        double value = Convert.ToNumber (v);
                        int oper = (int) this.oper;
-                       if (oper % 2 == 1)
+                       if (oper % 2 == 1) /* prefix? */
                                return value + 1;
                        else
                                return value - 1;
index bf6157a762f588e019b44a06bec23fa8a9344939..6285a6d06b53d4246b9957f3690718c706e21c72 100644 (file)
@@ -30,6 +30,7 @@
 
 using System;
 using System.Text;
+using System.Text.RegularExpressions;
 
 namespace Microsoft.JScript {
 
@@ -39,6 +40,8 @@ namespace Microsoft.JScript {
                private bool _ignoreCase;
                private bool _global;
                private bool _multiline;
+               private int _lastindex = 0;
+               internal Regex regex;
                        
                public override string ToString ()
                {
@@ -74,16 +77,31 @@ namespace Microsoft.JScript {
                }
 
                public Object lastIndex {
-                       get { throw new NotImplementedException (); }
-                       set { throw new NotImplementedException (); }
+                       get { return _lastindex; }
+                       set { _lastindex = Convert.ToInt32 (value); }
                }
 
-               internal RegExpObject  (string pattern, bool ignoreCase, bool global, bool multiLine)
+               internal RegExpObject (string pattern, bool ignoreCase, bool global, bool multiLine)
+               {
+                       Initialize (pattern, ignoreCase, global, multiLine);
+               }
+
+               internal void Initialize (string pattern, bool ignoreCase, bool global, bool multiLine)
                {
                        _source = pattern;
                        _ignoreCase = ignoreCase;
                        _global = global;
                        _multiline = multiLine;
+                       RegexOptions options = RegexOptions.ECMAScript | RegexOptions.Compiled;
+                       if (ignoreCase)
+                               options |= RegexOptions.IgnoreCase;
+                       if (multiLine)
+                               options |= RegexOptions.Multiline;
+                       try {
+                               regex = new Regex (source, options);
+                       } catch (ArgumentException) {
+                               throw new JScriptException (JSError.RegExpSyntax);
+                       }
                }
        }
 }
index aecd079e736b29d96efc33035411aa2675888609..8245bf1ce46999c8a2ff8f2fcfb0be99d9150778 100644 (file)
@@ -30,6 +30,8 @@
 //
 
 using System;
+using System.Text.RegularExpressions;
+using System.Collections;
 
 namespace Microsoft.JScript {  
 
@@ -38,9 +40,19 @@ namespace Microsoft.JScript {
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.RegExp_compile)]
                public static RegExpObject compile (object thisObj, object source, object flags)
                {
-                       throw new NotImplementedException ();
-               }
+                       //
+                       // Note: We always compile RegExp internals so all this method is useful for is for
+                       // changing the properties of the otherwise immutable RegExp objects.
+                       //
+                       RegExpObject re = Convert.ToRegExp (thisObj);
+                       string flag_str = Convert.ToString (flags);
 
+                       re.Initialize (Convert.ToString (source),
+                               flag_str.IndexOfAny (new char [] { 'i' }) > -1,
+                               flag_str.IndexOfAny (new char [] { 'g' }) > -1,
+                               flag_str.IndexOfAny (new char [] { 'm' }) > -1);
+                       return re;
+               }
 
                public static RegExpConstructor constructor {
                        get { return RegExpConstructor.Ctr; }
@@ -49,14 +61,46 @@ namespace Microsoft.JScript {
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.RegExp_exec)]
                public static object exec (object thisObj, object input)
                {
-                       throw new NotImplementedException ();
+                       RegExpObject re = Convert.ToRegExp (thisObj);
+                       string str = Convert.ToString (input);
+                       bool global = re.global;
+                       int lastIndex = global ? (int) re.lastIndex : 0;
+                       bool success = lastIndex >= 0 && lastIndex <= str.Length;
+
+                       Match md = null;
+                       if (success) {
+                               md = re.regex.Match (str, lastIndex);
+                               success = md.Success;
+                       }
+
+                       if (!success) {
+                               re.lastIndex = 0;
+                               return DBNull.Value;
+                       }
+
+                       int index = md.Index;
+                       int endIndex = index + md.Length;
+                       if (global)
+                               re.lastIndex = endIndex;
+
+                       GroupCollection caps = md.Groups;
+                       int len = caps.Count;
+                       RegExpMatch result = new RegExpMatch ();
+
+                       result.AddField ("index", index);
+                       result.AddField ("input", input);
+                       result.length = len;
+                       for (int j = 0; j < len; j++)
+                               result.elems [j] = caps [j].Value;
+
+                       return result;
                }
 
 
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.RegExp_test)]
                public static bool test (object thisObj, object input)
                {
-                       throw new NotImplementedException ();
+                       return exec (thisObj, input) != DBNull.Value;
                }
 
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.RegExp_toString)]
index 84833b9d6c7cf28d9d4c951f9d0779eadc0d29d0..971fd88306d2fc29be7bb4d3c92cb63c656b62d3 100644 (file)
@@ -31,11 +31,15 @@ using System;
 using System.Reflection;
 using System.Diagnostics;
 using System.Globalization;
+using System.Collections;
 
 namespace Microsoft.JScript {
 
        public abstract class ScriptFunction : JSObject {
 
+               internal MethodInfo method;
+               internal MethodAttributes attr;
+
                [DebuggerStepThroughAttribute]
                [DebuggerHiddenAttribute]
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasVarArgs)]
@@ -49,6 +53,14 @@ namespace Microsoft.JScript {
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject | JSFunctionAttributeEnum.HasVarArgs)]
                public Object Invoke (Object thisOb, params Object [] args)
                {
+                       if (method != null) {
+                               if ((attr & MethodAttributes.Static) != 0)
+                                       return method.Invoke (null, LateBinding.assemble_args (thisOb, method, args, null));
+                               else
+                                       return method.Invoke (thisOb, LateBinding.assemble_args (null, method, args, null));
+                       }
+
+                       Console.WriteLine ("Called ScriptFunction:Invoke on user function");
                        throw new NotImplementedException ();
                }
 
index 9e2d9237365be3a327ef236c5f61289f7356e8db..de3c726a8908e6567f2c2af5d015e5ad0948c8ca 100644 (file)
@@ -59,7 +59,11 @@ namespace Microsoft.JScript {
 
                public MethodInfo GetMethod (string name, BindingFlags bindFlags)
                {
-                       throw new NotImplementedException ();
+                       Type prototype = SemanticAnalyser.map_to_prototype (this);
+                       if (prototype != null)
+                               return prototype.GetMethod (name, bindFlags | BindingFlags.Static);
+                       else
+                               throw new NotImplementedException ();
                }
 
                public MethodInfo GetMethod (string name, BindingFlags bindFlags, 
@@ -135,5 +139,16 @@ namespace Microsoft.JScript {
                public virtual Type UnderlyingSystemType {
                        get { throw new NotImplementedException (); }
                }
+
+               internal object CallMethod (string name, params object [] args)
+               {
+                       MethodInfo method = GetMethod (name, BindingFlags.InvokeMethod | BindingFlags.Public);
+                       return CallMethod (method, args);
+               }
+
+               internal object CallMethod (MethodInfo method, params object [] args)
+               {
+                       return method.Invoke (null, LateBinding.assemble_args (this, method, args, null));
+               }
        }
 }      
index d2aeb255be6168daefed438bc0cdaefd750f03ac..1cc0c62b12d481cc2a3f23779956dfa45c61c983 100644 (file)
@@ -73,7 +73,13 @@ namespace Microsoft.JScript {
                        prototypes.Add (typeof (NumberObject), typeof (NumberPrototype));
                        prototypes.Add (typeof (DateObject), typeof (DatePrototype));
                        prototypes.Add (typeof (RegExpObject), typeof (RegExpPrototype));
-                       // FIXME: Error objects missing
+                       prototypes.Add (typeof (RegExpMatch), typeof (ArrayPrototype));
+                       prototypes.Add (typeof (ErrorObject), typeof (ErrorPrototype));
+                       prototypes.Add (typeof (EvalErrorObject), typeof (ErrorPrototype));
+                       prototypes.Add (typeof (RangeErrorObject), typeof (ErrorPrototype));
+                       prototypes.Add (typeof (SyntaxErrorObject), typeof (ErrorPrototype));
+                       prototypes.Add (typeof (TypeErrorObject), typeof (ErrorPrototype));
+                       prototypes.Add (typeof (URIErrorObject), typeof (ErrorPrototype));
                }
 
                internal static string ImplementationName (string name)
@@ -138,7 +144,7 @@ namespace Microsoft.JScript {
 
                internal static void assert_type (object thisObj, Type expType)
                {
-                       if (thisObj == null || thisObj.GetType () != expType)
+                       if (thisObj == null || (thisObj.GetType () != expType && !thisObj.GetType ().IsSubclassOf (expType)))
                                throw new Exception ("Type error");
                }
 
@@ -186,7 +192,7 @@ namespace Microsoft.JScript {
                        return null;
                }
 
-               internal static Type map_to_prototype (JSObject jsObj)
+               internal static Type map_to_prototype (ScriptObject jsObj)
                {
                        if (jsObj == null)
                                throw new Exception ("jsObj can't be null");
index 87ce0f06d00e0b2c67889fa0b6dd5b982bdb0fb3..4aa34fc34239c8f66a7ad0faf9d9eac275bdd4d3 100644 (file)
@@ -64,19 +64,22 @@ namespace Microsoft.JScript {
                        case TypeCode.String:
                                return ic1.ToString (null) == ic2.ToString (null);
 
+                       case TypeCode.Object:
+                               return v1 == v2;
+
                        default:
                                if (both_numbers) {
                                        double num1;
                                        if (Convert.IsFloatTypeCode (tc1))
                                                num1 = ic1.ToDouble (null);
                                        else
-                                               num1 = (double) ic1.ToInt32 (null);
+                                               num1 = (double) ic1.ToInt64 (null);
 
                                        double num2;
                                        if (Convert.IsFloatTypeCode (tc2))
                                                num2 = ic2.ToDouble (null);
                                        else
-                                               num2 = (double) ic2.ToInt32 (null);
+                                               num2 = (double) ic2.ToInt64 (null);
 
                                        return num1 == num2;
                                }
index b04cd97722d65000011786a154d6a150af0a4ac0..d6b0522f4e0ae541b8c4d37735d603fdcc789cf9 100644 (file)
@@ -31,6 +31,7 @@
 using System;
 using Microsoft.JScript.Vsa;
 using System.Globalization;
+using System.Text.RegularExpressions;
 
 namespace Microsoft.JScript {
        
@@ -151,10 +152,11 @@ namespace Microsoft.JScript {
                // with their signature, because position will
                // automatically be forced to 0 in that case. Because
                // of that we currently use 'object position' instead
-               // of their 'double position'.
+               // of their 'double position' in lastIndexOfGood
+               // (which we use from our own compiler) and a wrapper
+               // around that for when we run MS IL.
                //
-               [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_lastIndexOf)]
-               public static int lastIndexOf (object thisObj, object searchString, object position)
+               public static int lastIndexOfGood (object thisObj, object searchString, object position)
                {
                        string string_obj = Convert.ToString (thisObj);
                        string search_obj = Convert.ToString (searchString);
@@ -175,6 +177,17 @@ namespace Microsoft.JScript {
                        return result;
                }
 
+               [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_lastIndexOf)]
+               public static int lastIndexOf (object thisObj, object searchString, object position)
+               {
+                       return lastIndexOfGood (thisObj, searchString, position);
+               }
+
+               public static int lastIndexOf (object thisObj, object searchString, double position)
+               {
+                       return lastIndexOfGood (thisObj, searchString, position);
+               }
+
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_link)]
                public static string link (object thisObj, object linkRef)
                {
@@ -204,19 +217,63 @@ namespace Microsoft.JScript {
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject | JSFunctionAttributeEnum.HasEngine, JSBuiltin.String_match)]
                public static object match (object thisObj, VsaEngine engine, object regExp)
                {
-                       throw new NotImplementedException ();
+                       string string_obj = Convert.ToString (thisObj);
+                       RegExpObject regex_obj = Convert.ToRegExp (regExp);
+                       bool global = regex_obj.global;
+
+                       if (!global)
+                               return RegExpPrototype.exec (regex_obj, string_obj);
+
+                       MatchCollection md = regex_obj.regex.Matches (string_obj);
+                       int n = md.Count;
+                       regex_obj.lastIndex = md [n - 1].Index + 1;
+
+                       ArrayObject result = new ArrayObject ();
+                       result.length = n;
+                       for (int i = 0; i < n; i++)
+                               result.elems [i] = md [i].Value;
+
+                       return result;
                }
 
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_replace)]
                public static string replace (object thisObj, object regExp, object replacement)
                {
+                       string string_obj = Convert.ToString (thisObj);
+
+                       if (!(regExp is RegExpObject)) {
+                               string match_str = Convert.ToString (regExp);
+                               string replace_str = Convert.ToString (replacement);
+                               int match_pos = string_obj.IndexOf (match_str);
+
+                               if (match_pos == -1)
+                                       return string_obj;
+
+                               return String.Concat (string_obj.Substring (0, match_pos), replace_str,
+                                       string_obj.Substring (match_pos + match_str.Length));
+                       }
+
+                       RegExpObject regex_obj = (RegExpObject) regExp;
+                       int count = regex_obj.global ? -1 : 1;
+
+                       if (!(replacement is FunctionObject))
+                               return regex_obj.regex.Replace (string_obj, Convert.ToString (replacement), count);
+
                        throw new NotImplementedException ();
                }
 
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject | JSFunctionAttributeEnum.HasEngine, JSBuiltin.String_search)]
                public static int search (object thisObj, VsaEngine engine, object regExp)
                {
-                       throw new NotImplementedException ();
+                       string string_obj = Convert.ToString (thisObj);
+                       RegExpObject regex_obj = Convert.ToRegExp (regExp);
+                       Match md = regex_obj.regex.Match (string_obj);
+                       /* Note: Microsoft's implementation updates the lastIndex property of regex_obj here, but
+                        * ECMA-262, 15.5.4.12, NOTE 1 explicitely says not to do so. We do the ECMA-262 behavior. */
+                       if (md.Success)
+                               return md.Index;
+                       else
+                               return -1;
                }
 
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_slice)]
@@ -261,7 +318,95 @@ namespace Microsoft.JScript {
                public static ArrayObject split (object thisObj, VsaEngine engine,
                                                 object separator, object limit)
                {
-                       throw new NotImplementedException ();
+                       string string_obj = Convert.ToString (thisObj);
+                       int length = string_obj.Length;
+                       int max_count = (limit != null) ? Convert.ToInt32 (limit) : -1;
+                       ArrayObject result = new ArrayObject ();
+
+                       if (separator == null) {
+                               result.length = 1;
+                               result.elems [0] = string_obj;
+                               return result;
+                       }
+
+                       int start_pos = 0;
+                       int end_pos = -1;
+                       int match_len = 0;
+                       int count = 0;
+                       int sep_len = 0;
+
+                       if (!(separator is RegExpObject)) {
+                               string sep_str = Convert.ToString (separator);
+                               sep_len = sep_str.Length;
+
+                               if (string_obj.Length == 0) {
+                                       if (sep_len > 0) {
+                                               result.length = 1;
+                                               result.elems [0] = string_obj;
+                                       }
+
+                                       return result;
+                               }
+
+                               while (end_pos != length && (max_count == -1 || count < max_count)) {
+                                       end_pos = (length != 0) ? string_obj.IndexOf (sep_str, start_pos) : length;
+                                       if (end_pos == -1)
+                                               end_pos = length;
+                                       else if (sep_len == 0)
+                                               end_pos++;
+
+                                       match_len = end_pos - start_pos;
+                                       result.elems [count] = string_obj.Substring (start_pos, match_len);
+
+                                       start_pos += match_len + sep_len;
+                                       count++;
+                               }
+
+                               result.length = count;
+                               return result;
+                       }
+
+                       RegExpObject sep_re = (RegExpObject) separator;
+                       MatchCollection md = sep_re.regex.Matches (string_obj);
+                       int n = md.Count;
+
+                       Match match = null;
+                       for (int i = 0; i < n; i++) {
+                               match = md [i];
+                               sep_len = match.Length;
+                               end_pos = match.Index;
+                               match_len = end_pos - start_pos;
+
+                               if (start_pos != 0 || match_len > 0) {
+                                       result.elems [count] = string_obj.Substring (start_pos, match_len);
+                                       count++;
+                               }
+
+                               bool first_cap = true;
+                               foreach (Capture cap in match.Groups) {
+                                       if (first_cap) {
+                                               first_cap = false;
+                                               continue;
+                                       }
+
+                                       result.elems [count] = cap.Value;
+                                       count++;
+                               }
+
+                               start_pos += match_len + sep_len;
+                       }
+
+                       if (n > 0) {
+                               sep_re.lastIndex = match.Index + match.Length;
+
+                               if (start_pos < length) {
+                                       result.elems [count] = string_obj.Substring (start_pos);
+                                       count++;
+                               }
+                       }
+
+                       result.length = count;
+                       return result;
                }
 
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_strike)]
@@ -322,7 +467,7 @@ namespace Microsoft.JScript {
                        if (end == null)
                                _end = string_len;
                        else {
-                               _end = (int) (double) end;
+                               _end = Convert.ToInt32 (end);
 
                                if (_end == Double.NaN || _end < 0)
                                        _end = 0;
@@ -374,9 +519,10 @@ namespace Microsoft.JScript {
                [JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_toString)]
                public static string toString (object thisObj)
                {
-                       SemanticAnalyser.assert_type (thisObj, typeof (StringObject));
-                       StringObject str_obj = thisObj as StringObject;
-                       return str_obj.value;
+                       if (!Convert.IsString (thisObj))
+                               throw new JScriptException (JSError.StringExpected);
+                       else
+                               return Convert.ToString (thisObj);
                }
 
                [MonoTODO ("I18N Needs checking -- contact flgr@ccan.de for details")]
index 239e64b29da43492ab509f3c13613369c57415fc..6a9fff534bfab6b3f54cf4a229abbdfbf07c5a21 100644 (file)
@@ -38,13 +38,11 @@ namespace Microsoft.JScript {
                {
                        IConvertible ic = value as IConvertible;
                        TypeCode tc = Convert.GetTypeCode (value, ic);
+
+                       if (Convert.IsNumberTypeCode (tc))
+                               return "number";
                        
                        switch (tc) {
-                       case TypeCode.Char:
-                       case TypeCode.Int32:
-                       case TypeCode.Double:
-                               return "number";
-
                        case TypeCode.String:
                                return "string";
 
index cff56b77199b700ad0c94764caaabc0783614141..789122efe5213d372773628f51773cf308e99f0c 100644 (file)
@@ -1404,7 +1404,7 @@ namespace Microsoft.JScript {
                                        missing = params_info.Length - n;
 
                                for (int k = 0; k < missing; k++)
-                                       ig.Emit (OpCodes.Ldsfld, typeof (DBNull).GetField ("Value"));
+                                       ig.Emit (OpCodes.Ldnull);
                        }
                }