[asp.net] HtmlForum.Name rendering updates + test updates
[mono.git] / mcs / class / System.Web / System.Web.UI / ClientScriptManager.cs
index 6ff81feb4f4df6b1c37fc656193c576c81f6270b..0ad416d30f211adde4e86ddedee0872bae3adb0e 100644 (file)
@@ -8,7 +8,7 @@
 //   Lluis Sanchez (lluis@novell.com)
 //
 // (C) 2002,2003 Ximian, Inc. (http://www.ximian.com)
-// (c) 2003 Novell, Inc. (http://www.novell.com)
+// (c) 2003-2010 Novell, Inc. (http://www.novell.com)
 //
 
 //
 
 using System;
 using System.Collections;
-#if NET_2_0
 using System.Collections.Generic;
-#endif
 using System.Text;
 using System.Collections.Specialized;
 using System.Web.Util;
+using System.Globalization;
 
 namespace System.Web.UI
 {
-       #if NET_2_0
-       public sealed
-       #else
-       internal
-       #endif
-               class ClientScriptManager
+       public sealed partial class ClientScriptManager
        {
+               internal const string EventStateFieldName = "__EVENTVALIDATION";
+               
                Hashtable registeredArrayDeclares;
                ScriptEntry clientScriptBlocks;
                ScriptEntry startupScriptBlocks;
                internal Hashtable hiddenFields;
                ScriptEntry submitStatements;
-               ScriptEntry scriptIncludes;
                Page page;
-#if NET_2_0
-               List <int> eventValidationValues;
+               int [] eventValidationValues;
+               int eventValidationPos = 0;
                Hashtable expandoAttributes;
                bool _hasRegisteredForEventValidationOnCallback;
-#endif
+               bool _pageInRender;
+               bool _initCallBackRegistered;
+               bool _webFormClientScriptRendered;
+               bool _webFormClientScriptRequired;
+               
+               internal bool ScriptsPresent {
+                       get {
+                               return _webFormClientScriptRequired ||
+                                       _initCallBackRegistered ||
+                                       _hasRegisteredForEventValidationOnCallback ||
+                                       clientScriptBlocks != null ||
+                                       startupScriptBlocks != null ||
+                                       submitStatements != null ||
+                                       registeredArrayDeclares != null ||
+                                       expandoAttributes != null;
+                       }
+               }
                
                internal ClientScriptManager (Page page)
                {
                        this.page = page;
                }
 
-#if !NET_2_0
-               public string GetPostBackClientEvent (Control control, string argument)
-               {
-                       return GetPostBackEventReference (control, argument);
-               }
-#endif
-
                public string GetPostBackClientHyperlink (Control control, string argument)
                {
                        return "javascript:" + GetPostBackEventReference (control, argument);
                }
        
-#if NET_2_0
                public string GetPostBackClientHyperlink (Control control, string argument, bool registerForEventValidation)
                {
                        if (registerForEventValidation)
                                RegisterForEventValidation (control.UniqueID, argument);
                        return "javascript:" + GetPostBackEventReference (control, argument);
                }
-#endif         
 
-#if !NET_2_0
-               internal
-#else
-               public
-#endif
-               string GetPostBackEventReference (Control control, string argument)
+               public string GetPostBackEventReference (Control control, string argument)
                {
                        if (control == null)
                                throw new ArgumentNullException ("control");
                        
                        page.RequiresPostBackScript ();
-#if NET_2_0
-                       return String.Format ("{0}.__doPostBack('{1}','{2}')", page.theForm, control.UniqueID, argument);
-#else
-                       return String.Format ("__doPostBack('{0}','{1}')", control.UniqueID, argument);
-#endif
+                       if(page.IsMultiForm)
+                               return page.theForm + ".__doPostBack('" + control.UniqueID + "','" + argument + "')";
+                       else
+                               return "__doPostBack('" + control.UniqueID + "','" + argument + "')";
                }
 
-#if NET_2_0
                public string GetPostBackEventReference (Control control, string argument, bool registerForEventValidation)
                {
                        if (control == null)
@@ -150,36 +145,42 @@ namespace System.Web.UI
                        if (actionUrl != null)
                                RegisterHiddenField (Page.PreviousPageID, page.Request.FilePath);
 
-                       string prefix = options.RequiresJavaScriptProtocol ? "javascript:" : "";
-#if TARGET_J2EE
-                       // Allow the page to transform ActionUrl to a portlet action url
-                       if (actionUrl != null && page.PortletNamespace != null) {
-                               actionUrl = page.CreateActionUrl(actionUrl);
-                               prefix += "Portal";
-                       }
-#endif
+                       if(options.TrackFocus)
+                               RegisterHiddenField (Page.LastFocusID, String.Empty);
 
-                       return String.Format ("{0}WebForm_DoPostback({1},{2},{3},{4},{5},{6},{7},{8},{9})", 
-                                       prefix,
-                                       ClientScriptManager.GetScriptLiteral (options.TargetControl.UniqueID), 
-                                       ClientScriptManager.GetScriptLiteral (options.Argument),
-                                       ClientScriptManager.GetScriptLiteral (actionUrl),
-                                       ClientScriptManager.GetScriptLiteral (options.AutoPostBack),
-                                       ClientScriptManager.GetScriptLiteral (options.PerformValidation),
-                                       ClientScriptManager.GetScriptLiteral (options.TrackFocus),
-                                       ClientScriptManager.GetScriptLiteral (options.ClientSubmit),
-                                       ClientScriptManager.GetScriptLiteral (options.ValidationGroup),
-                                       page.theForm
-                               );
+                       string prefix = options.RequiresJavaScriptProtocol ? "javascript:" : String.Empty;
+                       if (page.IsMultiForm)
+                               prefix += page.theForm + ".";
+
+                       return prefix + "WebForm_DoPostback(" +
+                               ClientScriptManager.GetScriptLiteral (options.TargetControl.UniqueID) + "," +
+                               ClientScriptManager.GetScriptLiteral (options.Argument) + "," +
+                               ClientScriptManager.GetScriptLiteral (actionUrl) + "," +
+                               ClientScriptManager.GetScriptLiteral (options.AutoPostBack) + "," +
+                               ClientScriptManager.GetScriptLiteral (options.PerformValidation) + "," +
+                               ClientScriptManager.GetScriptLiteral (options.TrackFocus) + "," +
+                               ClientScriptManager.GetScriptLiteral (options.ClientSubmit) + "," +
+                               ClientScriptManager.GetScriptLiteral (options.ValidationGroup) + ")";
                }
 
                internal void RegisterWebFormClientScript ()
                {
-                       if (IsClientScriptIncludeRegistered (typeof (Page), "webform"))
+                       if (_webFormClientScriptRequired)
                                return;
 
-                       RegisterClientScriptInclude (typeof (Page), "webform", GetWebResourceUrl (typeof (Page), "webform.js"));
                        page.RequiresPostBackScript ();
+                       _webFormClientScriptRequired = true;
+               }
+
+               internal void WriteWebFormClientScript (HtmlTextWriter writer) {
+                       if (!_webFormClientScriptRendered && _webFormClientScriptRequired) {
+                               writer.WriteLine ();
+                               WriteClientScriptInclude (writer, GetWebResourceUrl (typeof (Page), "webform.js"), typeof (Page), "webform.js");
+                               WriteBeginScriptBlock (writer);
+                               writer.WriteLine ("WebForm_Initialize({0});", page.IsMultiForm ? page.theForm : "window");
+                               WriteEndScriptBlock (writer);
+                               _webFormClientScriptRendered = true;
+                       }
                }
                
                public string GetCallbackEventReference (Control control, string argument, string clientCallback, string context)
@@ -199,23 +200,27 @@ namespace System.Web.UI
                        if(!(control is ICallbackEventHandler))
                                throw new InvalidOperationException ("The control must implement the ICallbackEventHandler interface and provide a RaiseCallbackEvent method.");
 
-                       return GetCallbackEventReference (control.UniqueID, argument, clientCallback, context, clientErrorCallback, useAsync);
+                       return GetCallbackEventReference ("'" + control.UniqueID + "'", argument, clientCallback, context, clientErrorCallback, useAsync);
                }
 
                public string GetCallbackEventReference (string target, string argument, string clientCallback, string context, string clientErrorCallback, bool useAsync)
                {
                        RegisterWebFormClientScript ();
-                       
-                       return string.Format ("WebForm_DoCallback('{0}',{1},{2},{3},{4},{5},{6})", target, argument, clientCallback, context, ((clientErrorCallback == null) ? "null" : clientErrorCallback), (useAsync ? "true" : "false"), page.theForm);
+
+                       if (!_initCallBackRegistered) {
+                               _initCallBackRegistered = true;
+                               RegisterStartupScript (typeof (Page), "WebForm_InitCallback", page.WebFormScriptReference + ".WebForm_InitCallback();", true);
+                       }
+                       return page.WebFormScriptReference + ".WebForm_DoCallback(" +
+                               target + "," +
+                               (argument ?? "null") + "," +
+                               clientCallback + "," +
+                               (context ?? "null") + "," +
+                               (clientErrorCallback ?? "null") + "," +
+                               (useAsync ? "true" : "false") + ")";
                }
-#endif
                
-#if NET_2_0
-               public
-#else
-               internal
-#endif
-               string GetWebResourceUrl(Type type, string resourceName)
+               public string GetWebResourceUrl(Type type, string resourceName)
                {
                        if (type == null)
                                throw new ArgumentNullException ("type");
@@ -259,12 +264,12 @@ namespace System.Web.UI
                
                public bool IsClientScriptIncludeRegistered (string key)
                {
-                       return IsScriptRegistered (scriptIncludes, GetType(), key);
+                       return IsClientScriptIncludeRegistered (GetType (), key);
                }
        
                public bool IsClientScriptIncludeRegistered (Type type, string key)
                {
-                       return IsScriptRegistered (scriptIncludes, type, key);
+                       return IsScriptRegistered (clientScriptBlocks, type, "include-" + key);
                }
                
                bool IsScriptRegistered (ScriptEntry scriptList, Type type, string key)
@@ -286,9 +291,15 @@ namespace System.Web.UI
                                registeredArrayDeclares.Add (arrayName, new ArrayList());
        
                        ((ArrayList) registeredArrayDeclares[arrayName]).Add(arrayValue);
+                       page.RequiresFormScriptDeclaration ();
                }
-       
+
                void RegisterScript (ref ScriptEntry scriptList, Type type, string key, string script, bool addScriptTags)
+               {
+                       RegisterScript (ref scriptList, type, key, script, addScriptTags ? ScriptEntryFormat.AddScriptTag : ScriptEntryFormat.None);
+               }
+
+               void RegisterScript (ref ScriptEntry scriptList, Type type, string key, string script, ScriptEntryFormat format)
                {
                        ScriptEntry last = null;
                        ScriptEntry entry = scriptList;
@@ -299,11 +310,8 @@ namespace System.Web.UI
                                last = entry;
                                entry = entry.Next;
                        }
-                       
-                       if (addScriptTags)
-                               script = "<script language=javascript>\n<!--\n" + script + "\n// -->\n</script>";
 
-                       entry = new ScriptEntry (type, key, script);
+                       entry = new ScriptEntry (type, key, script, format);
                        
                        if (last != null) last.Next = entry;
                        else scriptList = entry;
@@ -379,13 +387,12 @@ namespace System.Web.UI
                        if (url == null || url.Length == 0)
                                throw new ArgumentException ("url");
 
-                       RegisterScript (ref scriptIncludes, type, key, url, false);
+                       RegisterScript (ref clientScriptBlocks, type, "include-" + key, url, ScriptEntryFormat.Include);
                }
 
