Hi, I''ve never posted here before so please forgive me if I''m not observing proper decorum, yadda yadda yadda :-) I''ve ran into a very, very strange bug with Prototype I wanted to share and see if anyone else has seen this. In a few of my projects involving Ext JS, I''m using the TreePanel control, which uses AJAX to load child nodes asynchronously. Because I bundle in the prototype library with my Ext, these AJAX calls are being processed by Prototype (v 1.6.0.2). In every instance where I use one of these tree panels, I''ve noticed the weirdest problem where every so often, totally at random, even though the child nodes are sent back correctly by the server, the tree panel logs an error and the children fail to load. I''ve been tracking this for weeks now and finally stumbled upon the root cause of the problem, and it turns out to be an apparent bug in Prototype, not in Ext: In the Ajax.Request class, the respondToReadyState method, you have: respondToReadyState: function(readyState) { var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this); etc etc etc... Maybe 90% of the time, readyState here and transport.readyState are the same (as they always should be?). However, it turns out, maybe 10% of the time the readyState passed into the event handler is completely different from the ready state in the XHR object (transport.readyState). I set up a piece of code to log this in Firebug (but this happens in every browser, mind you): respondToReadyState: function(readyState) { if (readyState != this.transport.readyState) console.log("readyState is " + readyState + " but transport says " + this.transport.readyState + "!!!!!"); And, in the course of perhaps 15 minutes of various ajax requests (not just in my tree panel, but anywhere), I see this in my console: readyState is 170 but transport says 1!!!!! readyState is 7 but transport says 1!!!!! readyState is 7 but transport says 1!!!!! readyState is 3 but transport says 1!!!!! readyState is 4 but transport says 1!!!!! That last one is the real problem - because readyState is 4 but the real readyState in the XHR object is still actually 1, the success callback is triggered (because Ajax.Response checks transport.readyState, not the readyState passed to respondToReadyState), but there is no responseText (yet), so the whole call fails. Extremely frustrating bug to tease out, let me tell you, because Firebug *always* seems to get the right responseText, even though Prototype doesn''t. It was easy enough now to fix my problem, all I did was this: respondToReadyState: function(readyState) { readyState = this.transport.readyState; [ continue on as normal ] And now I have *no* problems. But I really don''t like the idea of modifying my prototype :-(. So what gives? Can I really be the only person this is happening to? And what the heck would a readyState of 170 mean anyway? It''s super-duper-done? Thanks for listening, and despite this little glitch, thanks so much for Prototype! I just can''t live without my Enumerables! --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Sorry, got a bit turned around in the middle there, I meant: That last one is the real problem - because readyState is 4 but the real readyState in the XHR object is still actually 1, the success callback is triggered ( because state is Complete), but there is no responseText (because Ajax.Response checks transport.readyState, not the readyState passed to respondToReadyState, and Ajax.Response is responsible for setting Ajax.Response.responseText), so the whole call fails. On Jun 26, 5:54 pm, jove4015 <smwe...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Hi, > > I''ve never posted here before so please forgive me if I''m not > observing proper decorum, yadda yadda yadda :-) > > I''ve ran into a very, very strange bug with Prototype I wanted to > share and see if anyone else has seen this. In a few of my projects > involving Ext JS, I''m using the TreePanel control, which uses AJAX to > load child nodes asynchronously. Because I bundle in the prototype > library with my Ext, these AJAX calls are being processed by Prototype > (v 1.6.0.2). In every instance where I use one of these tree panels, > I''ve noticed the weirdest problem where every so often, totally at > random, even though the child nodes are sent back correctly by the > server, the tree panel logs an error and the children fail to load. > > I''ve been tracking this for weeks now and finally stumbled upon the > root cause of the problem, and it turns out to be an apparent bug in > Prototype, not in Ext: > > In the Ajax.Request class, the respondToReadyState method, you have: > > respondToReadyState: function(readyState) { > var state = Ajax.Request.Events[readyState], response = new > Ajax.Response(this); > etc etc etc... > > Maybe 90% of the time, readyState here and transport.readyState are > the same (as they always should be?). However, it turns out, maybe > 10% of the time the readyState passed into the event handler is > completely different from the ready state in the XHR object > (transport.readyState). I set up a piece of code to log this in > Firebug (but this happens in every browser, mind you): > > respondToReadyState: function(readyState) { > if (readyState != this.transport.readyState) > console.log("readyState is " + readyState + " but transport says " > + this.transport.readyState + "!!!!!"); > > And, in the course of perhaps 15 minutes of various ajax requests (not > just in my tree panel, but anywhere), I see this in my console: > > readyState is 170 but transport says 1!!!!! > readyState is 7 but transport says 1!!!!! > readyState is 7 but transport says 1!!!!! > readyState is 3 but transport says 1!!!!! > readyState is 4 but transport says 1!!!!! > > That last one is the real problem - because readyState is 4 but the > real readyState in the XHR object is still actually 1, the success > callback is triggered (because Ajax.Response checks > transport.readyState, not the readyState passed to > respondToReadyState), but there is no responseText (yet), so the whole > call fails. > > Extremely frustrating bug to tease out, let me tell you, because > Firebug *always* seems to get the right responseText, even though > Prototype doesn''t. It was easy enough now to fix my problem, all I > did was this: > > respondToReadyState: function(readyState) { > readyState = this.transport.readyState; > [ continue on as normal ] > > And now I have *no* problems. But I really don''t like the idea of > modifying my prototype :-(. So what gives? Can I really be the only > person this is happening to? And what the heck would a readyState of > 170 mean anyway? It''s super-duper-done? > > Thanks for listening, and despite this little glitch, thanks so much > for Prototype! I just can''t live without my Enumerables!--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
There are two places in the Prototype request lifecycle that respondToReadyState is called. The obvious place is when an actual state change is triggered: (inside Ajax.Request.Prototype) onStateChange: function() { var readyState = this.transport.readyState; if (readyState != 1) this.respondToReadyState(this.transport.readyState); } This method is set to the value of request.transport.onreadystatechange when the Ajax.Request is created. However, if the response is asynchronous (nobody is writing synchronous Ajax, are they?!), the Ajax.Request#request() method also fires off a state change of 1 immediately (10ms) after it is created: if (this.options.asynchronous) { this.transport.onreadystatechange = this.onStateChange.bind(this); setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10); } Not sure how you''re seeing a value of 170 in there. Hmm. -Fred On Thu, Jun 26, 2008 at 4:56 PM, jove4015 <smweiss-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > Sorry, got a bit turned around in the middle there, I meant: > > That last one is the real problem - because readyState is 4 but the > real readyState in the XHR object is still actually 1, the success > callback is triggered ( because state is Complete), but there is no > responseText (because Ajax.Response checks > transport.readyState, not the readyState passed to > respondToReadyState, and Ajax.Response is responsible for setting > Ajax.Response.responseText), so the whole > call fails. > > On Jun 26, 5:54 pm, jove4015 <smwe...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > Hi, > > > > I''ve never posted here before so please forgive me if I''m not > > observing proper decorum, yadda yadda yadda :-) > > > > I''ve ran into a very, very strange bug with Prototype I wanted to > > share and see if anyone else has seen this. In a few of my projects > > involving Ext JS, I''m using the TreePanel control, which uses AJAX to > > load child nodes asynchronously. Because I bundle in the prototype > > library with my Ext, these AJAX calls are being processed by Prototype > > (v 1.6.0.2). In every instance where I use one of these tree panels, > > I''ve noticed the weirdest problem where every so often, totally at > > random, even though the child nodes are sent back correctly by the > > server, the tree panel logs an error and the children fail to load. > > > > I''ve been tracking this for weeks now and finally stumbled upon the > > root cause of the problem, and it turns out to be an apparent bug in > > Prototype, not in Ext: > > > > In the Ajax.Request class, the respondToReadyState method, you have: > > > > respondToReadyState: function(readyState) { > > var state = Ajax.Request.Events[readyState], response = new > > Ajax.Response(this); > > etc etc etc... > > > > Maybe 90% of the time, readyState here and transport.readyState are > > the same (as they always should be?). However, it turns out, maybe > > 10% of the time the readyState passed into the event handler is > > completely different from the ready state in the XHR object > > (transport.readyState). I set up a piece of code to log this in > > Firebug (but this happens in every browser, mind you): > > > > respondToReadyState: function(readyState) { > > if (readyState != this.transport.readyState) > > console.log("readyState is " + readyState + " but > transport says " > > + this.transport.readyState + "!!!!!"); > > > > And, in the course of perhaps 15 minutes of various ajax requests (not > > just in my tree panel, but anywhere), I see this in my console: > > > > readyState is 170 but transport says 1!!!!! > > readyState is 7 but transport says 1!!!!! > > readyState is 7 but transport says 1!!!!! > > readyState is 3 but transport says 1!!!!! > > readyState is 4 but transport says 1!!!!! > > > > That last one is the real problem - because readyState is 4 but the > > real readyState in the XHR object is still actually 1, the success > > callback is triggered (because Ajax.Response checks > > transport.readyState, not the readyState passed to > > respondToReadyState), but there is no responseText (yet), so the whole > > call fails. > > > > Extremely frustrating bug to tease out, let me tell you, because > > Firebug *always* seems to get the right responseText, even though > > Prototype doesn''t. It was easy enough now to fix my problem, all I > > did was this: > > > > respondToReadyState: function(readyState) { > > readyState = this.transport.readyState; > > [ continue on as normal ] > > > > And now I have *no* problems. But I really don''t like the idea of > > modifying my prototype :-(. So what gives? Can I really be the only > > person this is happening to? And what the heck would a readyState of > > 170 mean anyway? It''s super-duper-done? > > > > Thanks for listening, and despite this little glitch, thanks so much > > for Prototype! I just can''t live without my Enumerables! > > >-- Science answers questions; philosophy questions answers. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Yeah, these calls are definitely asynchronous... So *both* types are happening here. And yeah, I really don''t get it either. I''ve been using Prototype for years and I just feel like I would have seen the ramifications of this before. It really boggles my mind... I mean, I''ve found my AJAX calls to be very reliable up until I started using these TreePanels! I''m starting to wonder now if there''s some way in which readyState is conflicting with some global variable set by Ext. I definitely don''t use that variable in my own code (I do everything in namespaces now anyway). Also I''ve looked at where that readyState is being passed from and it''s coming originally from transport.readyState in the first place, so one really *really* has to wonder how the two values manage to become different. But, then I wonder even more, why bother passing the readyState when it''s right there in the object itself anyway? Seems like extra fuss for no benefit to me. On Jun 26, 6:05 pm, "Frederick Polgardy" <f...-SMQUYeM9IBBWk0Htik3J/w@public.gmane.org> wrote:> There are two places in the Prototype request lifecycle that > respondToReadyState is called. The obvious place is when an actual state > change is triggered: > > (inside Ajax.Request.Prototype) > > onStateChange: function() { > var readyState = this.transport.readyState; > if (readyState != 1) > this.respondToReadyState(this.transport.readyState); > } > > This method is set to the value of request.transport.onreadystatechange when > the Ajax.Request is created. > > However, if the response is asynchronous (nobody is writing synchronous > Ajax, are they?!), the Ajax.Request#request() method also fires off a state > change of 1 immediately (10ms) after it is created: > > if (this.options.asynchronous) { > this.transport.onreadystatechange = this.onStateChange.bind(this); > setTimeout((function() {this.respondToReadyState(1)}).bind(this), > 10); > } > > Not sure how you''re seeing a value of 170 in there. Hmm. > > -Fred > > > > On Thu, Jun 26, 2008 at 4:56 PM, jove4015 <smwe...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > Sorry, got a bit turned around in the middle there, I meant: > > > That last one is the real problem - because readyState is 4 but the > > real readyState in the XHR object is still actually 1, the success > > callback is triggered ( because state is Complete), but there is no > > responseText (because Ajax.Response checks > > transport.readyState, not the readyState passed to > > respondToReadyState, and Ajax.Response is responsible for setting > > Ajax.Response.responseText), so the whole > > call fails. > > > On Jun 26, 5:54 pm, jove4015 <smwe...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > Hi, > > > > I''ve never posted here before so please forgive me if I''m not > > > observing proper decorum, yadda yadda yadda :-) > > > > I''ve ran into a very, very strange bug with Prototype I wanted to > > > share and see if anyone else has seen this. In a few of my projects > > > involving Ext JS, I''m using the TreePanel control, which uses AJAX to > > > load child nodes asynchronously. Because I bundle in the prototype > > > library with my Ext, these AJAX calls are being processed by Prototype > > > (v 1.6.0.2). In every instance where I use one of these tree panels, > > > I''ve noticed the weirdest problem where every so often, totally at > > > random, even though the child nodes are sent back correctly by the > > > server, the tree panel logs an error and the children fail to load. > > > > I''ve been tracking this for weeks now and finally stumbled upon the > > > root cause of the problem, and it turns out to be an apparent bug in > > > Prototype, not in Ext: > > > > In the Ajax.Request class, the respondToReadyState method, you have: > > > > respondToReadyState: function(readyState) { > > > var state = Ajax.Request.Events[readyState], response = new > > > Ajax.Response(this); > > > etc etc etc... > > > > Maybe 90% of the time, readyState here and transport.readyState are > > > the same (as they always should be?). However, it turns out, maybe > > > 10% of the time the readyState passed into the event handler is > > > completely different from the ready state in the XHR object > > > (transport.readyState). I set up a piece of code to log this in > > > Firebug (but this happens in every browser, mind you): > > > > respondToReadyState: function(readyState) { > > > if (readyState != this.transport.readyState) > > > console.log("readyState is " + readyState + " but > > transport says " > > > + this.transport.readyState + "!!!!!"); > > > > And, in the course of perhaps 15 minutes of various ajax requests (not > > > just in my tree panel, but anywhere), I see this in my console: > > > > readyState is 170 but transport says 1!!!!! > > > readyState is 7 but transport says 1!!!!! > > > readyState is 7 but transport says 1!!!!! > > > readyState is 3 but transport says 1!!!!! > > > readyState is 4 but transport says 1!!!!! > > > > That last one is the real problem - because readyState is 4 but the > > > real readyState in the XHR object is still actually 1, the success > > > callback is triggered (because Ajax.Response checks > > > transport.readyState, not the readyState passed to > > > respondToReadyState), but there is no responseText (yet), so the whole > > > call fails. > > > > Extremely frustrating bug to tease out, let me tell you, because > > > Firebug *always* seems to get the right responseText, even though > > > Prototype doesn''t. It was easy enough now to fix my problem, all I > > > did was this: > > > > respondToReadyState: function(readyState) { > > > readyState = this.transport.readyState; > > > [ continue on as normal ] > > > > And now I have *no* problems. But I really don''t like the idea of > > > modifying my prototype :-(. So what gives? Can I really be the only > > > person this is happening to? And what the heck would a readyState of > > > 170 mean anyway? It''s super-duper-done? > > > > Thanks for listening, and despite this little glitch, thanks so much > > > for Prototype! I just can''t live without my Enumerables! > > -- > Science answers questions; philosophy questions answers.--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Maybe ExtJS mucks with the XHR prototype in some way? On Thu, Jun 26, 2008 at 5:38 PM, jove4015 <smweiss-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > Yeah, these calls are definitely asynchronous... So *both* types are > happening here.-- Science answers questions; philosophy questions answers. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
I wish it were that simple... I just did a quick grep through all of the Ext JS code I include and there''s no reference to XMLHttpRequest outside of comments (and certainly no reference to XMLHttpRequest.prototype)... when I check the contents of XMLHttpRequest.prototype in Firebug they match what I see on a page that does not include Ext. I''d say maybe it''s Firebug but the bug that caused me to find this in the first place happens in IE 6/7 and Safari 2/3 as well... really it might even happen in Opera, I just haven''t looked. On Jun 26, 6:46 pm, "Frederick Polgardy" <f...-SMQUYeM9IBBWk0Htik3J/w@public.gmane.org> wrote:> Maybe ExtJS mucks with the XHR prototype in some way? > > On Thu, Jun 26, 2008 at 5:38 PM, jove4015 <smwe...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > Yeah, these calls are definitely asynchronous... So *both* types are > > happening here. > > -- > Science answers questions; philosophy questions answers.--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
aha - found someone else who seems to have found out why: http://prototype.lighthouseapp.com/projects/8886-prototype/tickets/189-respondtoreadystate-is-called-with-a-random-readystate On Jun 26, 6:55 pm, jove4015 <smwe...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> I wish it were that simple... I just did a quick grep through all of > the Ext JS code I include and there''s no reference to XMLHttpRequest > outside of comments (and certainly no reference to > XMLHttpRequest.prototype)... when I check the contents of > XMLHttpRequest.prototype in Firebug they match what I see on a page > that does not include Ext. > > I''d say maybe it''s Firebug but the bug that caused me to find this in > the first place happens in IE 6/7 and Safari 2/3 as well... really it > might even happen in Opera, I just haven''t looked. > > On Jun 26, 6:46 pm, "Frederick Polgardy" <f...-SMQUYeM9IBBWk0Htik3J/w@public.gmane.org> wrote: > > > Maybe ExtJS mucks with the XHR prototype in some way? > > > On Thu, Jun 26, 2008 at 5:38 PM, jove4015 <smwe...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > Yeah, these calls are definitely asynchronous... So *both* types are > > > happening here. > > > -- > > Science answers questions; philosophy questions answers.--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
henry.christopher-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
2008-Jun-27 14:04 UTC
Re: Strange readyStates in prototype Ajax
Jove, I have seen very familiar behavior in an application I''m building with Ext. I poll the server for a JSON response, and every once in a while I notice that the transport.responseText is empty, and my function would throw an error. More details in this ticket: http://prototype.lighthouseapp.com/projects/8886/tickets/128-string-evaljson-throwing-a-typeerror I''ve since refactored to use transport.responseJSON, and the problem with that part of the application seems to have abated. However, the entire application is Ajax, and every so often I will have a response come up empty. Do the Ajax internals work the same way for transport.responseText as for transport.responseJSON? Also, if you have a patch, I''d love to see it! Best, Chris On Jun 26, 7:01 pm, jove4015 <smwe...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> aha - found someone else who seems to have found out why: > > http://prototype.lighthouseapp.com/projects/8886-prototype/tickets/18... > > On Jun 26, 6:55 pm, jove4015 <smwe...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > I wish it were that simple... I just did a quick grep through all of > > the Ext JS code I include and there''s no reference to XMLHttpRequest > > outside of comments (and certainly no reference to > > XMLHttpRequest.prototype)... when I check the contents of > > XMLHttpRequest.prototype in Firebug they match what I see on a page > > that does not include Ext. > > > I''d say maybe it''s Firebug but the bug that caused me to find this in > > the first place happens in IE 6/7 and Safari 2/3 as well... really it > > might even happen in Opera, I just haven''t looked. > > > On Jun 26, 6:46 pm, "Frederick Polgardy" <f...-SMQUYeM9IBBWk0Htik3J/w@public.gmane.org> wrote: > > > > Maybe ExtJS mucks with the XHR prototype in some way? > > > > On Thu, Jun 26, 2008 at 5:38 PM, jove4015 <smwe...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > > > > Yeah, these calls are definitely asynchronous... So *both* types are > > > > happening here. > > > > -- > > > Science answers questions; philosophy questions answers.--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---