Merge branch 'master' of github.com:mono/mono
[mono.git] / mcs / class / System.Web.Extensions / System.Web.UI / ScriptManager.cs
index b9b415255705fee618d05ad5c531a80e68d2cb6b..4c39f6c4e88347fb0a57e34cf12adb72eeee56fd 100644 (file)
@@ -44,6 +44,7 @@ using System.Threading;
 using System.Web.Script.Serialization;
 using System.Web.Script.Services;
 using System.Xml;
+using System.Collections.ObjectModel;
 
 namespace System.Web.UI
 {
@@ -54,13 +55,14 @@ namespace System.Web.UI
        [PersistChildrenAttribute (false)]
        [AspNetHostingPermissionAttribute (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
        [AspNetHostingPermissionAttribute (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
-       public class ScriptManager : Control, IPostBackDataHandler
+       public class ScriptManager : Control, IPostBackDataHandler, IScriptManager
        {
                // the keywords are used in fomatting async response
                const string updatePanel = "updatePanel";
                const string hiddenField = "hiddenField";
                const string arrayDeclaration = "arrayDeclaration";
                const string scriptBlock = "scriptBlock";
+               const string scriptStartupBlock = "scriptStartupBlock";
                const string expando = "expando";
                const string onSubmit = "onSubmit";
                const string asyncPostBackControlIDs = "asyncPostBackControlIDs";
@@ -81,7 +83,7 @@ namespace System.Web.UI
                const string scriptContentWithTags = "ScriptContentWithTags";
                const string scriptPath = "ScriptPath";
 
-               static readonly object ScriptManagerKey = new object ();
+               static readonly object ScriptManagerKey = typeof (IScriptManager);
 
                int _asyncPostBackTimeout = 90;
                List<Control> _asyncPostBackControls;
@@ -98,12 +100,12 @@ namespace System.Web.UI
                bool _enableScriptGlobalization;
                bool _enableScriptLocalization;
                string _scriptPath;
-               ScriptEntry _clientScriptBlocks;
-               ScriptEntry _startupScriptBlocks;
-               ScriptEntry _scriptIncludes;
-               ScriptEntry _onSubmitStatements;
-               List<ArrayDeclaration> _arrayDeclarations;
-               Hashtable _hiddenFields;
+               List<RegisteredScript> _clientScriptBlocks;
+               List<RegisteredScript> _startupScriptBlocks;
+               List<RegisteredScript> _onSubmitStatements;
+               List<RegisteredArrayDeclaration> _arrayDeclarations;
+               List<RegisteredExpandoAttribute> _expandoAttributes;
+               List<RegisteredHiddenField> _hiddenFields;
                List<IScriptControl> _registeredScriptControls;
                Dictionary<IExtenderControl, Control> _registeredExtenderControls;
                bool? _supportsPartialRendering;
@@ -115,11 +117,12 @@ namespace System.Web.UI
                string _controlIDToFocus;
                bool _allowCustomErrorsRedirect = true;
                string _asyncPostBackErrorMessage;
-               List<DisposeScriptEntry> _disposeScripts;
+               List<RegisteredDisposeScript> _disposeScripts;
                List<ScriptReferenceEntry> _scriptToRegister;
                bool _loadScriptsBeforeUI = true;
                AuthenticationServiceManager _authenticationService;
                ProfileServiceManager _profileService;
+               List<ScriptManagerProxy> _proxies;
 
                [DefaultValue (true)]
                [Category ("Behavior")]
@@ -229,11 +232,11 @@ namespace System.Web.UI
                        get {
                                if (IsDeploymentRetail)
                                        return false;
-#if !TARGET_J2EE
+
                                CompilationSection compilation = (CompilationSection) WebConfigurationManager.GetSection ("system.web/compilation");
                                if (!compilation.Debug && (ScriptMode == ScriptMode.Auto || ScriptMode == ScriptMode.Inherit))
                                        return false;
-#endif
+
                                if (ScriptMode == ScriptMode.Release)
                                        return false;
 
@@ -241,7 +244,7 @@ namespace System.Web.UI
                        }
                }
 
-               bool IsDeploymentRetail {
+               internal bool IsDeploymentRetail {
                        get {
 #if TARGET_J2EE
                                return false;
@@ -391,21 +394,53 @@ namespace System.Web.UI
 
                public static ScriptManager GetCurrent (Page page) {
                        if (page == null)
-                               throw new ArgumentNullException("page");
-                       return (ScriptManager) page.Items [ScriptManagerKey];
+                               throw new ArgumentNullException ("page");
+                       return GetCurrentInternal (page);
                }
 
+               static ScriptManager GetCurrentInternal (Page page)
+               {
+                       if (page == null)
+                               return null;
+
+                       return (ScriptManager) page.Items [ScriptManagerKey];
+               }
+               
                static void SetCurrent (Page page, ScriptManager instance) {
                        page.Items [ScriptManagerKey] = instance;
+                       page.ClientScript.RegisterWebFormClientScript ();
                }
 
+               UpdatePanel FindPanelWithId (string id)
+               {
+                       if (_updatePanels == null)
+                               return null;
+                       foreach (UpdatePanel panel in _updatePanels) {
+                               if (panel.ID == id)
+                                       return panel;
+                       }
+                       return null;
+               }
+               
                protected virtual bool LoadPostData (string postDataKey, NameValueCollection postCollection) {
                        _isInAsyncPostBack = true;
                        string arg = postCollection [postDataKey];
                        if (!String.IsNullOrEmpty (arg)) {
                                string [] args = arg.Split ('|');
-                               _panelToRefreshID = args [0];
-                               _asyncPostBackSourceElementID = args [1];
+                               switch (args.Length) {
+                                       case 1:
+                                               _asyncPostBackSourceElementID = args [0];
+                                               break;
+
+                                       case 2:
+                                               _panelToRefreshID = args [0];
+                                               _asyncPostBackSourceElementID = args [1];
+                                               break;
+
+                                       default: // "impossible situation"
+                                               throw new InvalidOperationException ("Unexpected format of post data.");
+                               }
+                               
                                return true;
                        }
                        return false;
@@ -419,7 +454,7 @@ namespace System.Web.UI
                protected override void OnInit (EventArgs e) {
                        base.OnInit (e);
 
-                       if (GetCurrent (Page) != null)
+                       if (GetCurrentInternal (Page) != null)
                                throw new InvalidOperationException ("Only one instance of a ScriptManager can be added to the page.");
 
                        SetCurrent (Page, this);
@@ -452,11 +487,11 @@ namespace System.Web.UI
                                        StringBuilder sb = new StringBuilder ();
                                        sb.AppendLine ();
                                        for (int i = 0; i < _disposeScripts.Count; i++) {
-                                               DisposeScriptEntry entry = _disposeScripts [i];
+                                               RegisteredDisposeScript entry = _disposeScripts [i];
                                                if (IsMultiForm)
                                                        sb.Append ("Sys.WebForms.PageRequestManager.getInstance($get(\"" + Page.Form.ClientID + "\"))._registerDisposeScript(\"");
                                                else
-                                               sb.Append ("Sys.WebForms.PageRequestManager.getInstance()._registerDisposeScript(\"");
+                                                       sb.Append ("Sys.WebForms.PageRequestManager.getInstance()._registerDisposeScript(\"");
                                                sb.Append (entry.UpdatePanel.ClientID);
                                                sb.Append ("\", ");
                                                sb.Append (JavaScriptSerializer.DefaultSerializer.Serialize (entry.Script)); //JavaScriptSerializer.Serialize used escape script literal 
@@ -489,61 +524,73 @@ namespace System.Web.UI
                        if (IsMultiForm) {
                                ajaxExtensionScript = new ScriptReference ("MicrosoftAjaxExtension.js", String.Empty);
                                OnResolveScriptReference (new ScriptReferenceEventArgs (ajaxExtensionScript));
-                               
+
                                ajaxWebFormsExtensionScript = new ScriptReference ("MicrosoftAjaxWebFormsExtension.js", String.Empty);
                                OnResolveScriptReference (new ScriptReferenceEventArgs (ajaxWebFormsExtensionScript));
                        }
 
                        foreach (ScriptReferenceEntry script in GetScriptReferences ()) {
                                OnResolveScriptReference (new ScriptReferenceEventArgs (script.ScriptReference));
-                               if (!IsInAsyncPostBack || (script.Control != this && HasBeenRendered (script.Control))) {
                                        if (_scriptToRegister == null)
                                                _scriptToRegister = new List<ScriptReferenceEntry> ();
                                        _scriptToRegister.Add (script);
-                               }
                        }
 
                        if (!IsInAsyncPostBack) {
                                // Register Ajax framework script.
-                               RegisterScriptReference (ajaxScript, true);
+                               RegisterScriptReference (this, ajaxScript, true);
                                if (IsMultiForm) {
-                                       RegisterScriptReference (ajaxExtensionScript, true);
+                                       RegisterScriptReference (this, ajaxExtensionScript, true);
                                        RegisterClientScriptBlock (this, typeof (ScriptManager), "Sys.Application", "\nSys.Application._initialize(document.getElementById('" + Page.Form.ClientID + "'));\n", true);
                                }
 
                                StringBuilder sb = new StringBuilder ();
-                               sb.AppendLine ("if (typeof(Sys) === 'undefined') throw new Error('ASP.NET Ajax client-side framework failed to load.');");
+                               sb.AppendLine ("if (typeof(Sys) === 'undefined') throw new Error('ASP.NET Ajax client-side framework failed to load.');");
 
                                ScriptingProfileServiceSection profileService = (ScriptingProfileServiceSection) WebConfigurationManager.GetSection ("system.web.extensions/scripting/webServices/profileService");
-                               if (profileService.Enabled)
+                               if (profileService != null && profileService.Enabled)
                                        sb.AppendLine ("Sys.Services._ProfileService.DefaultWebServicePath = '" + ResolveClientUrl ("~" + System.Web.Script.Services.ProfileService.DefaultWebServicePath) + "';");
-                               if (_profileService != null && !String.IsNullOrEmpty (_profileService.Path))
-                                       sb.AppendLine ("Sys.Services.ProfileService.set_path('" + ResolveUrl (_profileService.Path) + "');");
+                               string profileServicePath = GetProfileServicePath ();
+                               if (!String.IsNullOrEmpty (profileServicePath))
+                                       sb.AppendLine ("Sys.Services.ProfileService.set_path('" + profileServicePath + "');");
 
                                ScriptingAuthenticationServiceSection authenticationService = (ScriptingAuthenticationServiceSection) WebConfigurationManager.GetSection ("system.web.extensions/scripting/webServices/authenticationService");
-                               if (authenticationService.Enabled)
+                               if (authenticationService != null && authenticationService.Enabled) {
                                        sb.AppendLine ("Sys.Services._AuthenticationService.DefaultWebServicePath = '" + ResolveClientUrl ("~/Authentication_JSON_AppService.axd") + "';");
-                               if (_authenticationService != null && !String.IsNullOrEmpty (_authenticationService.Path))
-                                       sb.AppendLine ("Sys.Services.AuthenticationService.set_path('" + ResolveUrl (_authenticationService.Path) + "');");
+                                       if (Page.User.Identity.IsAuthenticated)
+                                               sb.AppendLine ("Sys.Services.AuthenticationService._setAuthenticated(true);");
+                               }
+                               string authenticationServicePath = GetAuthenticationServicePath ();
+                               if (!String.IsNullOrEmpty (authenticationServicePath))
+                                       sb.AppendLine ("Sys.Services.AuthenticationService.set_path('" + authenticationServicePath + "');");
 
                                RegisterClientScriptBlock (this, typeof (ScriptManager), "Framework", sb.ToString (), true);
 
-                               RegisterScriptReference (ajaxWebFormsScript, true);
+                               RegisterScriptReference (this, ajaxWebFormsScript, true);
 
                                if (IsMultiForm)
-                                       RegisterScriptReference (ajaxWebFormsExtensionScript, true);
+                                       RegisterScriptReference (this, ajaxWebFormsExtensionScript, true);
                        }
-
+                       
                        // Register Scripts
                        if (_scriptToRegister != null)
                                for (int i = 0; i < _scriptToRegister.Count; i++)
-                                       RegisterScriptReference (_scriptToRegister [i].ScriptReference, _scriptToRegister [i].LoadScriptsBeforeUI);
+                                       RegisterScriptReference (_scriptToRegister [i].Control, _scriptToRegister [i].ScriptReference, _scriptToRegister [i].LoadScriptsBeforeUI);
 
                        if (!IsInAsyncPostBack) {
                                // Register services
                                if (_services != null && _services.Count > 0) {
                                        for (int i = 0; i < _services.Count; i++) {
-                                               RegisterServiceReference (_services [i]);
+                                               RegisterServiceReference (this, _services [i]);
+                                       }
+                               }
+
+                               if (_proxies != null && _proxies.Count > 0) {
+                                       for (int i = 0; i < _proxies.Count; i++) {
+                                               ScriptManagerProxy proxy = _proxies [i];
+                                               for (int j = 0; j < proxy.Services.Count; j++) {
+                                                       RegisterServiceReference (proxy, proxy.Services [j]);
+                                               }
                                        }
                                }
 
@@ -556,17 +603,87 @@ namespace System.Web.UI
                                if (IsMultiForm)
                                        RegisterStartupScript (this, typeof (ExtenderControl), "Sys.Application.initialize();", "Sys.Application.getInstance($get(\"" + Page.Form.ClientID + "\")).initialize();\n", true);
                                else
-                               RegisterStartupScript (this, typeof (ExtenderControl), "Sys.Application.initialize();", "Sys.Application.initialize();\n", true);
+                                       RegisterStartupScript (this, typeof (ExtenderControl), "Sys.Application.initialize();", "Sys.Application.initialize();\n", true);
                        }
                }
 
+               string GetProfileServicePath () {
+                       if (_profileService != null && !String.IsNullOrEmpty (_profileService.Path))
+                               return ResolveClientUrl (_profileService.Path);
+
+                       if (_proxies != null && _proxies.Count > 0)
+                               for (int i = 0; i < _proxies.Count; i++)
+                                       if (!String.IsNullOrEmpty (_proxies [i].ProfileService.Path))
+                                               return _proxies [i].ResolveClientUrl (_proxies [i].ProfileService.Path);
+                       return null;
+               }
+
+               string GetAuthenticationServicePath () {
+                       if (_authenticationService != null && !String.IsNullOrEmpty (_authenticationService.Path))
+                               return ResolveClientUrl (_authenticationService.Path);
+
+                       if (_proxies != null && _proxies.Count > 0)
+                               for (int i = 0; i < _proxies.Count; i++)
+                                       if (!String.IsNullOrEmpty (_proxies [i].AuthenticationService.Path))
+                                               return _proxies [i].ResolveClientUrl (_proxies [i].AuthenticationService.Path);
+                       return null;
+               }
+
+               public ReadOnlyCollection<RegisteredArrayDeclaration> GetRegisteredArrayDeclarations () {
+                       if (_arrayDeclarations == null)
+                               _arrayDeclarations = new List<RegisteredArrayDeclaration> ();
+                       return new ReadOnlyCollection<RegisteredArrayDeclaration> (_arrayDeclarations);
+               }
+
+               public ReadOnlyCollection<RegisteredScript> GetRegisteredClientScriptBlocks () {
+                       if (_clientScriptBlocks == null)
+                               _clientScriptBlocks = new List<RegisteredScript> ();
+                       return new ReadOnlyCollection<RegisteredScript> (_clientScriptBlocks);
+               }
+
+               public ReadOnlyCollection<RegisteredDisposeScript> GetRegisteredDisposeScripts () {
+                       if (_disposeScripts == null)
+                               _disposeScripts = new List<RegisteredDisposeScript> ();
+                       return new ReadOnlyCollection<RegisteredDisposeScript> (_disposeScripts);
+               }
+
+               public ReadOnlyCollection<RegisteredExpandoAttribute> GetRegisteredExpandoAttributes () {
+                       if (_expandoAttributes == null)
+                               _expandoAttributes = new List<RegisteredExpandoAttribute> ();
+                       return new ReadOnlyCollection<RegisteredExpandoAttribute> (_expandoAttributes);
+               }
+
+               public ReadOnlyCollection<RegisteredHiddenField> GetRegisteredHiddenFields () {
+                       if (_hiddenFields == null)
+                               _hiddenFields = new List<RegisteredHiddenField> ();
+                       return new ReadOnlyCollection<RegisteredHiddenField> (_hiddenFields);
+               }
+
+               public ReadOnlyCollection<RegisteredScript> GetRegisteredOnSubmitStatements () {
+                       if (_onSubmitStatements == null)
+                               _onSubmitStatements = new List<RegisteredScript> ();
+                       return new ReadOnlyCollection<RegisteredScript> (_onSubmitStatements);
+               }
+
+               public ReadOnlyCollection<RegisteredScript> GetRegisteredStartupScripts () {
+                       if (_startupScriptBlocks == null)
+                               _startupScriptBlocks = new List<RegisteredScript> ();
+                       return new ReadOnlyCollection<RegisteredScript> (_startupScriptBlocks);
+               }
+
 #if TARGET_J2EE
+               bool _isMultiForm = false;
+               bool _isMultiFormInited = false;
+
                bool IsMultiForm {
                        get {
-                               Mainsoft.Web.Configuration.PagesSection pageSection = (Mainsoft.Web.Configuration.PagesSection) WebConfigurationManager.GetSection ("mainsoft.web/pages");
-                               if (pageSection != null)
-                                       return pageSection.MultiForm;
-                               return false;
+                               if (!_isMultiFormInited) {
+                                       string isMultiForm = WebConfigurationManager.AppSettings ["mainsoft.use.portlet.namespace"];
+                                       _isMultiForm = isMultiForm != null ? Boolean.Parse (isMultiForm) : false;
+
+                                       _isMultiFormInited = true;
+                               }
+                               return _isMultiForm;
                        }
                }
 #else
@@ -575,12 +692,21 @@ namespace System.Web.UI
                }
 #endif
 
-               static bool HasBeenRendered (Control control) {
+               bool PanelRequiresUpdate (UpdatePanel panel)
+               {
+                       if (panel == null || _panelsToRefresh == null || _panelsToRefresh.Count == 0)
+                               return false;
+
+                       return _panelsToRefresh.Contains (panel);
+               }
+               
+               bool HasBeenRendered (Control control)
+               {
                        if (control == null)
                                return false;
 
-                       UpdatePanel parent = control.Parent as UpdatePanel;
-                       if (parent != null && parent.RequiresUpdate)
+                       UpdatePanel panel = control as UpdatePanel;
+                       if (PanelRequiresUpdate (panel))
                                return true;
 
                        return HasBeenRendered (control.Parent);
@@ -593,6 +719,14 @@ namespace System.Web.UI
                                }
                        }
 
+                       if (_proxies != null && _proxies.Count > 0) {
+                               for (int i = 0; i < _proxies.Count; i++) {
+                                       ScriptManagerProxy proxy = _proxies [i];
+                                       for (int j = 0; j < proxy.Scripts.Count; j++)
+                                               yield return new ScriptReferenceEntry (proxy, proxy.Scripts [j], LoadScriptsBeforeUI);
+                               }
+                       }
+
                        if (_registeredScriptControls != null && _registeredScriptControls.Count > 0) {
                                for (int i = 0; i < _registeredScriptControls.Count; i++) {
                                        IEnumerable<ScriptReference> scripts = _registeredScriptControls [i].GetScriptReferences ();
@@ -617,29 +751,29 @@ namespace System.Web.UI
                                ResolveScriptReference (this, e);
                }
 
-               protected virtual void RaisePostDataChangedEvent () {
-                       UpdatePanel up = Page.FindControl (_panelToRefreshID) as UpdatePanel;
-                       if (up != null && up.ChildrenAsTriggers)
-                               up.Update ();
-               }
-
-               public static void RegisterArrayDeclaration (Control control, string arrayName, string arrayValue) {
-                       RegisterArrayDeclaration (control.Page, arrayName, arrayValue);
+               protected virtual void RaisePostDataChangedEvent ()
+               {
+                       // Why override?
                }
 
                public static void RegisterArrayDeclaration (Page page, string arrayName, string arrayValue) {
-                       ScriptManager sm = GetCurrent (page);
-                       if (sm.IsInAsyncPostBack)
-                               sm.RegisterArrayDeclaration (arrayName, arrayValue);
-                       else
-                               page.ClientScript.RegisterArrayDeclaration (arrayName, arrayValue);
+                       RegisterArrayDeclaration ((Control) page, arrayName, arrayValue);
                }
 
-               void RegisterArrayDeclaration (string arrayName, string arrayValue) {
-                       if (_arrayDeclarations == null)
-                               _arrayDeclarations = new List<ArrayDeclaration> ();
+               public static void RegisterArrayDeclaration (Control control, string arrayName, string arrayValue) {
+                       Page page = control.Page;
+                       ScriptManager sm = GetCurrentInternal (page);
+
+                       if (sm == null)
+                               return;
+                       
+                       if (sm._arrayDeclarations == null)
+                               sm._arrayDeclarations = new List<RegisteredArrayDeclaration> ();
+
+                       sm._arrayDeclarations.Add (new RegisteredArrayDeclaration (control, arrayName, arrayValue));
 
-                       _arrayDeclarations.Add (new ArrayDeclaration (arrayName, arrayValue));
+                       if (!sm.IsInAsyncPostBack)
+                               page.ClientScript.RegisterArrayDeclaration (arrayName, arrayValue);
                }
 
                public void RegisterAsyncPostBackControl (Control control) {
@@ -655,102 +789,85 @@ namespace System.Web.UI
                        _asyncPostBackControls.Add (control);
                }
 
-               public static void RegisterClientScriptBlock (Control control, Type type, string key, string script, bool addScriptTags) {
-                       RegisterClientScriptBlock (control.Page, type, key, script, addScriptTags);
-               }
-
                public static void RegisterClientScriptBlock (Page page, Type type, string key, string script, bool addScriptTags) {
-                       ScriptManager sm = GetCurrent (page);
-                       if (sm.IsInAsyncPostBack)
-                               RegisterScript (ref sm._clientScriptBlocks, type, key, script, addScriptTags ? ScriptEntryType.ScriptContentNoTags : ScriptEntryType.ScriptContentWithTags);
-                       else
-                               page.ClientScript.RegisterClientScriptBlock (type, key, script, addScriptTags);
+                       RegisterClientScriptBlock ((Control) page, type, key, script, addScriptTags);
                }
 
-               public static void RegisterClientScriptInclude (Control control, Type type, string key, string url) {
-                       RegisterClientScriptInclude (control.Page, type, key, url);
+               public static void RegisterClientScriptBlock (Control control, Type type, string key, string script, bool addScriptTags) {
+                       Page page = control.Page;
+                       ScriptManager sm = GetCurrentInternal (page);
+
+                       if (sm == null)
+                               return;
+                       
+                       RegisterScript (ref sm._clientScriptBlocks, control, type, key, script, null, addScriptTags, RegisteredScriptType.ClientScriptBlock);
+
+                       if (!sm.IsInAsyncPostBack)
+                               page.ClientScript.RegisterClientScriptBlock (type, key, script, addScriptTags);
                }
 
                public static void RegisterClientScriptInclude (Page page, Type type, string key, string url) {
-                       ScriptManager sm = GetCurrent (page);
-                       if (sm.IsInAsyncPostBack)
-                               RegisterScript (ref sm._scriptIncludes, type, key, url, ScriptEntryType.ScriptPath);
-                       else
-                               page.ClientScript.RegisterClientScriptInclude (type, key, url);
+                       RegisterClientScriptInclude ((Control) page, type, key, url);
                }
 
-               public static void RegisterClientScriptResource (Control control, Type type, string resourceName) {
-                       RegisterClientScriptResource (control.Page, type, resourceName);
+               public static void RegisterClientScriptInclude (Control control, Type type, string key, string url) {
+                       Page page = control.Page;
+                       ScriptManager sm = GetCurrentInternal (page);
+
+                       if (sm == null)
+                               return;
+                       
+                       RegisterScript (ref sm._clientScriptBlocks, control, type, key, null, url, false, RegisteredScriptType.ClientScriptInclude);
+
+                       if (!sm.IsInAsyncPostBack)
+                               page.ClientScript.RegisterClientScriptInclude (type, key, url);
                }
 
                public static void RegisterClientScriptResource (Page page, Type type, string resourceName) {
-                       RegisterClientScriptInclude (page, type, "resource-" + resourceName, ScriptResourceHandler.GetResourceUrl (type.Assembly, resourceName, true));
+                       RegisterClientScriptResource ((Control) page, type, resourceName);
                }
 
-               void RegisterScriptReference (ScriptReference script, bool loadScriptsBeforeUI) {
-
-                       bool isDebugMode = IsDeploymentRetail ? false : (script.ScriptModeInternal == ScriptMode.Inherit ? IsDebuggingEnabled : (script.ScriptModeInternal == ScriptMode.Debug));
-                       string url;
-                       if (!String.IsNullOrEmpty (script.Path)) {
-                               url = GetScriptName (ResolveClientUrl (script.Path), isDebugMode, EnableScriptLocalization ? script.ResourceUICultures : null);
-                       }
-                       else if (!String.IsNullOrEmpty (script.Name)) {
-                               Assembly assembly;
-                               if (String.IsNullOrEmpty (script.Assembly))
-                                       assembly = typeof (ScriptManager).Assembly;
-                               else
-                                       assembly = Assembly.Load (script.Assembly);
-                               string name = GetScriptName (script.Name, isDebugMode, null);
-                               if (script.IgnoreScriptPath || String.IsNullOrEmpty (ScriptPath))
-                                       url = ScriptResourceHandler.GetResourceUrl (assembly, name, script.NotifyScriptLoaded);
-                               else {
-                                       AssemblyName an = assembly.GetName ();
-                                       url = ResolveClientUrl (String.Concat (VirtualPathUtility.AppendTrailingSlash (ScriptPath), an.Name, '/', an.Version, '/', name));
-                               }
-                       }
-                       else {
-                               throw new InvalidOperationException ("Name and Path cannot both be empty.");
-                       }
+               public static void RegisterClientScriptResource (Control control, Type type, string resourceName) {
+                       RegisterClientScriptInclude (control, type, resourceName, ScriptResourceHandler.GetResourceUrl (type.Assembly, resourceName, true));
+               }
 
+               void RegisterScriptReference (Control control, ScriptReference script, bool loadScriptsBeforeUI)
+               {
+                       string scriptPath = script.Path;
+                       string url = script.GetUrl (this, false);
+                       if (control != this && !String.IsNullOrEmpty (scriptPath))
+                               url = control.ResolveClientUrl (url);
+                       
                        if (loadScriptsBeforeUI)
-                               RegisterClientScriptInclude (this, typeof (ScriptManager), url, url);
+                               RegisterClientScriptInclude (control, typeof (ScriptManager), url, url);
                        else
-                               RegisterStartupScript (this, typeof (ScriptManager), url, String.Format ("<script src=\"{0}\" type=\"text/javascript\"></script>", url), false);
-               }
-
-               static string GetScriptName (string releaseName, bool isDebugMode, string [] supportedUICultures) {
-                       if (!isDebugMode && (supportedUICultures == null || supportedUICultures.Length == 0))
-                               return releaseName;
-
-                       if (releaseName.Length < 3 || !releaseName.EndsWith (".js", StringComparison.OrdinalIgnoreCase))
-                               throw new InvalidOperationException (String.Format ("'{0}' is not a valid script path.  The path must end in '.js'.", releaseName));
-
-                       StringBuilder sb = new StringBuilder (releaseName);
-                       sb.Length -= 3;
-                       if (isDebugMode)
-                               sb.Append (".debug");
-                       string culture = Thread.CurrentThread.CurrentUICulture.Name;
-                       if (supportedUICultures != null && Array.IndexOf<string> (supportedUICultures, culture) >= 0)
-                               sb.AppendFormat (".{0}", culture);
-                       sb.Append (".js");
-
-                       return sb.ToString ();
+                               RegisterStartupScript (control, typeof (ScriptManager), url, String.Format ("<script src=\"{0}\" type=\"text/javascript\"></script>", url), false);
                }
 
-               void RegisterServiceReference (ServiceReference serviceReference) {
+               void RegisterServiceReference (Control control, ServiceReference serviceReference)
+               {
                        if (serviceReference.InlineScript) {
-                               string url = ResolveUrl (serviceReference.Path);
-                               LogicalTypeInfo logicalTypeInfo = LogicalTypeInfo.GetLogicalTypeInfo (WebServiceParser.GetCompiledType (url, Context), url);
-                               RegisterClientScriptBlock (this, typeof (ScriptManager), url, logicalTypeInfo.Proxy, true);
+                               string url = control.ResolveUrl (serviceReference.Path);
+                               Type type = WebServiceParser.GetCompiledType (url, Context);
+                               if (type != null) {
+                                       object[] attributes = type.GetCustomAttributes (typeof (ScriptServiceAttribute), true);
+                                       if (attributes.Length == 0)
+                                               throw new InvalidOperationException ("Only Web services with a [ScriptService] attribute on the class definition can be called from script.");
+                               }
+                               
+                               LogicalTypeInfo logicalTypeInfo = LogicalTypeInfo.GetLogicalTypeInfo (type, url);
+                               RegisterClientScriptBlock (control, typeof (ScriptManager), url, logicalTypeInfo.Proxy, true);
                        }
                        else {
 #if TARGET_J2EE
                                string pathInfo = "/js.invoke";
 #else
                                string pathInfo = "/js";
+                               if (IsDebuggingEnabled)
+                                       pathInfo += "debug";
 #endif
-                               string url = String.Concat (ResolveClientUrl (serviceReference.Path), pathInfo);
-                               RegisterClientScriptInclude (this, typeof (ScriptManager), url, url);
+                               string url = String.Concat (control.ResolveClientUrl (serviceReference.Path), pathInfo);
+                               RegisterClientScriptInclude (control, typeof (ScriptManager), url, url);
                        }
                }
 
@@ -784,8 +901,8 @@ namespace System.Web.UI
                                return;
 
                        if (_disposeScripts == null)
-                               _disposeScripts = new List<DisposeScriptEntry> ();
-                       _disposeScripts.Add (new DisposeScriptEntry (updatePanel, disposeScript));
+                               _disposeScripts = new List<RegisteredDisposeScript> ();
+                       _disposeScripts.Add (new RegisteredDisposeScript (control, disposeScript, updatePanel));
                }
 
                static UpdatePanel GetUpdatePanel (Control control) {
@@ -801,46 +918,54 @@ namespace System.Web.UI
 
                public static void RegisterExpandoAttribute (Control control, string controlId, string attributeName, string attributeValue, bool encode) {
                        Page page = control.Page;
-                       ScriptManager sm = GetCurrent (page);
-                       if (sm.IsInAsyncPostBack)
-                               sm.RegisterExpandoAttribute (controlId, attributeName, attributeValue, encode);
-                       else
+                       ScriptManager sm = GetCurrentInternal (page);
+
+                       if (sm == null)
+                               return;
+                       
+                       if (sm._expandoAttributes == null)
+                               sm._expandoAttributes = new List<RegisteredExpandoAttribute> ();
+
+                       sm._expandoAttributes.Add (new RegisteredExpandoAttribute (control, controlId, attributeName, attributeValue, encode));
+
+                       if (!sm.IsInAsyncPostBack)
                                page.ClientScript.RegisterExpandoAttribute (controlId, attributeName, attributeValue, encode);
                }
 
-               private void RegisterExpandoAttribute (string controlId, string attributeName, string attributeValue, bool encode) {
-                       // seems MS do nothing.
+               public static void RegisterHiddenField (Page page, string hiddenFieldName, string hiddenFieldInitialValue) {
+                       RegisterHiddenField ((Control) page, hiddenFieldName, hiddenFieldInitialValue);
                }
 
                public static void RegisterHiddenField (Control control, string hiddenFieldName, string hiddenFieldInitialValue) {
-                       RegisterHiddenField (control.Page, hiddenFieldName, hiddenFieldInitialValue);
-               }
+                       Page page = control.Page;
+                       ScriptManager sm = GetCurrentInternal (page);
 
-               public static void RegisterHiddenField (Page page, string hiddenFieldName, string hiddenFieldInitialValue) {
-                       ScriptManager sm = GetCurrent (page);
-                       if (sm.IsInAsyncPostBack)
-                               sm.RegisterHiddenField (hiddenFieldName, hiddenFieldInitialValue);
-                       else
+                       if (sm == null)
+                               return;
+                       
+                       if (sm._hiddenFields == null)
+                               sm._hiddenFields = new List<RegisteredHiddenField> ();
+
+                       sm._hiddenFields.Add (new RegisteredHiddenField (control, hiddenFieldName, hiddenFieldInitialValue));
+
+                       if (!sm.IsInAsyncPostBack)
                                page.ClientScript.RegisterHiddenField (hiddenFieldName, hiddenFieldInitialValue);
                }
 
-               void RegisterHiddenField (string hiddenFieldName, string hiddenFieldInitialValue) {
-                       if (_hiddenFields == null)
-                               _hiddenFields = new Hashtable ();
-
-                       if (!_hiddenFields.ContainsKey (hiddenFieldName))
-                               _hiddenFields.Add (hiddenFieldName, hiddenFieldInitialValue);
+               public static void RegisterOnSubmitStatement (Page page, Type type, string key, string script) {
+                       RegisterOnSubmitStatement ((Control) page, type, key, script);
                }
 
                public static void RegisterOnSubmitStatement (Control control, Type type, string key, string script) {
-                       RegisterOnSubmitStatement (control.Page, type, key, script);
-               }
+                       Page page = control.Page;
+                       ScriptManager sm = GetCurrentInternal (page);
 
-               public static void RegisterOnSubmitStatement (Page page, Type type, string key, string script) {
-                       ScriptManager sm = GetCurrent (page);
-                       if (sm.IsInAsyncPostBack)
-                               RegisterScript (ref sm._onSubmitStatements, type, key, script, ScriptEntryType.OnSubmit);
-                       else
+                       if (sm == null)
+                               return;
+                       
+                       RegisterScript (ref sm._onSubmitStatements, control, type, key, script, null, false, RegisteredScriptType.OnSubmitStatement);
+
+                       if (!sm.IsInAsyncPostBack)
                                page.ClientScript.RegisterOnSubmitStatement (type, key, script);
                }
 
@@ -875,7 +1000,7 @@ namespace System.Web.UI
                                return;
 
                        Control targetControl = _registeredExtenderControls [extenderControl];
-                       RegisterScriptDescriptors (extenderControl.GetScriptDescriptors (targetControl));
+                       RegisterScriptDescriptors ((Control) extenderControl, extenderControl.GetScriptDescriptors (targetControl));
                }
 
                public void RegisterScriptDescriptors (IScriptControl scriptControl) {
@@ -885,14 +1010,13 @@ namespace System.Web.UI
                        if (_registeredScriptControls == null || !_registeredScriptControls.Contains (scriptControl))
                                return;
 
-                       RegisterScriptDescriptors (scriptControl.GetScriptDescriptors ());
+                       RegisterScriptDescriptors ((Control) scriptControl, scriptControl.GetScriptDescriptors ());
                }
 
-               void RegisterScriptDescriptors (IEnumerable<ScriptDescriptor> scriptDescriptors) {
+               void RegisterScriptDescriptors (Control control, IEnumerable<ScriptDescriptor> scriptDescriptors)
+               {
                        if (scriptDescriptors == null)
                                return;
-                       if (IsInAsyncPostBack && !IsInPartialRendering)
-                               return;
 
                        StringBuilder sb = new StringBuilder ();
                        foreach (ScriptDescriptor scriptDescriptor in scriptDescriptors) {
@@ -901,23 +1025,29 @@ namespace System.Web.UI
                                        sb.AppendLine ("Sys.Application.getInstance($get(\"" + Page.Form.ClientID + "\")).add_init(function() {");
                                }
                                else
-                               sb.AppendLine ("Sys.Application.add_init(function() {");
+                                       sb.AppendLine ("Sys.Application.add_init(function() {");
+                               sb.Append ("\t");
                                sb.AppendLine (scriptDescriptor.GetScript ());
                                sb.AppendLine ("});");
                        }
                        string script = sb.ToString ();
-                       RegisterStartupScript (this, typeof (ExtenderControl), script, script, true);
+                       RegisterStartupScript (control, typeof (ScriptDescriptor), script, script, true);
                }
 
-               public static void RegisterStartupScript (Control control, Type type, string key, string script, bool addScriptTags) {
-                       RegisterStartupScript (control.Page, type, key, script, addScriptTags);
+               public static void RegisterStartupScript (Page page, Type type, string key, string script, bool addScriptTags) {
+                       RegisterStartupScript ((Control) page, type, key, script, addScriptTags);
                }
 
-               public static void RegisterStartupScript (Page page, Type type, string key, string script, bool addScriptTags) {
-                       ScriptManager sm = GetCurrent (page);
-                       if (sm.IsInAsyncPostBack)
-                               RegisterScript (ref sm._startupScriptBlocks, type, key, script, addScriptTags ? ScriptEntryType.ScriptContentNoTags : ScriptEntryType.ScriptContentWithTags);
-                       else
+               public static void RegisterStartupScript (Control control, Type type, string key, string script, bool addScriptTags) {
+                       Page page = control.Page;
+                       ScriptManager sm = GetCurrentInternal (page);
+
+                       if (sm == null)
+                               return;
+                       
+                       RegisterScript (ref sm._startupScriptBlocks, control, type, key, script, null, addScriptTags, RegisteredScriptType.ClientStartupScript);
+
+                       if (!sm.IsInAsyncPostBack)
                                page.ClientScript.RegisterStartupScript (type, key, script, addScriptTags);
                }
 
@@ -945,23 +1075,11 @@ namespace System.Web.UI
                                _registeredExtenderControls.Add (extenderControl, targetControl);
                }
 
-               static void RegisterScript (ref ScriptEntry scriptList, Type type, string key, string script, ScriptEntryType scriptEntryType) {
-                       ScriptEntry last = null;
-                       ScriptEntry entry = scriptList;
+               static void RegisterScript (ref List<RegisteredScript> scriptList, Control control, Type type, string key, string script, string url, bool addScriptTag, RegisteredScriptType scriptType) {
+                       if (scriptList == null)
+                               scriptList = new List<RegisteredScript> ();
 
-                       while (entry != null) {
-                               if (entry.Type == type && entry.Key == key)
-                                       return;
-                               last = entry;
-                               entry = entry.Next;
-                       }
-
-                       entry = new ScriptEntry (type, key, script, scriptEntryType);
-
-                       if (last != null)
-                               last.Next = entry;
-                       else
-                               scriptList = entry;
+                       scriptList.Add (new RegisteredScript (control, type, key, script, url, addScriptTag, scriptType));
                }
 
                protected override void Render (HtmlTextWriter writer) {
@@ -974,9 +1092,18 @@ namespace System.Web.UI
                                writer.WriteLine ("//<![CDATA[");
                                writer.WriteLine ("Sys.WebForms.PageRequestManager._initialize('{0}', document.getElementById('{1}'));", UniqueID, Page.Form.ClientID);
                                if (IsMultiForm)
-                                       writer.WriteLine ("Sys.WebForms.PageRequestManager.getInstance($get(\"{0}\"))._updateControls([{1}], [{2}], [{3}], {4});", Page.Form.ClientID, FormatUpdatePanelIDs (_updatePanels, true), FormatListIDs (_asyncPostBackControls, true), FormatListIDs (_postBackControls, true), AsyncPostBackTimeout);
+                                       writer.WriteLine ("Sys.WebForms.PageRequestManager.getInstance($get(\"{0}\"))._updateControls([{1}], [{2}], [{3}], {4});",
+                                                         Page.Form.ClientID,
+                                                         FormatUpdatePanelIDs (_updatePanels, true),
+                                                         FormatListIDs (_asyncPostBackControls, true, false),
+                                                         FormatListIDs (_postBackControls, true, false),
+                                                         AsyncPostBackTimeout);
                                else
-                               writer.WriteLine ("Sys.WebForms.PageRequestManager.getInstance()._updateControls([{0}], [{1}], [{2}], {3});", FormatUpdatePanelIDs (_updatePanels, true), FormatListIDs (_asyncPostBackControls, true), FormatListIDs (_postBackControls, true), AsyncPostBackTimeout);
+                                       writer.WriteLine ("Sys.WebForms.PageRequestManager.getInstance()._updateControls([{0}], [{1}], [{2}], {3});",
+                                                         FormatUpdatePanelIDs (_updatePanels, true),
+                                                         FormatListIDs (_asyncPostBackControls, true, false),
+                                                         FormatListIDs (_postBackControls, true, false),
+                                                         AsyncPostBackTimeout);
                                writer.WriteLine ("//]]");
                                writer.WriteLine ("</script>");
                        }
@@ -988,21 +1115,29 @@ namespace System.Web.UI
                                return null;
 
                        StringBuilder sb = new StringBuilder ();
-                       for (int i = 0; i < list.Count; i++) {
-                               sb.AppendFormat ("{0}{1}{2}{0},", useSingleQuote ? "'" : String.Empty, list [i].ChildrenAsTriggers ? "t" : "f", list [i].UniqueID);
+                       foreach (UpdatePanel panel in list) {
+                               if (!panel.Visible)
+                                       continue;
+                               
+                               sb.AppendFormat ("{0}{1}{2}{0},", useSingleQuote ? "'" : String.Empty, panel.ChildrenAsTriggers ? "t" : "f", panel.UniqueID);
                        }
+                       
                        if (sb.Length > 0)
                                sb.Length--;
 
                        return sb.ToString ();
                }
 
-               static string FormatListIDs<T> (List<T> list, bool useSingleQuote) where T : Control {
+               static string FormatListIDs<T> (List<T> list, bool useSingleQuote, bool skipInvisible) where T : Control
+               {
                        if (list == null || list.Count == 0)
                                return null;
 
                        StringBuilder sb = new StringBuilder ();
                        for (int i = 0; i < list.Count; i++) {
+                               if (skipInvisible && !list [i].Visible)
+                                       continue;
+                               
                                sb.AppendFormat ("{0}{1}{0},", useSingleQuote ? "'" : String.Empty, list [i].UniqueID);
                        }
                        if (sb.Length > 0)
@@ -1060,8 +1195,15 @@ namespace System.Web.UI
 #endif
                        HttpException httpEx = ex as HttpException;
                        string message = AsyncPostBackErrorMessage;
-                       if (String.IsNullOrEmpty (message) && writeMessage)
-                               message = ex.Message;
+                       if (String.IsNullOrEmpty (message) && writeMessage) {
+                               HttpContext ctx = HttpContext.Current;
+                               
+                               if (IsDebuggingEnabled)
+                                       message = ex.ToString ();
+                               else
+                                       message = ex.Message;
+                       }
+                       
                        WriteCallbackOutput (output, error, httpEx == null ? "500" : httpEx.GetHttpCode ().ToString (), message);
                }
 
@@ -1069,11 +1211,18 @@ namespace System.Web.UI
                        WriteCallbackOutput (output, pageRedirect, null, redirectUrl);
                }
 
-               internal void WriteCallbackPanel (TextWriter output, UpdatePanel panel, StringBuilder panelOutput) {
+               void RegisterPanelForRefresh (UpdatePanel panel)
+               {
                        if (_panelsToRefresh == null)
                                _panelsToRefresh = new List<UpdatePanel> ();
-                       _panelsToRefresh.Add (panel);
+                       else if (_panelsToRefresh.Contains (panel))
+                               return;
 
+                       _panelsToRefresh.Add (panel);
+               }
+               
+               internal void WriteCallbackPanel (TextWriter output, UpdatePanel panel, StringBuilder panelOutput)
+               {
                        WriteCallbackOutput (output, updatePanel, panel.ClientID, panelOutput);
                }
 
@@ -1107,18 +1256,89 @@ namespace System.Web.UI
                        output.Write ('|');
                }
 
-               void RenderPageCallback (HtmlTextWriter output, Control container) {
+               void RenderPageCallback (HtmlTextWriter output, Control container)
+               {
                        Page page = (Page) container;
 
+                       // MSDN: http://msdn.microsoft.com/en-us/library/system.web.ui.updatepanel.aspx
+                       //
+                       // Refreshing UpdatePanel Content
+                       //
+                       // When partial-page rendering is enabled, a control can perform a postback
+                       // that updates the whole page or an asynchronous postback that updates the
+                       // content of one or more UpdatePanel controls. Whether a control causes an
+                       // asynchronous postback and updates an UpdatePanel control depends on the
+                       // following:
+                       //
+                       // * If the UpdateMode property of the UpdatePanel control is set to Always,
+                       //   the UpdatePanel control's content is updated on every postback that
+                       //   originates from the page. This includes asynchronous postbacks from
+                       //   controls that are inside other UpdatePanel controls and postbacks from
+                       //   controls that are not inside UpdatePanel controls.
+                       //
+                       // * If the UpdateMode property is set to Conditional, the UpdatePanel
+                       //   control's content is updated in the following circumstances:
+                       //
+                       //       o When you call the Update method of the UpdatePanel control
+                       //         explicitly.
+                       //       o When the UpdatePanel control is nested inside another UpdatePanel
+                       //         control, and the parent panel is updated.
+                       //       o When a postback is caused by a control that is defined as a
+                       //         trigger by using the Triggers property of the UpdatePanel
+                       //         control. In this scenario, the control explicitly triggers an
+                       //         update of the panel content. The control can be either inside or
+                       //         outside the UpdatePanel control that the trigger is associated
+                       //         with.
+                       //       o When the ChildrenAsTriggers property is set to true and a child
+                       //         control of the UpdatePanel control causes a postback. Child
+                       //         controls of nested UpdatePanel controls do not cause an update to
+                       //         the outer UpdatePanel control unless they are explicitly defined
+                       //         as triggers.
+                       //
+                       if (_updatePanels != null && _updatePanels.Count > 0) {
+                               bool needsUpdate;
+                               
+                               foreach (UpdatePanel panel in _updatePanels) {
+                                       if (panel.RequiresUpdate || (!String.IsNullOrEmpty (_panelToRefreshID) && String.Compare (_panelToRefreshID, panel.UniqueID, StringComparison.Ordinal) == 0))
+                                               needsUpdate = true;
+                                       else
+                                               needsUpdate = false;
+                                       
+                                       if (needsUpdate == false) {
+                                               Control parent = panel.Parent;
+                                               UpdatePanel parentPanel;
+                                               
+                                               bool havePanelsToRefresh = _panelsToRefresh != null ? _panelsToRefresh.Count > 0 : false;
+                                               while (parent != null) {
+                                                       parentPanel = parent as UpdatePanel;
+                                                       if (havePanelsToRefresh && parentPanel != null && _panelsToRefresh.Contains (parentPanel)) {
+                                                               needsUpdate = true;
+                                                               break;
+                                                       }
+                                                       parent = parent.Parent;
+                                               }
+                                       }
+                                       
+                                       panel.SetInPartialRendering (needsUpdate);
+                                       if (needsUpdate)
+                                               RegisterPanelForRefresh (panel);
+                               }
+                       }
+                       
                        page.Form.SetRenderMethodDelegate (RenderFormCallback);
                        HtmlTextParser parser = new HtmlTextParser (output);
                        page.Form.RenderControl (parser);
 
-                       WriteCallbackOutput (output, asyncPostBackControlIDs, null, FormatListIDs (_asyncPostBackControls, false));
-                       WriteCallbackOutput (output, postBackControlIDs, null, FormatListIDs (_postBackControls, false));
+                       Dictionary <string, string> pageHiddenFields = parser.HiddenFields;
+                       if (pageHiddenFields != null)
+                               foreach (KeyValuePair <string, string> kvp in pageHiddenFields)
+                                       WriteCallbackOutput (output, hiddenField, kvp.Key, kvp.Value);
+                       
+                       WriteCallbackOutput (output, asyncPostBackControlIDs, null, FormatListIDs (_asyncPostBackControls, false, false));
+                       WriteCallbackOutput (output, postBackControlIDs, null, FormatListIDs (_postBackControls, false, false));
                        WriteCallbackOutput (output, updatePanelIDs, null, FormatUpdatePanelIDs (_updatePanels, false));
-                       WriteCallbackOutput (output, childUpdatePanelIDs, null, FormatListIDs (_childUpdatePanels, false));
-                       WriteCallbackOutput (output, panelsToRefreshIDs, null, FormatListIDs (_panelsToRefresh, false));
+                       WriteCallbackOutput (output, childUpdatePanelIDs, null, FormatListIDs (_childUpdatePanels, false, true));
+                       WriteCallbackOutput (output, panelsToRefreshIDs, null, FormatListIDs (_panelsToRefresh, false, true));
                        WriteCallbackOutput (output, asyncPostBackTimeout, null, AsyncPostBackTimeout.ToString ());
                        if (!IsMultiForm)
                                WriteCallbackOutput (output, pageTitle, null, Page.Title);
@@ -1130,8 +1350,8 @@ namespace System.Web.UI
                                }
 
                        WriteArrayDeclarations (output);
+                       WriteExpandoAttributes (output);
                        WriteScriptBlocks (output, _clientScriptBlocks);
-                       WriteScriptBlocks (output, _scriptIncludes);
                        WriteScriptBlocks (output, _startupScriptBlocks);
                        WriteScriptBlocks (output, _onSubmitStatements);
                        WriteHiddenFields (output);
@@ -1141,54 +1361,98 @@ namespace System.Web.UI
 
                        if (_disposeScripts != null)
                                for (int i = 0; i < _disposeScripts.Count; i++) {
-                                       DisposeScriptEntry entry = _disposeScripts [i];
+                                       RegisteredDisposeScript entry = _disposeScripts [i];
                                        if ((_panelsToRefresh != null && _panelsToRefresh.IndexOf (entry.UpdatePanel) >= 0) || (_childUpdatePanels != null && _childUpdatePanels.IndexOf (entry.UpdatePanel) >= 0))
                                                WriteCallbackOutput (output, scriptDispose, entry.UpdatePanel.ClientID, entry.Script);
                                }
                }
 
+               private void WriteExpandoAttributes (HtmlTextWriter writer) {
+                       if (_expandoAttributes != null) {
+                               for (int i = 0; i < _expandoAttributes.Count; i++) {
+                                       RegisteredExpandoAttribute attr = _expandoAttributes [i];
+                                       if (HasBeenRendered (attr.Control)) {
+                                               string value;
+                                               if (attr.Encode) {
+                                                       StringWriter sw = new StringWriter ();
+                                                       Newtonsoft.Json.JavaScriptUtils.WriteEscapedJavaScriptString (attr.Value, sw);
+                                                       value = sw.ToString ();
+                                               }
+                                               else
+                                                       value = "\"" + attr.Value + "\"";
+                                               WriteCallbackOutput (writer, expando, "document.getElementById('" + attr.ControlId + "')['" + attr.Name + "']", value);
+                                       }
+                               }
+                       }
+               }
+
                void WriteArrayDeclarations (HtmlTextWriter writer) {
                        if (_arrayDeclarations != null) {
                                for (int i = 0; i < _arrayDeclarations.Count; i++) {
-                                       ArrayDeclaration array = _arrayDeclarations [i];
-                                       WriteCallbackOutput (writer, arrayDeclaration, array.ArrayName, array.ArrayValue);
+                                       RegisteredArrayDeclaration array = _arrayDeclarations [i];
+                                       if (Page == array.Control || HasBeenRendered (array.Control))
+                                               WriteCallbackOutput (writer, arrayDeclaration, array.Name, array.Value);
                                }
                        }
                }
 
-               void WriteScriptBlocks (HtmlTextWriter output, ScriptEntry scriptList) {
-                       while (scriptList != null) {
-                               switch (scriptList.ScriptEntryType) {
-                               case ScriptEntryType.ScriptContentNoTags:
-                                       WriteCallbackOutput (output, scriptBlock, scriptContentNoTags, scriptList.Script);
-                                       break;
-                               case ScriptEntryType.ScriptContentWithTags:
-                                       string script = SerializeScriptBlock (scriptList);
-                                       WriteCallbackOutput (output, scriptBlock, scriptContentWithTags, script);
-                                       break;
-                               case ScriptEntryType.ScriptPath:
-                                       WriteCallbackOutput (output, scriptBlock, scriptPath, scriptList.Script);
-                                       break;
-                               case ScriptEntryType.OnSubmit:
-                                       WriteCallbackOutput (output, onSubmit, null, scriptList.Script);
-                                       break;
+               void WriteScriptBlocks (HtmlTextWriter output, List<RegisteredScript> scriptList) {
+                       if (scriptList == null)
+                               return;
+                       var registeredScripts = new Dictionary <string, RegisteredScript> ();
+                       Control control;
+                       Page page = Page;
+                       
+                       for (int i = 0; i < scriptList.Count; i++) {
+                               RegisteredScript scriptEntry = scriptList [i];
+                               if (registeredScripts.ContainsKey (scriptEntry.Key))
+                                       continue;
+
+                               control = scriptEntry.Control;
+                               if (page == control || HasBeenRendered (control)) {
+                                       registeredScripts.Add (scriptEntry.Key, scriptEntry);
+                                       switch (scriptEntry.ScriptType) {
+                                               case RegisteredScriptType.ClientScriptBlock:
+                                                       if (scriptEntry.AddScriptTags)
+                                                               WriteCallbackOutput (output, scriptBlock, scriptContentNoTags, scriptEntry.Script);
+                                                       else
+                                                               WriteCallbackOutput (output, scriptBlock, scriptContentWithTags, SerializeScriptBlock (scriptEntry));
+                                                       break;
+                                               case RegisteredScriptType.ClientStartupScript:
+                                                       if (scriptEntry.AddScriptTags)
+                                                               WriteCallbackOutput (output, scriptStartupBlock, scriptContentNoTags, scriptEntry.Script);
+                                                       else
+                                                               WriteCallbackOutput (output, scriptStartupBlock, scriptContentWithTags, SerializeScriptBlock (scriptEntry));
+                                                       break;
+                                               case RegisteredScriptType.ClientScriptInclude:
+                                                       WriteCallbackOutput (output, scriptBlock, scriptPath, scriptEntry.Url);
+                                                       break;
+                                               case RegisteredScriptType.OnSubmitStatement:
+                                                       WriteCallbackOutput (output, onSubmit, null, scriptEntry.Script);
+                                                       break;
+                                       }
                                }
-                               scriptList = scriptList.Next;
                        }
                }
 
                void WriteHiddenFields (HtmlTextWriter output) {
                        if (_hiddenFields == null)
                                return;
-                       foreach (string key in _hiddenFields.Keys) {
-                               string value = _hiddenFields [key] as string;
-                               WriteCallbackOutput (output, hiddenField, key, value);
+                       Hashtable registeredFields = new Hashtable ();
+                       for (int i = 0; i < _hiddenFields.Count; i++) {
+                               RegisteredHiddenField field = _hiddenFields [i];
+                               if (registeredFields.ContainsKey (field.Name))
+                                       continue;
+                               if (Page == field.Control || HasBeenRendered (field.Control)) {
+                                       registeredFields.Add (field.Name, field);
+                                       WriteCallbackOutput (output, hiddenField, field.Name, field.InitialValue);
+                               }
                        }
                }
 
-               static string SerializeScriptBlock (ScriptEntry scriptList) {
+               static string SerializeScriptBlock (RegisteredScript scriptEntry) {
                        try {
-                               XmlTextReader reader = new XmlTextReader (new StringReader (scriptList.Script));
+                               XmlTextReader reader = new XmlTextReader (new StringReader (scriptEntry.Script));
                                while (reader.Read ()) {
                                        switch (reader.NodeType) {
                                        case XmlNodeType.Element:
@@ -1209,17 +1473,18 @@ namespace System.Web.UI
                        }
                        catch {
                        }
-                       throw new InvalidOperationException (String.Format ("The script tag registered for type '{0}' and key '{1}' has invalid characters outside of the script tags: {2}. Only properly formatted script tags can be registered.", scriptList.Type, scriptList.Key, scriptList.Script));
+                       throw new InvalidOperationException (String.Format ("The script tag registered for type '{0}' and key '{1}' has invalid characters outside of the script tags: {2}. Only properly formatted script tags can be registered.", scriptEntry.Type, scriptEntry.Key, scriptEntry.Script));
                }
 
-               void RenderFormCallback (HtmlTextWriter output, Control container) {
+               void RenderFormCallback (HtmlTextWriter output, Control container)
+               {
                        output = ((HtmlTextParser) output).ResponseOutput;
                        HtmlForm form = (HtmlForm) container;
                        HtmlTextWriter writer = new HtmlDropWriter (output);
+                       
                        if (form.HasControls ()) {
-                               for (int i = 0; i < form.Controls.Count; i++) {
-                                       form.Controls [i].RenderControl (writer);
-                               }
+                               foreach (Control control in form.Controls)
+                                       control.RenderControl (writer);
                        }
                }
 
@@ -1241,10 +1506,29 @@ namespace System.Web.UI
                {
                        bool _done;
 
+                       public Dictionary <string, string> _hiddenFields;
+
+                       public Dictionary <string, string> HiddenFields {
+                               get { return _hiddenFields; }
+                       }
+                       
                        public HtmlTextParser (HtmlTextWriter responseOutput)
-                               : base (new TextParser (responseOutput), responseOutput) {
+                               : this (new TextParser (responseOutput), responseOutput) {
                        }
 
+                       HtmlTextParser (TextParser parser, HtmlTextWriter responseOutput)
+                               : base (parser, responseOutput)
+                       {
+                               parser.HiddenFieldParsed += new TextParser.TextParserHiddenFieldParsedEventHandler (OnHiddenFieldParsed);
+                       }
+                       
+                       void OnHiddenFieldParsed (TextParser sender, TextParserHiddenFieldParsedEventArgs args)
+                       {
+                               if (_hiddenFields == null)
+                                       _hiddenFields = new Dictionary <string, string> ();
+                               _hiddenFields [args.Name] = args.Value;
+                       }
+                       
                        public override void WriteAttribute (string name, string value) {
                                if (!_done && String.Compare ("action", name, StringComparison.OrdinalIgnoreCase) == 0) {
                                        _done = true;
@@ -1255,8 +1539,31 @@ namespace System.Web.UI
                        }
                }
 
+               sealed class TextParserHiddenFieldParsedEventArgs : EventArgs
+               {
+                       public string Name {
+                               get;
+                               private set;
+                       }
+
+                       public string Value {
+                               get;
+                               private set;
+                       }
+                       
+                       public TextParserHiddenFieldParsedEventArgs (string name, string value)
+                       {
+                               this.Name = name;
+                               this.Value = value;
+                       }
+               }
+               
                sealed class TextParser : TextWriter
                {
+                       public delegate void TextParserHiddenFieldParsedEventHandler (TextParser sender, TextParserHiddenFieldParsedEventArgs args);
+
+                       static object textParserHiddenFieldParsedEvent = new object ();
+                       
                        int _state;
                        char _charState = (char) 255;
                        const char nullCharState = (char) 255;
@@ -1264,7 +1571,13 @@ namespace System.Web.UI
                        Dictionary<string, string> _currentField;
                        string _currentAttribute;
                        readonly HtmlTextWriter _responseOutput;
-
+                       TextParserHiddenFieldParsedEventHandler _hiddenFieldParsedHandler;
+                       
+                       public event TextParserHiddenFieldParsedEventHandler HiddenFieldParsed {
+                               add { _hiddenFieldParsedHandler = value; }
+                               remove { _hiddenFieldParsedHandler = null; }
+                       }
+                       
                        public override Encoding Encoding {
                                get { return Encoding.UTF8; }
                        }
@@ -1383,10 +1696,13 @@ namespace System.Web.UI
                                        return;
 
                                string value = _currentField ["value"];
-                               if (String.IsNullOrEmpty (value))
+                               if (value == null)
                                        return;
 
-                               ScriptManager.WriteCallbackOutput (_responseOutput, hiddenField, _currentField ["name"], HttpUtility.HtmlDecode (value));
+                               if (_hiddenFieldParsedHandler != null)
+                                       _hiddenFieldParsedHandler (this, new TextParserHiddenFieldParsedEventArgs (_currentField ["name"], HttpUtility.HtmlDecode (value)));
+                               else
+                                       ScriptManager.WriteCallbackOutput (_responseOutput, hiddenField, _currentField ["name"], HttpUtility.HtmlDecode (value));
                        }
                }
 
@@ -1404,42 +1720,7 @@ namespace System.Web.UI
                        }
                }
 
-               sealed class ScriptEntry
-               {
-                       readonly public Type Type;
-                       readonly public string Key;
-                       readonly public string Script;
-                       readonly public ScriptEntryType ScriptEntryType;
-                       public ScriptEntry Next;
-
-                       public ScriptEntry (Type type, string key, string script, ScriptEntryType scriptEntryType) {
-                               Key = key;
-                               Type = type;
-                               Script = script;
-                               ScriptEntryType = scriptEntryType;
-                       }
-               }
-
-               enum ScriptEntryType
-               {
-                       ScriptContentNoTags,
-                       ScriptContentWithTags,
-                       ScriptPath,
-                       OnSubmit
-               }
-
-               sealed class ArrayDeclaration
-               {
-                       readonly public string ArrayName;
-                       readonly public string ArrayValue;
-
-                       public ArrayDeclaration (string arrayName, string arrayValue) {
-                               ArrayName = arrayName;
-                               ArrayValue = arrayValue;
-                       }
-               }
-
-               sealed class CultureInfoSerializer : JavaScriptSerializer.LazyDictionary
+               sealed class CultureInfoSerializer
                {
                        readonly CultureInfo _ci;
                        public CultureInfoSerializer (CultureInfo ci) {
@@ -1447,11 +1728,18 @@ namespace System.Web.UI
                                        throw new ArgumentNullException ("ci");
                                _ci = ci;
                        }
-                       protected override IEnumerator<KeyValuePair<string, object>> GetEnumerator () {
-                               yield return new KeyValuePair<string, object> ("name", _ci.Name);
-                               yield return new KeyValuePair<string, object> ("numberFormat", _ci.NumberFormat);
-                               yield return new KeyValuePair<string, object> ("dateTimeFormat", _ci.DateTimeFormat);
+
+                       public string name {
+                               get { return _ci.Name; }
                        }
+
+                       public NumberFormatInfo numberFormat {
+                               get { return _ci.NumberFormat; }
+                       }
+
+                       public DateTimeFormatInfo dateTimeFormat {
+                               get { return _ci.DateTimeFormat; }
+                       }                       
                }
 
                sealed class ScriptReferenceEntry
@@ -1485,18 +1773,47 @@ namespace System.Web.UI
                        }
                }
 
-               sealed class DisposeScriptEntry
-               {
-                       readonly UpdatePanel _updatePanel;
-                       readonly string _script;
+               internal void RegisterProxy (ScriptManagerProxy scriptManagerProxy) {
+                       if (_proxies == null)
+                               _proxies = new List<ScriptManagerProxy> ();
 
-                       public UpdatePanel UpdatePanel { get { return _updatePanel; } }
-                       public string Script { get { return _script; } }
+                       _proxies.Add (scriptManagerProxy);
+               }
 
-                       public DisposeScriptEntry (UpdatePanel updatePanel, string script) {
-                               _updatePanel = updatePanel;
-                               _script = script;
-                       }
+               #region IScriptManager Members
+
+               void IScriptManager.RegisterOnSubmitStatementExternal (Control control, Type type, string key, string script) {
+                       RegisterOnSubmitStatement (control, type, key, script);
+               }
+
+               void IScriptManager.RegisterExpandoAttributeExternal (Control control, string controlId, string attributeName, string attributeValue, bool encode) {
+                       RegisterExpandoAttribute (control, controlId, attributeName, attributeValue, encode);
+               }
+
+               void IScriptManager.RegisterHiddenFieldExternal (Control control, string hiddenFieldName, string hiddenFieldInitialValue) {
+                       RegisterHiddenField (control, hiddenFieldName, hiddenFieldInitialValue);
+               }
+
+               void IScriptManager.RegisterStartupScriptExternal (Control control, Type type, string key, string script, bool addScriptTags) {
+                       RegisterStartupScript (control, type, key, script, addScriptTags);
+               }
+
+               void IScriptManager.RegisterArrayDeclarationExternal (Control control, string arrayName, string arrayValue) {
+                       RegisterArrayDeclaration (control, arrayName, arrayValue);
                }
+
+               void IScriptManager.RegisterClientScriptBlockExternal (Control control, Type type, string key, string script, bool addScriptTags) {
+                       RegisterClientScriptBlock (control, type, key, script, addScriptTags);
+               }
+
+               void IScriptManager.RegisterClientScriptIncludeExternal (Control control, Type type, string key, string url) {
+                       RegisterClientScriptInclude (control, type, key, url);
+               }
+
+               void IScriptManager.RegisterClientScriptResourceExternal (Control control, Type type, string resourceName) {
+                       RegisterClientScriptResource (control, type, resourceName);
+               }
+
+               #endregion
        }
 }