-#if NET_2_0
                public void RegisterClientScriptResource (Type type, string resourceName)
                {
-                       RegisterScript (ref scriptIncludes, type, "resource-" + resourceName, GetWebResourceUrl (type, resourceName), false);
+                       RegisterScript (ref clientScriptBlocks, type, "resource-" + resourceName, GetWebResourceUrl (type, resourceName), ScriptEntryFormat.Include);
                }
 
                public void RegisterExpandoAttribute (string controlId, string attributeName, string attributeValue)
@@ -412,9 +419,29 @@ namespace System.Web.UI
 
                        list.Add (attributeName, encode ? StrUtils.EscapeQuotesAndBackslashes (attributeValue) : attributeValue);
                }
-               
+
+               void EnsureEventValidationArray ()
+               {
+                       if (eventValidationValues == null || eventValidationValues.Length == 0)
+                               eventValidationValues = new int [64];
+
+                       int len = eventValidationValues.Length;
+
+                       if (eventValidationPos >= len) {
+                               int [] tmp = new int [len * 2];
+                               Array.Copy (eventValidationValues, tmp, len);
+                               eventValidationValues = tmp;
+                       }
+               }
+
+               internal void ResetEventValidationState ()
+               {
+                       _pageInRender = true;
+                       eventValidationPos = 0;
+               }
+
                // Implemented following the description in http://odetocode.com/Blogs/scott/archive/2006/03/20/3145.aspx
