Safari scope problem with dynodes

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • dd

    Safari scope problem with dynodes

    Hi,

    I've discovered a scenario where Safari 1.3 (I need to make my stuff
    compliant with 1.3+) gets confused about the scope of local variables
    WITHIN functions that were created in dynamic script blocks. I've made
    this example where function def has a local i variable in a loop, and
    it calls function abc which also has a local i variable in a loop. What
    happens is that Safari is not respecting the scope and is allowing the
    called function to corrupt a local variable in the parent function

    Here's the whole test page including html tags. If you try it you'll
    see that IE and Gecko both produce the output "in abc" twice, because
    the def function correctly gets to call abc twice. On Safari, i gets
    corrupted, and abc only gets called once... Any ideas what I can do to
    prevent this?

    <html><body>
    <script language="javas cript">
    function abc() {
    for(var i=0; i<1; i++)
    document.getEle mentById("dd"). innerHTML+="in abc<br>";
    }
    var funcs=("\n" + abc.toString()) ;

    function def() {
    for(var i=0; i<2; i++)
    abc();
    }
    funcs += ("\n" + def.toString()) ;
    //I now have the funcs abc and def in string form that I'll put into my
    dynamic script element

    var s=document.crea teElement('SCRI PT');
    if(navigator.us erAgent.toLower Case().indexOf( "safari")!=-1)
    s.innerHTML=fun cs; //safari needs this way
    else
    s.text=funcs; //normal browsers need this

    var b=document.getE lementsByTagNam e('body')[0];
    if(b)b.appendCh ild(s); //create those two funcs now

    setTimeout(def, 1000);
    </script>

    <div id='dd'></div>
    </body></html>

  • dd

    #2
    Re: Safari scope problem with dynodes

    In addition to the local variable scope problem when deploying
    functions like this, I also had problems with regexp replaces. Safari
    doesn't like it and I'm not sure why:

    var ss=s.replace(/ /g,"_"); //there's a space between the / /

    To keep Safari happy I had to do this:

    var ss=s;
    while(ss.indexO f(" ")!=-1)ss=ss.replace (" ","_");

    It might work in a regular inline function (I never bothered trying)
    but if the code is deployed via a dynamic script block it's not happy.

    I also have problems with nested ternary statements on Safari. This
    example works on all browsers except Safari:

    eval("foo"+a+"( a"+(arg>1?",pan ":"")+(arg>2?", klr":"")+(arg>3 ?",iac":"")+(ar g>4?",vwt":"")+ (arg>5?",vau":" ")+(arg>6?",cjs ":"")+")");

    It seems to be too complex for Safari's JS parser to handle.

    I feel sorry for Safari users.

    Comment

    • RobG

      #3
      Re: Safari scope problem with dynodes

      dd wrote:
      Hi,
      >
      I've discovered a scenario where Safari 1.3 (I need to make my stuff
      compliant with 1.3+) gets confused about the scope of local variables
      WITHIN functions that were created in dynamic script blocks.
      You will find that it is extremely difficult to find a general solution
      for dynamically creating script elements:

      <URL:
      http://groups.google.com.au/group/co...ebcff147d2e442
      >
      I also think you are wrong about the apparent error - it does 'work' in
      Safari, but the character string '<br>' is treated differently because
      you add the script content with innerHTML.

      I've made
      this example where function def has a local i variable in a loop, and
      it calls function abc which also has a local i variable in a loop. What
      happens is that Safari is not respecting the scope and is allowing the
      called function to corrupt a local variable in the parent function
      You attempt to create two duplicate functions with the same name in the
      same document, since they have (nearly) identical bodies, you won't
      know which one is called. You also attempt to add an element to the
      document body from within a declared head element - it is almost
      certain that the body doesn't exist, so your extra script element is
      never added. What your script calls is the functions defined in the
      original script element, not the new ones you think you've added.

      If you define your functions using strings and use your script adding
      code onload, it "works" in the above browsers (code below). Of course
      then you have issues with some characters such as "<" being interpreted
      differently by .text and .innerHTML. I've changed the function to use
      a text node and remove browser sniffing, but now it wont work in IE -
      fun, isn't it? :-)


      <script type="text/javascript">

      var funcs =
      'function abc() { '+
      ' for(var i=0; i<1; i++) '+
      ' document.getEle mentById("dd"). innerHTML+="in abc<br>"; '+
      '} ';

      funcs +=
      'function def() { '+
      ' for(var i=0; i<2; i++) '+
      ' abc(); '+
      '} ';

      window.onload = function(){
      var s = document.create Element('SCRIPT ');
      s.appendChild(d ocument.createT extNode(funcs)) ;
      document.body.a ppendChild(s);
      def();
      }

      </script>

      <div id="dd"></div>


      One solution is to use eval:

      window.onload = function(){
      eval(funcs);
      def();
      }

      And be aware of the consequences of using eval in this context - the
      scope in which the functions are created is changed, you need to take
      other measures if you want variables declared inside the eval'd string
      to be available after the onload function runs.


      --
      Rob

      Comment

      • RobG

        #4
        Re: Safari scope problem with dynodes

        dd wrote:
        In addition to the local variable scope problem when deploying
        functions like this, I also had problems with regexp replaces. Safari
        doesn't like it and I'm not sure why:
        >
        var ss=s.replace(/ /g,"_"); //there's a space between the / /
        As normal code, Safari has not issues with that at all. If you are
        referring to code inserted using innerHTML, then it is a manifestation
        of incorrectly quoting characters when using innerHTML to insert the
        script element content.

        Since you are using the same string for both innerHTML[1] and .text,
        the solution is to not do that and use one of the methods indicated in
        my previous reply.


        [...]
        I also have problems with nested ternary statements on Safari. This
        example works on all browsers except Safari:
        >
        eval("foo"+a+"( a"+(arg>1?",pan ":"")+(arg>2?", klr":"")+(arg>3 ?",iac":"")+(ar g>4?",vwt":"")+ (arg>5?",vau":" ")+(arg>6?",cjs ":"")+")");
        Are you again referring to code inserted using innerHTML? If so, see
        previous comments/posts. Otherwise, post a small working example that
        displays the error. I'm not going to guess all the likely values of
        all those variables to test it otherwise.

        It seems to be too complex for Safari's JS parser to handle.
        I don't think it is. However, it does seem far too complex to maintain
        and there is almost certainly a better way to achieve the same result
        in maintainable code and without eval. It seems like you should
        investigate the Function apply method.

        I feel sorry for Safari users.
        A misguided sentiment, I think your problems are of your own making.


        1. innerHTML is a proprietary MS invention that has been widely copied
        in other browsers. It has no public standard and implementations
        differ. It should only be used as a convenience method to insert or
        extract simple, fully-formed HTML elements.


        --
        Rob

        Comment

        • dd

          #5
          Re: Safari scope problem with dynodes

          Thanks for this and the other reply in this thread RobG, they're very
          informative. Some of the things you pointed out are purely based on my
          trying to take my actual problem and bring it down to a simple
          self-contained example. What I do actually have in my "real" page is
          the funcs as a string (and not declared inline) and there's no <br>
          involved either.

          What I have learned from your example though is to give createTextNode
          a try, and also perhaps give eval a try. I use eval in my Win/IE logic
          but had to use dynodes for Gecko and thought I'd need to for Safari
          too. I'll give Safari a shot at using eval too. I'll feed back what the
          results were. Thanks a lot :)

          Comment

          • dd

            #6
            Re: Safari scope problem with dynodes


            RobG wrote:
            dd wrote:
            I feel sorry for Safari users.
            A misguided sentiment, I think your problems are of your own making.
            Rob
            You're right of course, frustration setting in, you know what it's
            like.

            That tip of createTextNode has worked, I just tried it. No doubt all
            those problems (the regexp, the ternary prob and the everything else
            seems to be solved by doing this. I gotta paypal you $50, easily
            deserved :) I'll email you separately.

            btw, I discovered the .apply(this,arg uments) coincidentally a week ago
            and used it elsewhere. I'll be applying it to that "bad" code in my
            previous post when I get to it :)

            Comment

            • Randy Webb

              #7
              Re: Safari scope problem with dynodes

              dd said the following on 1/6/2007 4:51 AM:
              RobG wrote:
              >dd wrote:
              >>I feel sorry for Safari users.
              >A misguided sentiment, I think your problems are of your own making.
              >Rob
              >
              You're right of course, frustration setting in, you know what it's
              like.
              >
              That tip of createTextNode has worked, I just tried it. No doubt all
              those problems (the regexp, the ternary prob and the everything else
              seems to be solved by doing this. I gotta paypal you $50, easily
              deserved :) I'll email you separately.
              I want my half Rob, I will sue you!!!! Wait, would that be in the US
              Courts, Australian Courts, European Courts (ECMA is in Europe) or in the
              court of my imagination?
              <G>

              --
              Randy
              Chance Favors The Prepared Mind
              comp.lang.javas cript FAQ - http://jibbering.com/faq/index.html
              Javascript Best Practices - http://www.JavascriptToolbox.com/bestpractices/

              Comment

              • RobG

                #8
                Re: Safari scope problem with dynodes


                Randy Webb wrote:
                dd said the following on 1/6/2007 4:51 AM:
                That tip of createTextNode has worked, I just tried it. No doubt all
                those problems (the regexp, the ternary prob and the everything else
                seems to be solved by doing this. I gotta paypal you $50, easily
                deserved :) I'll email you separately.
                >
                I want my half Rob, I will sue you!!!! Wait, would that be in the US
                Courts, Australian Courts, European Courts (ECMA is in Europe) or in the
                court of my imagination?
                <G>
                I'll promise you 100% of what I received - and since I didn't take up
                the offer, you can guess the rest... :-)

                --
                Rob

                Comment

                • Randy Webb

                  #9
                  Re: Safari scope problem with dynodes

                  RobG said the following on 1/6/2007 8:03 PM:
                  Randy Webb wrote:
                  >dd said the following on 1/6/2007 4:51 AM:
                  >>That tip of createTextNode has worked, I just tried it. No doubt all
                  >>those problems (the regexp, the ternary prob and the everything else
                  >>seems to be solved by doing this. I gotta paypal you $50, easily
                  >>deserved :) I'll email you separately.
                  >I want my half Rob, I will sue you!!!! Wait, would that be in the US
                  >Courts, Australian Courts, European Courts (ECMA is in Europe) or in the
                  >court of my imagination?
                  ><G>
                  >
                  I'll promise you 100% of what I received - and since I didn't take up
                  the offer, you can guess the rest... :-)
                  >
                  What a nice guy you are :-)

                  --
                  Randy
                  Chance Favors The Prepared Mind
                  comp.lang.javas cript FAQ - http://jibbering.com/faq/index.html
                  Javascript Best Practices - http://www.JavascriptToolbox.com/bestpractices/

                  Comment

                  Working...