using System;
using System.Collections;
-
+
namespace Microsoft.JScript {
public class ArrayObject : JSObject {
{
length = 0;
}
-
+
internal ArrayObject (object o)
{
IConvertible ic = o as IConvertible;
TypeCode tc = ic.GetTypeCode ();
- if (tc == TypeCode.Int32 || ic.ToDouble (null) < Int32.MaxValue) {
- int size = ic.ToInt32 (null);
- if (size > 0)
- length = o;
- else
- throw new JScriptException (JSError.ArrayLengthConstructIncorrect);
- } else {
- elems = new Hashtable ();
- elems.Add (o, o);
- }
+ try {
+ if (tc == TypeCode.Int32 || ic.ToDouble (null) < Int32.MaxValue) {
+ int size = ic.ToInt32 (null);
+ if (size > 0) {
+ length = o;
+ return;
+ } else
+ throw new JScriptException (JSError.ArrayLengthConstructIncorrect);
+ }
+ } catch (FormatException) { /* OK */ }
+
+ elems = new Hashtable ();
+ length = 1;
+ elems.Add (0, o);
}
internal ArrayObject (params object [] args)
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Array_join)]
public static string join (object thisObj, object separator)
{
+ // TODO: Shouldn't this be generic!?
SemanticAnalyser.assert_type (thisObj, typeof (ArrayObject));
ArrayObject array_obj = (ArrayObject) thisObj;
-
+
string _separator;
if (separator == null)
_separator = ",";
- else
+ else
_separator = Convert.ToString (separator);
Hashtable elems = array_obj.Elements;
StringBuilder str = new StringBuilder ();
bool first = true;
+
foreach (DictionaryEntry entry in elems) {
if (!first)
str.Append (_separator);
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Array_pop)]
public static object pop (object thisObj)
{
- throw new NotImplementedException ();
+ // TODO: Shouldn't this be generic!?
+ SemanticAnalyser.assert_type (thisObj, typeof (ArrayObject));
+ ArrayObject array_obj = (ArrayObject) thisObj;
+
+ int n = (int) array_obj.length;
+ if (n > 0) {
+ int new_len = n - 1;
+ array_obj.length = new_len;
+ if (array_obj.elems.ContainsKey (new_len)) {
+ object result = array_obj.elems [new_len];
+ array_obj.elems.Remove (new_len);
+ return result;
+ }
+ }
+ return null;
}
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject | JSFunctionAttributeEnum.HasVarArgs, JSBuiltin.Array_push)]
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Array_reverse)]
public static object reverse (object thisObj)
{
- throw new NotImplementedException ();
+ // TODO: Shouldn't this be generic!?
+ SemanticAnalyser.assert_type (thisObj, typeof (ArrayObject));
+ ArrayObject array_obj = (ArrayObject) thisObj;
+
+ int n = (int) array_obj.length;
+ int half_n = n / 2;
+ int j = n - 1;
+ object temp;
+
+ for (int i = 0; i < half_n; i++, j--) {
+ temp = array_obj.elems [i];
+ array_obj.elems [i] = array_obj.elems [j];
+ array_obj.elems [j] = temp;
+ }
+ return array_obj;
}
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Array_shift)]
public static object shift (object thisObj)
{
- throw new NotImplementedException ();
+ // TODO: Shouldn't this be generic!?
+ SemanticAnalyser.assert_type (thisObj, typeof (ArrayObject));
+ ArrayObject array_obj = (ArrayObject) thisObj;
+
+ int n = (int) array_obj.length;
+ if (n > 0) {
+ array_obj.length = n - 1;
+ if (array_obj.elems.ContainsKey (0)) {
+ object result = array_obj.elems [0];
+ array_obj.elems.Remove (0);
+ for (int i = 1; i < n; i++)
+ array_obj.elems [i - 1] = array_obj.elems [i];
+ array_obj.elems.Remove (n - 1);
+ return result;
+ }
+ }
+ return null;
}
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject | JSFunctionAttributeEnum.HasEngine, JSBuiltin.Array_slice)]
- public static ArrayObject slice (object thisObj, VsaEngine engine,
- double start, object end)
+ public static ArrayObject slice (object thisObj, VsaEngine engine, double start, object end)
{
- throw new NotImplementedException ();
+ // TODO: Shouldn't this be generic!?
+ SemanticAnalyser.assert_type (thisObj, typeof (ArrayObject));
+ ArrayObject array_obj = (ArrayObject) thisObj;
+ int array_len = (int) array_obj.length;
+ int _start, _end;
+
+ if (start > array_len)
+ _start = array_len;
+ else {
+ _start = (int) start;
+ if (_start < 0)
+ _start += array_len;
+ }
+
+ if (end == null)
+ _end = array_len;
+ else {
+ _end = (int) (double) end;
+
+ if (_end < 0)
+ _end += array_len;
+ else if (_end > array_len)
+ _end = array_len;
+ }
+
+ if (_end < _start)
+ _end = _start;
+
+ ArrayObject result = new ArrayObject();
+ result.length = _end - _start;
+
+ for (int i = _start; i < _end; i++)
+ result.elems [i - _start] = array_obj.elems [i];
+
+ return result;
}
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Array_sort)]
throw new NotImplementedException ();
}
+ internal static bool IsNumberTypeCode (TypeCode tc)
+ {
+ switch (tc) {
+ case TypeCode.Byte:
+ case TypeCode.Char:
+ case TypeCode.Double:
+ case TypeCode.Int16:
+ case TypeCode.Int32:
+ case TypeCode.SByte:
+ case TypeCode.Single:
+ case TypeCode.UInt16:
+ case TypeCode.UInt32:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ internal static bool IsFloatTypeCode (TypeCode tc)
+ {
+ switch (tc) {
+ case TypeCode.Double:
+ case TypeCode.Single:
+ return true;
+ default:
+ return false;
+ }
+ }
public static double CheckIfDoubleIsInteger (double d)
{
}
- public static object Coerce2 (object value, TypeCode target,
- bool truncationPermitted)
+ public static object Coerce2 (object value, TypeCode target,
+ bool truncationPermitted)
{
throw new NotImplementedException ();
}
public static int ToInt32 (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:
+ return (int) value;
+
+ case TypeCode.Single:
+ case TypeCode.Double:
+ return (int) Math.Floor ((double) value);
+
+ default:
+ Console.WriteLine ("\nToInt32: value.GetType = {0}", value.GetType ());
+ break;
+ }
throw new NotImplementedException ();
}
public static double ToNumber (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:
+ return (double) value;
+
+ case TypeCode.Single:
+ case TypeCode.Double:
+ return (double) value;
+
+ case TypeCode.String:
+ return GlobalObject.parseFloat (value);
+
+ default:
+ Console.WriteLine ("\nToNumber: value.GetType = {0}", value.GetType ());
+ break;
+ }
+
throw new NotImplementedException ();
}
public static object ToObject (object value, VsaEngine engine)
- {
+ {
IConvertible ic = value as IConvertible;
TypeCode tc = Convert.GetTypeCode (value, ic);
switch (tc) {
case TypeCode.String:
return new StringObject (ic.ToString (null));
+ case TypeCode.Single:
+ case TypeCode.Double:
+ case TypeCode.Char:
+ case TypeCode.Byte:
+ case TypeCode.SByte:
+ case TypeCode.UInt16:
+ case TypeCode.UInt32:
+ case TypeCode.Int16:
+ case TypeCode.Int32:
+ return new NumberObject (ic.ToDouble (null));
case TypeCode.Object:
return value;
default:
TypeCode tc = Convert.GetTypeCode (value, ic);
switch (tc) {
+ case TypeCode.Empty:
+ return "";
+
case TypeCode.DBNull:
return "null";
return "true";
else
return "false";
-
+
+ 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 (null);
return RegExpPrototype.toString (value);
else if (value is StringObject)
return StringPrototype.toString (value);
+ else if (value is FunctionWrapper)
+ return FunctionPrototype.toString (value);
Console.WriteLine ("value.GetType = {0}", value.GetType ());
throw new NotImplementedException ();
default:
public static string ToString (double d)
- {
+ {
IConvertible ic = d as IConvertible;
return ic.ToString (null);
}
return TypeCode.Empty;
else if (ic == null)
return TypeCode.Object;
- else
- return ic.GetTypeCode ();
+ else
+ return ic.GetTypeCode ();
}
}
}
TypeCode tc2 = Convert.GetTypeCode (v2, ic2);
switch (tc1) {
+ case TypeCode.Empty:
+ switch (tc2) {
+ case TypeCode.Empty:
+ return true;
+ case TypeCode.DBNull:
+ return true;
+ }
+ break;
+
+ case TypeCode.DBNull:
+ switch (tc1) {
+ case TypeCode.DBNull:
+ return true;
+ case TypeCode.Empty:
+ return true;
+ }
+ break;
+
+ case TypeCode.Boolean:
+ switch (tc1) {
+ case TypeCode.Boolean:
+ return ic1.ToBoolean (null) == ic2.ToBoolean (null);
+ }
+ break;
+
+ case TypeCode.Char:
+ switch (tc2) {
+ case TypeCode.Char:
+ return ic1.ToChar (null) == ic2.ToChar (null);
+ case TypeCode.Double:
+ return (double) ic1.ToChar (null) == ic2.ToDouble (null);
+ }
+ break;
+
case TypeCode.Double:
switch (tc2) {
case TypeCode.Double:
internal override bool Resolve (IdentificationTable context, bool no_effect)
{
this.no_effect = no_effect;
- return Resolve (context);
- }
+ return Resolve (context);
+ }
internal override void Emit (EmitContext ec)
{
LocalBuilder local_builder;
if (op != JSToken.None) {
- Type t = typeof (Equality);
+ Type t = typeof (Equality);
local_builder = ig.DeclareLocal (t);
if (op == JSToken.Equal)
ig.Emit (OpCodes.Ldc_I4_S, (byte) 53);
else if (op == JSToken.NotEqual)
ig.Emit (OpCodes.Ldc_I4_S, (byte) 54);
- ig.Emit (OpCodes.Newobj, t.GetConstructor (new Type [] {typeof (int)}));
+ ig.Emit (OpCodes.Newobj, t.GetConstructor (new Type [] { typeof (int) }));
ig.Emit (OpCodes.Stloc, local_builder);
ig.Emit (OpCodes.Ldloc, local_builder);
}
if (left != null)
left.Emit (ec);
if (right != null)
- right.Emit (ec);
-
+ right.Emit (ec);
+
if (op == JSToken.Equal || op == JSToken.NotEqual) {
ig.Emit (OpCodes.Call, typeof (Equality).GetMethod ("EvaluateEquality"));
ig.Emit (OpCodes.Brtrue_S, t_lbl);
else if (op == JSToken.NotEqual)
ig.Emit (OpCodes.Brfalse_S, t_lbl);
-
+
ig.Emit (OpCodes.Ldc_I4_0);
ig.Emit (OpCodes.Br_S, f_lbl);
ig.MarkLabel (t_lbl);
ig.Emit (OpCodes.Ldc_I4_1);
ig.MarkLabel (f_lbl);
ig.Emit (OpCodes.Pop);
- }
+ }
}
}
}
StringBuilder sb = new StringBuilder ();
sb.Append ("function ");
- sb.Append (name + " ");
+ sb.Append (name);
sb.Append ("(");
if (parameters != null)
sb.Append (this.parameters.ToString ());
sb.Append (")");
- sb.Append (" : " + return_type);
- sb.Append ("{");
+ if (return_type != null)
+ sb.Append (" : " + return_type);
+ sb.Append (" {\n");
if (body != null)
sb.Append (body.ToString ());
+ else
+ sb.Append (" [native code]");
- sb.Append ("}");
+ sb.Append ("\n}");
return sb.ToString ();
}
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Function_toString)]
public static string toString (object thisObj)
{
+ if (thisObj is FunctionObject)
+ return (((FunctionObject) thisObj).ToString ());
throw new NotImplementedException ();
}
}
using System;
using System.Text;
+using System.Globalization;
namespace Microsoft.JScript {
[JSFunctionAttribute (0, JSBuiltin.Global_isNaN)]
public static bool isNaN (Object num)
{
- throw new NotImplementedException ();
+ double number = Convert.ToNumber (num);
+ return Double.IsNaN (number);
}
[JSFunctionAttribute(0, JSBuiltin.Global_isFinite)]
public static bool isFinite (double number)
{
- throw new NotImplementedException ();
+ return !Double.IsInfinity (number) && !Double.IsNaN (number);
}
public static Type @long {
[JSFunctionAttribute (0, JSBuiltin.Global_parseFloat)]
public static double parseFloat (Object @string)
{
- throw new NotImplementedException ();
+ string string_obj = Convert.ToString (@string);
+ double result;
+
+ if (Double.TryParse (string_obj, NumberStyles.Float, null, out result))
+ return result;
+ else if (string_obj.StartsWith ("Infinity") || string_obj.StartsWith ("+Infinity"))
+ return Double.PositiveInfinity;
+ else if (string_obj.StartsWith ("-Infinity"))
+ return Double.NegativeInfinity;
+ else
+ return Double.NaN;
}
[JSFunctionAttribute (0, JSBuiltin.Global_parseInt)]
namespace Microsoft.JScript {
-
- public sealed class Globals
- {
+ public sealed class Globals {
public static VsaEngine contextEngine;
public static ArrayObject ConstructArrayLiteral (object [] args)
{
- throw new NotImplementedException ();
+ return new ArrayObject (args);
}
}
}
public object obj;
private static BindingFlags bind_flags = BindingFlags.Public;
private string right_hand_side;
-
+
public LateBinding (string name)
{
this.right_hand_side = name;
[DebuggerStepThroughAttribute]
[DebuggerHiddenAttribute]
public object Call (object [] arguments, bool construct, bool brackets,
- VsaEngine engine)
+ VsaEngine engine)
{
if (construct) {
- if (brackets) {
+ if (brackets) {
} else {
}
} else {
type = SemanticAnalyser.map_to_prototype ((JSObject) obj);
MethodInfo method = type.GetMethod (right_hand_side, BindingFlags.Public | BindingFlags.Static);
- object [] args = build_args (arguments, 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.
+ //
+ object [] args = null;
+ foreach (JSFunctionAttribute attr in custom_attrs)
+ if ((attr.GetAttributeValue () & JSFunctionAttributeEnum.HasEngine) != 0) {
+ args = build_args (arguments, engine);
+ break;
+ }
+
+ if (args == null)
+ 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);
+
return method.Invoke (type, args);
}
}
args.Add (o);
return args.ToArray ();
}
-
+
[DebuggerStepThroughAttribute]
[DebuggerHiddenAttribute]
public static object CallValue (object thisObj, object val, object [] arguments,
if (construct) {
if (brackets) {
return null;
- }
+ }
return null;
} else if (brackets) {
if (!(val is JSObject))
JSObject js_val = (JSObject) val;
object res = js_val.GetField (Convert.ToString (arguments [0]));
- if (res is JSFieldInfo)
+ if (res is JSFieldInfo)
return ((JSFieldInfo) res).GetValue (arguments [0]);
- else
+ else
throw new NotImplementedException ();
} else {
return null;
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 (members.Length > 0) {
MemberInfo member = members [0];
switch (member_type) {
case MemberTypes.Property:
MethodInfo method = ((PropertyInfo) member).GetGetMethod ();
- return method.Invoke (obj, new object [] {});
+ return method.Invoke (obj, new object [] { });
+ case MemberTypes.Method:
+ return new FunctionObject (((MethodInfo) member).Name);
+ default:
+ System.Console.WriteLine ("GetNonMissingValue: type = {0}, member_type = {1}", type, member_type);
+ break;
}
}
throw new NotImplementedException ();
namespace Microsoft.JScript {
public class NumberObject : JSObject {
-
- double value;
+
+ internal double value;
internal NumberObject ()
{
internal NumberObject (object value)
{
- throw new NotImplementedException ();
+ this.value = (double) value;
}
public new Type GetType ()
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.Number_valueOf)]
public static object valueOf (object thisObj)
{
- throw new NotImplementedException ();
+ SemanticAnalyser.assert_type (thisObj, typeof (NumberObject));
+ NumberObject no = thisObj as NumberObject;
+ return no.value;
}
}
}
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.String:
return ic1.ToString (null) + ic2.ToString (null);
+
+ case TypeCode.Empty:
+ return ic1.ToString (null);
+
+ case TypeCode.DBNull:
+ return ic1.ToString (null) + "null";
}
break;
default:
return EvaluatePlus (v2, v1);
}
+
+ System.Console.WriteLine ("EvaluatePlus: tc1 = {0}, tc2 = {1}", tc1, tc2);
throw new NotImplementedException ();
}
public static bool JScriptStrictEquals (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 both_numbers = Convert.IsNumberTypeCode (tc1) && Convert.IsNumberTypeCode (tc2);
+ if (tc1 != tc2 && !both_numbers)
+ return false;
+
+ switch (tc1) {
+ case TypeCode.DBNull:
+ case TypeCode.Empty:
+ return true;
+
+ case TypeCode.Boolean:
+ return ic1.ToBoolean (null) == ic2.ToBoolean (null);
+
+ case TypeCode.String:
+ return ic1.ToString (null) == ic2.ToString (null);
+
+ default:
+ if (both_numbers) {
+ double num1;
+ if (Convert.IsFloatTypeCode (tc1))
+ num1 = ic1.ToDouble (null);
+ else
+ num1 = (double) ic1.ToInt32 (null);
+
+ double num2;
+ if (Convert.IsFloatTypeCode (tc2))
+ num2 = ic2.ToDouble (null);
+ else
+ num2 = (double) ic2.ToInt32 (null);
+
+ return num1 == num2;
+ }
+ Console.WriteLine ("StrictEquality, tc1 = {0}, tc2 = {1}", tc1, tc2);
+ break;
+ }
throw new NotImplementedException ();
}
using System;
using Microsoft.JScript.Vsa;
+using System.Globalization;
namespace Microsoft.JScript {
public class StringPrototype : StringObject {
+ /* Note that the implementation of this HTML tag stuff is pretty dumb.
+ * It does not do any escaping of HTML characters like '<', '>' or '"' which means that you can do
+ * HTML injection via for example "foo".anchor("NAME\" style=\"font-size: 500pt;") which will result
+ * in <A NAME="NAME" style="font-size: 500pt;">, however Mozilla, Internet Explorer and Opera all do
+ * the same thing and I could not find any standard against this behavior. */
+
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_anchor)]
public static string anchor (object thisObj, object anchorName)
{
- throw new NotImplementedException ();
+ return "<A NAME=\"" + Convert.ToString (anchorName) + "\">" + Convert.ToString (thisObj) + "</A>";
}
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_big)]
public static string big (object thisObj)
{
- throw new NotImplementedException ();
+ return "<BIG>" + Convert.ToString (thisObj) + "</BIG>";
}
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_blink)]
public static string blink (object thisObj)
{
- throw new NotImplementedException ();
+ return "<BLINK>" + Convert.ToString (thisObj) + "</BLINK>";
}
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_bold)]
public static string bold (object thisObj)
{
- throw new NotImplementedException ();
+ return "<B>" + Convert.ToString (thisObj) + "</B>";
}
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_charAt)]
public static string charAt (object thisObj, double pos)
{
- throw new NotImplementedException ();
+ int _pos = Convert.ToInt32 (pos);
+ string string_obj = Convert.ToString (thisObj);
+
+ if (_pos < 0 || _pos >= string_obj.Length)
+ return "";
+
+ return string_obj.Substring (_pos, 1);
}
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_charCodeAt)]
- public static object charCodeAt (object thisObj, double pos)
+ public static object charCodeAt (object thisObj, double arg)
{
- throw new NotImplementedException ();
+ int pos = Convert.ToInt32 (arg);
+ string string_obj = Convert.ToString (thisObj);
+
+ if (pos < 0 || pos >= string_obj.Length)
+ return Double.NaN;
+
+ return string_obj [pos];
}
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject | JSFunctionAttributeEnum.HasVarArgs, JSBuiltin.String_concat)]
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_fixed)]
public static string @fixed (object thisObj)
{
- throw new NotImplementedException ();
+ return "<TT>" + Convert.ToString (thisObj) + "</TT>";
}
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_fontcolor)]
public static string fontcolor (object thisObj, object colorName)
{
- throw new NotImplementedException ();
+ return "<FONT COLOR=\"" + Convert.ToString (colorName) + "\">" + Convert.ToString (thisObj) + "</FONT>";
}
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_fontsize)]
public static string fontsize (object thisObj, object fontsize)
{
- throw new NotImplementedException ();
+ return "<FONT SIZE=\"" + Convert.ToString (fontsize) + "\">" + Convert.ToString (thisObj) + "</FONT>";
}
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_indexOf)]
public static int indexOf (object thisObj, object searchString, double position)
{
- throw new NotImplementedException ();
+ string string_obj = Convert.ToString (thisObj);
+ string search_obj = Convert.ToString (searchString);
+ int pos = (int) position;
+ if (pos < 0)
+ pos = 0;
+ else if (pos > string_obj.Length)
+ pos = string_obj.Length;
+ return string_obj.IndexOf (search_obj, pos);
}
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_italics)]
public static string italics (object thisObj)
{
- throw new NotImplementedException ();
+ return "<I>" + Convert.ToString (thisObj) + "</I>";
}
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_lastIndexOf)]
- public static int lastIndexOf (object thisobj, object searchString, double position)
- {
- throw new NotImplementedException ();
+ public static int lastIndexOf (object thisObj, object searchString, object position)
+ {
+ string string_obj = Convert.ToString (thisObj);
+ string search_obj = Convert.ToString (searchString);
+ int pos;
+ if (position == null)
+ pos = string_obj.Length;
+ else {
+ pos = Convert.ToInt32 (position);
+ if (pos < 0)
+ pos = 0;
+ else if (pos > string_obj.Length)
+ pos = string_obj.Length;
+ }
+ int result = string_obj.LastIndexOf (search_obj, pos);
+ // string:LastIndexOf ignores matches at string start if pos is 0
+ if (result == -1 && pos == 0 && string_obj.StartsWith (search_obj))
+ return 0;
+ return result;
}
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_link)]
public static string link (object thisObj, object linkRef)
{
- throw new NotImplementedException ();
+ return "<A HREF=\"" + Convert.ToString (linkRef) + "\">" + Convert.ToString (thisObj) + "</A>";
}
+ [MonoTODO ("I18N Needs checking -- contact flgr@ccan.de for details")]
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_localeCompare)]
public static int localeCompare (object thisObj, object thatObj)
{
- throw new NotImplementedException ();
+ // TODO FIXME I18N: Verify that we do the right thing even in border cases.
+ string string_a = Convert.ToString (thisObj);
+ string string_b = Convert.ToString (thatObj);
+ int caseless_result = String.Compare (string_a, string_b, true);
+ /* I have no idea if this is enough to fix the behavior in all cases, but it at least makes
+ * localeCompare("abc", "ABC") work as in MS JS.NET -- this will likely be revised after
+ * more testing. */
+ if (caseless_result == 0)
+ return -String.Compare (string_a, string_b, false);
+ else
+ return String.Compare (string_a, string_b, false);
}
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject | JSFunctionAttributeEnum.HasEngine, JSBuiltin.String_match)]
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_slice)]
public static string slice (object thisObj, double start, object end)
{
- throw new NotImplementedException ();
+ string string_obj = Convert.ToString (thisObj);
+ int string_len = string_obj.Length;
+ int _start, _end;
+
+ if (start > string_len)
+ _start = string_len;
+ else {
+ _start = (int) start;
+ if (_start < 0)
+ _start += string_len;
+ }
+
+ if (end == null)
+ _end = string_len;
+ else {
+ _end = (int) (double) end;
+
+ if (_end < 0)
+ _end += string_len;
+ else if (_end > string_len)
+ _end = string_len;
+ }
+
+ if (_end < _start)
+ _end = _start;
+
+ return string_obj.Substring (_start, _end - _start);
}
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_small)]
public static string small (object thisObj)
{
- throw new NotImplementedException ();
+ return "<SMALL>" + Convert.ToString (thisObj) + "</SMALL>";
}
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject | JSFunctionAttributeEnum.HasEngine, JSBuiltin.String_split)]
}
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_strike)]
- public static string strike (object thisOBj)
+ public static string strike (object thisObj)
{
- throw new NotImplementedException ();
+ return "<STRIKE>" + Convert.ToString (thisObj) + "</STRIKE>";
}
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_sub)]
public static string sub (object thisObj)
{
- throw new NotImplementedException ();
+ return "<SUB>" + Convert.ToString (thisObj) + "</SUB>";
}
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_substr)]
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_substring)]
public static string substring (object thisObj, double start, object end)
{
- throw new NotImplementedException ();
+ string string_obj = Convert.ToString (thisObj);
+ int string_len = string_obj.Length;
+ int _start, _end;
+
+ if (start == Double.NaN || start < 0)
+ _start = 0;
+ else if (start > string_len)
+ _start = string_len;
+ else
+ _start = (int) start;
+
+ if (end == null)
+ _end = string_len;
+ else {
+ _end = (int) (double) end;
+
+ if (_end == Double.NaN || _end < 0)
+ _end = 0;
+ else if (_end > string_len)
+ _end = string_len;
+ }
+
+ if (_end < _start) {
+ int temp = _start;
+ _start = _end;
+ _end = temp;
+ }
+ return string_obj.Substring (_start, _end - _start);
}
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_sup)]
public static string sup (object thisObj)
{
- throw new NotImplementedException ();
+ return "<SUP>" + Convert.ToString (thisObj) + "</SUP>";
}
+ /* TODO FIXME I18N: Somebody who is familar with locales should check if the definition of these really is
+ * this simple. */
+
+ [MonoTODO ("I18N Needs checking -- contact flgr@ccan.de for details")]
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_toLocaleLowerCase)]
public static string toLocaleLowerCase (object thisObj)
{
- throw new NotImplementedException ();
+ string string_obj = Convert.ToString (thisObj);
+ return string_obj.ToLower ();
}
+ [MonoTODO ("I18N Needs checking -- contact flgr@ccan.de for details")]
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_toLocaleUpperCase)]
public static string toLocaleUpperCase (object thisObj)
{
- throw new NotImplementedException ();
+ string string_obj = Convert.ToString (thisObj);
+ return string_obj.ToUpper ();
}
+ [MonoTODO ("I18N Needs checking -- contact flgr@ccan.de for details")]
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_toLowerCase)]
public static string toLowerCase (object thisObj)
{
- throw new NotImplementedException ();
+ string string_obj = Convert.ToString (thisObj);
+ return string_obj.ToLower (CultureInfo.InvariantCulture);
}
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_toString)]
return str_obj.value;
}
+ [MonoTODO ("I18N Needs checking -- contact flgr@ccan.de for details")]
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_toUpperCase)]
public static string toUpperCase (object thisObj)
{
- throw new NotImplementedException ();
+ string string_obj = Convert.ToString (thisObj);
+ return string_obj.ToUpper (CultureInfo.InvariantCulture);
}
[JSFunctionAttribute (JSFunctionAttributeEnum.HasThisObject, JSBuiltin.String_valueOf)]
public static object valueOf (object thisObj)
{
- throw new NotImplementedException ();
+ return toString (thisObj);
}
}
}
TypeCode tc = Convert.GetTypeCode (value, ic);
switch (tc) {
+ case TypeCode.Char:
case TypeCode.Int32:
case TypeCode.Double:
return "number";
return "string";
case TypeCode.Object:
+ case TypeCode.DBNull:
return "object";
+
+ case TypeCode.Empty:
+ return "undefined";
+
+ case TypeCode.Boolean:
+ return "boolean";
default:
Console.WriteLine ("TypeOf, tc = {0}", tc);