-               private int CalculateEventHash (string uniqueId, string argument)
+               int CalculateEventHash (string uniqueId, string argument)
                {
                        int uniqueIdHash = uniqueId.GetHashCode ();
                        int argumentHash = String.IsNullOrEmpty (argument) ? 0 : argument.GetHashCode ();
@@ -440,15 +467,16 @@ namespace System.Web.UI
                                return;
                        if (page.IsCallback)
                                _hasRegisteredForEventValidationOnCallback = true;
-                       else if (page.LifeCycle < PageLifeCycle.Render)
+                       else if (!_pageInRender)
                                throw new InvalidOperationException ("RegisterForEventValidation may only be called from the Render method");
-                       if (eventValidationValues == null)
-                               eventValidationValues = new List <int> ();
 
+                       EnsureEventValidationArray ();
                        
                        int hash = CalculateEventHash (uniqueId, argument);
-                       if (eventValidationValues.BinarySearch (hash) < 0)
-                               eventValidationValues.Add (hash);
+                       for (int i = 0; i < eventValidationPos; i++)
+                               if (eventValidationValues [i] == hash)
+                                       return;
+                       eventValidationValues [eventValidationPos++] = hash;
                }
 
                public void ValidateEvent (string uniqueId)
@@ -456,6 +484,11 @@ namespace System.Web.UI
                        ValidateEvent (uniqueId, null);
                }
 
+               ArgumentException InvalidPostBackException ()
+               {
+                       return new ArgumentException ("Invalid postback or callback argument. Event validation is enabled using <pages enableEventValidation=\"true\"/> in configuration or <%@ Page EnableEventValidation=\"true\" %> in a page. For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them. If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation.");
+               }
+               
                public void ValidateEvent (string uniqueId, string argument)
                {
                        if (uniqueId == null || uniqueId.Length == 0)
@@ -463,40 +496,66 @@ namespace System.Web.UI
                        if (!page.EnableEventValidation)
                                return;
                        if (eventValidationValues == null)
-                               goto bad;
+                               throw InvalidPostBackException ();
                        
                        int hash = CalculateEventHash (uniqueId, argument);
-                       if (eventValidationValues.BinarySearch (hash) < 0)
-                               goto bad;
-                       return;
+                       for (int i = 0; i < eventValidationValues.Length; i++)
+                               if (eventValidationValues [i] == hash)
+                                       return;
                        
-                       bad:
-                       throw new ArgumentException ("Invalid postback or callback argument. Event validation is enabled using <pages enableEventValidation=\"true\"/> in configuration or <%@ Page EnableEventValidation=\"true\" %> in a page. For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them. If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation.");
+                       throw InvalidPostBackException ();
                }
-#endif
+
                void WriteScripts (HtmlTextWriter writer, ScriptEntry scriptList)
                {
+                       if (scriptList == null)
+                               return;
+
+                       writer.WriteLine ();
+
                        while (scriptList != null) {
-                               writer.WriteLine (scriptList.Script);
+                               switch (scriptList.Format) {
+                               case ScriptEntryFormat.AddScriptTag:
+                                       EnsureBeginScriptBlock (writer);
+                                       writer.Write (scriptList.Script);
+                                       break;
+                               case ScriptEntryFormat.Include:
+                                       EnsureEndScriptBlock (writer);
+                                       WriteClientScriptInclude (writer, scriptList.Script, scriptList.Type, scriptList.Key);
+                                       break;
+                               default:
+                                       EnsureEndScriptBlock (writer);
+                                       writer.WriteLine (scriptList.Script);
+                                       break;
+                               }
                                scriptList = scriptList.Next;
                        }
+                       EnsureEndScriptBlock (writer);
+               }
+
+               bool _scriptTagOpened;
+
+               void EnsureBeginScriptBlock (HtmlTextWriter writer) {
+                       if (!_scriptTagOpened) {
+                               WriteBeginScriptBlock (writer);
+                               _scriptTagOpened = true;
+                       }
+               }
+
+               void EnsureEndScriptBlock (HtmlTextWriter writer) {
+                       if (_scriptTagOpened) {
+                               WriteEndScriptBlock (writer);
+                               _scriptTagOpened = false;
+                       }
                }
 
-#if NET_2_0
                internal void RestoreEventValidationState (string fieldValue)
                {
                        if (!page.EnableEventValidation || fieldValue == null || fieldValue.Length == 0)
                                return;
                        IStateFormatter fmt = page.GetFormatter ();
-                       int [] eventValues = (int []) fmt.Deserialize (fieldValue);
-#if TARGET_JVM // FIXME: No support yet for passing 'int[]' as 'T[]'
-                       eventValidationValues = new List<int> (eventValues.Length);
-                       for (int i = 0; i < eventValues.Length; i++)
-                               eventValidationValues.Add(eventValues[i]);
-#else
-                       eventValidationValues = new List<int> (eventValues);
-#endif
-                       eventValidationValues.Sort ();
+                       eventValidationValues = (int []) fmt.Deserialize (fieldValue);
+                       eventValidationPos = eventValidationValues.Length;
                }
                
                internal void SaveEventValidationState ()
@@ -513,27 +572,18 @@ namespace System.Web.UI
 
                internal string GetEventValidationStateFormatted ()
                {
-                       if (eventValidationValues == null || eventValidationValues.Count == 0)
+                       if (eventValidationValues == null || eventValidationValues.Length == 0)
                                return null;
 
                        if(page.IsCallback && !_hasRegisteredForEventValidationOnCallback)
                                return null;
 
                        IStateFormatter fmt = page.GetFormatter ();
-                       int [] array = new int [eventValidationValues.Count];
-#if TARGET_JVM // FIXME: No support yet for passing 'int[]' as 'T[]'
-                       ((ICollection)eventValidationValues).CopyTo (array, 0);
-#else
-                       eventValidationValues.CopyTo (array);
-#endif
+                       int [] array = new int [eventValidationPos];
+                       Array.Copy (eventValidationValues, array, eventValidationPos);
                        return fmt.Serialize (array);
                }
 
-               internal string EventStateFieldName
-               {
-                       get { return "__EVENTVALIDATION"; }
-               }
-
                internal void WriteExpandoAttributes (HtmlTextWriter writer)
                {
                        if (expandoAttributes == null)
@@ -553,61 +603,70 @@ namespace System.Web.UI
                        writer.WriteLine ();
                }
 
-#endif
-               internal void WriteBeginScriptBlock (HtmlTextWriter writer)
+               internal const string SCRIPT_BLOCK_START = "//<![CDATA[";
+               internal const string SCRIPT_BLOCK_END = "//]]>";
+               internal const string SCRIPT_ELEMENT_START = @"<script type=""text/javascript"">" + SCRIPT_BLOCK_START;
+               internal const string SCRIPT_ELEMENT_END = SCRIPT_BLOCK_END + "</script>";
+               
+               internal static void WriteBeginScriptBlock (HtmlTextWriter writer)
                {
-                       writer.WriteLine ("<script"+
-#if !NET_2_0
-                               " language=\"javascript\""+
-#endif
-                               " type=\"text/javascript\">");
-                       writer.WriteLine ("<!--");
+                       writer.WriteLine (SCRIPT_ELEMENT_START);
                }
 
-               internal void WriteEndScriptBlock (HtmlTextWriter writer)
+               internal static void WriteEndScriptBlock (HtmlTextWriter writer)
                {
-                       writer.WriteLine ("// -->");
-                       writer.WriteLine ("</script>");
+                       writer.WriteLine (SCRIPT_ELEMENT_END);
                }
                
                internal void WriteHiddenFields (HtmlTextWriter writer)
                {
                        if (hiddenFields == null)
                                return;
-       
+
+                       writer.WriteLine ();
+#if NET_4_0
+                       writer.AddAttribute (HtmlTextWriterAttribute.Class, "aspNetHidden");
+#endif
+                       writer.RenderBeginTag (HtmlTextWriterTag.Div);
+                       int oldIndent = writer.Indent;
+                       writer.Indent = 0;
+                       bool first = true;
+                       var sb = new StringBuilder ();
+                       
                        foreach (string key in hiddenFields.Keys) {
                                string value = hiddenFields [key] as string;
-                               writer.WriteLine ("<input type=\"hidden\" name=\"{0}\" id=\"{0}\" value=\"{1}\" />", key, value);
+                               if (first)
+                                       first = false;
+                               else
+                                       writer.WriteLine ();
+                               sb.Append ("<input type=\"hidden\" name=\"");
+                               sb.Append (key);
+                               sb.Append ("\" id=\"");
+                               sb.Append (key);
+                               sb.Append ("\" value=\"");
+                               sb.Append (HttpUtility.HtmlAttributeEncode (value));
+                               sb.Append ("\" />");
                        }
-       
+                       writer.Write (sb.ToString ());
+                       writer.Indent = oldIndent;
+                       writer.RenderEndTag (); // DIV
+                       writer.WriteLine ();
                        hiddenFields = null;
                }
                
-               internal void WriteClientScriptIncludes (HtmlTextWriter writer)
-               {
-                       ScriptEntry entry = scriptIncludes;
-                       while (entry != null) {
-                               if (!entry.Rendered) {
-#if TARGET_J2EE
-                                       if (!page.IsPortletRender)
-#endif
-                                               writer.WriteLine ("\n<script src=\"{0}\" type=\"text/javascript\"></script>", entry.Script);
-#if TARGET_J2EE
+               internal void WriteClientScriptInclude (HtmlTextWriter writer, string path, Type type, string key) {
+                                       if (!page.IsMultiForm)
+                                               writer.WriteLine ("<script src=\"{0}\" type=\"text/javascript\"></script>", path);
                                        else {
-                                               string scriptKey = "inc_" + entry.Key.GetHashCode ().ToString ("X");
-                                               writer.WriteLine ("\n<script type=\"text/javascript\">");
-                                               writer.WriteLine ("<!--");
-                                               writer.WriteLine ("if (document.{0} == null) {{", scriptKey);
-                                               writer.WriteLine ("\tdocument.{0} = true", scriptKey);
-                                               writer.WriteLine ("\tdocument.write('<script src=\"{0}\" type=\"text/javascript\"><\\/script>'); }}", entry.Script);
-                                               writer.WriteLine ("// -->");
+                                               string scriptKey = "inc_" + (type.FullName + key).GetHashCode ().ToString ("X");
+                                               writer.WriteLine ("<script type=\"text/javascript\">");
+                                               writer.WriteLine (SCRIPT_BLOCK_START);
+                                               writer.WriteLine ("if (!window.{0}) {{", scriptKey);
+                                               writer.WriteLine ("\twindow.{0} = true", scriptKey);
+                                               writer.WriteLine ("\tdocument.write('<script src=\"{0}\" type=\"text/javascript\"><\\/script>'); }}", path);
+                                               writer.WriteLine (SCRIPT_BLOCK_END);
                                                writer.WriteLine ("</script>");
                                        }
-#endif
-                                       entry.Rendered = true;
-                               }
-                               entry = entry.Next;
-                       }
                }
                
                internal void WriteClientScriptBlocks (HtmlTextWriter writer)
@@ -627,7 +686,10 @@ namespace System.Web.UI
                                WriteBeginScriptBlock (writer);
                                IDictionaryEnumerator arrayEnum = registeredArrayDeclares.GetEnumerator();
                                while (arrayEnum.MoveNext()) {
-                                       writer.Write("\tvar ");
+                                       if (page.IsMultiForm)
+                                               writer.Write ("\t" + page.theForm + ".");
+                                       else
+                                               writer.Write ("\tvar ");
                                        writer.Write(arrayEnum.Key);
                                        writer.Write(" =  new Array(");
                                        IEnumerator arrayListEnum = ((ArrayList) arrayEnum.Value).GetEnumerator();
@@ -640,41 +702,23 @@ namespace System.Web.UI
                                                writer.Write(arrayListEnum.Current);
                                        }
                                        writer.WriteLine(");");
-#if TARGET_J2EE
-                                       // in addition, add a form array declaration
-                                       if (page.IsPortletRender) {
-                                               writer.Write ("\t" + page.theForm + ".");
-                                               writer.Write (arrayEnum.Key);
-                                               writer.Write (" = ");
-                                               writer.Write (arrayEnum.Key);
-                                               writer.WriteLine (";");
-                                       }
-#endif
                                }
                                WriteEndScriptBlock (writer);
                                writer.WriteLine ();
                        }
                }
 
-#if NET_2_0
                internal string GetClientValidationEvent (string validationGroup) {
-                       string eventScript = "if (typeof(Page_ClientValidate) == 'function') Page_ClientValidate('" + validationGroup + "');";
-#if TARGET_J2EE
-                       if (page.IsPortletRender)
-                               return "if (typeof(SetValidatorContext) == 'function') SetValidatorContext ('" + page.theForm + "'); " + eventScript;
-#endif
-                       return eventScript;
+                       if (page.IsMultiForm)
+                               return "if (typeof(" + page.theForm + ".Page_ClientValidate) == 'function') " + page.theForm + ".Page_ClientValidate('" + validationGroup + "');";
+                       return "if (typeof(Page_ClientValidate) == 'function') Page_ClientValidate('" + validationGroup + "');";
                }
-#endif
 
                internal string GetClientValidationEvent ()
                {
-                       string eventScript = "if (typeof(Page_ClientValidate) == 'function') Page_ClientValidate();";
-#if TARGET_J2EE
-                       if (page.IsPortletRender)
-                               return "if (typeof(SetValidatorContext) == 'function') SetValidatorContext ('" + page.theForm + "'); " + eventScript;
-#endif
-                       return eventScript;
+                       if (page.IsMultiForm)
+                               return "if (typeof(" + page.theForm + ".Page_ClientValidate) == 'function') " + page.theForm + ".Page_ClientValidate();";
+                       return "if (typeof(Page_ClientValidate) == 'function') Page_ClientValidate();";
                }
 
 
@@ -685,28 +729,17 @@ namespace System.Web.UI
                        StringBuilder sb = new StringBuilder ();
                        ScriptEntry entry = submitStatements;
                        while (entry != null) {
-#if NET_2_0
                                sb.Append (EnsureEndsWithSemicolon (entry.Script));
-#else
-                               sb.Append (entry.Script);
-#endif
                                entry = entry.Next;
                        }
-#if NET_2_0
-                       RegisterClientScriptBlock ("HtmlForm-OnSubmitStatemen",
-@"<script type=""text/javascript"">
-<!--
-" + page.theForm + @".WebForm_OnSubmit = function () {
+                       RegisterClientScriptBlock (GetType(), "HtmlForm-OnSubmitStatemen",
+@"
+" + page.WebFormScriptReference + @".WebForm_OnSubmit = function () {
 " + sb.ToString () + @"
 return true;
 }
-// -->
-</script>");
-                       return "javascript:return this.WebForm_OnSubmit();";
-
-#else
-                       return sb.ToString ();
-#endif
+", true);
+                       return "javascript:return " + page.WebFormScriptReference + ".WebForm_OnSubmit();";
                }
                
                internal static string GetScriptLiteral (object ob)
@@ -715,38 +748,67 @@ return true;
                                return "null";
                        else if (ob is string) {
                                string s = (string)ob;
-                               s = s.Replace ("\"", "\\\"");
-                               return "\"" + s + "\"";
+                               bool escape = false;
+                               int len = s.Length;
+
+                               for (int i = 0; i < len; i++)
+                                       if (s [i] == '\\' || s [i] == '\"') {
+                                               escape = true;
+                                               break;
+                                       }
+
+                               if (!escape)
+                                       return string.Concat ("\"", s, "\"");
+
+                               StringBuilder sb = new StringBuilder (len + 10);
+
+                               sb.Append ('\"');
+                               for (int si = 0; si < len; si++) {
+                                       if (s [si] == '\"')
+                                               sb.Append ("\\\"");
+                                       else if (s [si] == '\\')
+                                               sb.Append ("\\\\");
+                                       else
+                                               sb.Append (s [si]);
+                               }
+                               sb.Append ('\"');
+
+                               return sb.ToString ();
                        } else if (ob is bool) {
-                               return ob.ToString().ToLower();
+                               return ob.ToString ().ToLower (Helpers.InvariantCulture);
                        } else {
                                return ob.ToString ();
                        }
                }
-               
-               class ScriptEntry
+
+               sealed class ScriptEntry
                {
-                       public Type Type;
-                       public string Key;
-                       public string Script;
+                       public readonly Type Type;
+                       public readonly string Key;
+                       public readonly string Script;
+                       public readonly ScriptEntryFormat Format;
                        public ScriptEntry Next;
-                       public bool Rendered;
-                        
-                       public ScriptEntry (Type type, string key, string script)
-                       {
+
+                       public ScriptEntry (Type type, string key, string script, ScriptEntryFormat format) {
                                Key = key;
                                Type = type;
                                Script = script;
+                               Format = format;
                        }
                }
 
-#if NET_2_0
+               enum ScriptEntryFormat
+               {
+                       None,
+                       AddScriptTag,
+                       Include,
+               }
+
                // helper method
                internal static string EnsureEndsWithSemicolon (string value) {
-                       if (value != null && value.Length > 0 && !value.EndsWith (";"))
+                       if (value != null && value.Length > 0 && value [value.Length - 1] != ';')
                                return value += ";";
                        return value;
                }
-#endif
        }
 }