Loading ...
Sorry, an error occurred while loading the content.

Javascript mystery

Expand Messages
  • Mark S. Miller
    Let s refer to a Javascript function that mentions this as a Javascript method. When a Javascript method is called as a function, it s this gets bound to
    Message 1 of 13 , Oct 9, 2007
    • 0 Attachment
      Let's refer to a Javascript function that mentions 'this' as a
      Javascript method. When a Javascript method is called as a function,
      it's 'this' gets bound to the global object.

      Because Caja code and Javascript code might call each other, Caja
      needs to rewrite function calls as follows:

      foo(args...)

      translates to

      foo.call(<useless-object>, args....)

      That way, even if Caja code calls a Javascript method as a function,
      it cannot trick that method into making unintended changes to the
      Javascript global object.

      An annoying question is what to use for <useless-object>. Crock
      informed me that neither null nor undefined would work, as Javascript
      systems will helpfully substitute the global object instead.
      Experimenting with this showed that it is indeed fatally dangerous,
      but in a mysterious way:


      function foo() { print(this); print(this === window); }

      foo()
      [object Window]
      true

      foo.call(undefined)
      [object Window]
      false

      foo.call(null)
      [object Window]
      false

      In the last two cases, 'this' did get bound to a Window object, but
      not the global 'window'. What did it get bound to? Does anyone have
      any idea what's going on?

      --
      Cheers,
      --MarkM
    • collin_jackson
      I was not able to reproduce this behavior. I tried this URL: javascript:(function(){alert(window===this);}).call(null); I got an alert of true on Firefox
      Message 2 of 13 , Oct 9, 2007
      • 0 Attachment
        I was not able to reproduce this behavior. I tried this URL:

        javascript:(function(){alert(window===this);}).call(null);

        I got an alert of "true" on Firefox 2.0.0.7, Internet Explorer 6, and
        Opera 9.23.

        What browser are you using?

        --- In caplet@yahoogroups.com, "Mark S. Miller" <erights@...> wrote:
        >
        > Let's refer to a Javascript function that mentions 'this' as a
        > Javascript method. When a Javascript method is called as a function,
        > it's 'this' gets bound to the global object.
        >
        > Because Caja code and Javascript code might call each other, Caja
        > needs to rewrite function calls as follows:
        >
        > foo(args...)
        >
        > translates to
        >
        > foo.call(<useless-object>, args....)
        >
        > That way, even if Caja code calls a Javascript method as a function,
        > it cannot trick that method into making unintended changes to the
        > Javascript global object.
        >
        > An annoying question is what to use for <useless-object>. Crock
        > informed me that neither null nor undefined would work, as Javascript
        > systems will helpfully substitute the global object instead.
        > Experimenting with this showed that it is indeed fatally dangerous,
        > but in a mysterious way:
        >
        >
        > function foo() { print(this); print(this === window); }
        >
        > foo()
        > [object Window]
        > true
        >
        > foo.call(undefined)
        > [object Window]
        > false
        >
        > foo.call(null)
        > [object Window]
        > false
        >
        > In the last two cases, 'this' did get bound to a Window object, but
        > not the global 'window'. What did it get bound to? Does anyone have
        > any idea what's going on?
        >
        > --
        > Cheers,
        > --MarkM
        >
      • Mike Samuel
        It seems that call and apply s behavior, in this regard, is browser dependent. The following var o = { valueOf: function () { return null }, toString: function
        Message 3 of 13 , Oct 9, 2007
        • 0 Attachment
          It seems that call and apply's behavior, in this regard, is browser dependent.

          The following

              var o = { valueOf: function () { return null }, toString: function () { return '[The Object o]'; } }
              function f() { alert(this); }
              f.call(o)

          On IE it alerts '[The Object o]', but on Firefox 2 it alerts '[Window]'.

          Firefox must be coercing to a primitive first.  What's strange is that replacing valueOf with something that returns false does not trigger this behavior.

          mike



          On 09/10/2007, collin_jackson <collinj@...> wrote:

          I was not able to reproduce this behavior. I tried this URL:

          javascript:(function(){alert(window===this);}).call(null);

          I got an alert of "true" on Firefox 2.0.0.7, Internet Explorer 6, and
          Opera 9.23.

          What browser are you using?



          --- In caplet@yahoogroups.com, "Mark S. Miller" <erights@...> wrote:
          >
          > Let's refer to a Javascript function that mentions 'this' as a
          > Javascript method. When a Javascript method is called as a function,
          > it's 'this' gets bound to the global object.
          >
          > Because Caja code and Javascript code might call each other, Caja
          > needs to rewrite function calls as follows:
          >
          > foo(args...)
          >
          > translates to
          >
          > foo.call(<useless-object>, args....)
          >
          > That way, even if Caja code calls a Javascript method as a function,
          > it cannot trick that method into making unintended changes to the
          > Javascript global object.
          >
          > An annoying question is what to use for <useless-object>. Crock
          > informed me that neither null nor undefined would work, as Javascript
          > systems will helpfully substitute the global object instead.
          > Experimenting with this showed that it is indeed fatally dangerous,
          > but in a mysterious way:
          >
          >
          > function foo() { print(this); print(this === window); }
          >
          > foo()
          > [object Window]
          > true
          >
          > foo.call(undefined)
          > [object Window]
          > false
          >
          > foo.call(null)
          > [object Window]
          > false
          >
          > In the last two cases, 'this' did get bound to a Window object, but
          > not the global 'window'. What did it get bound to? Does anyone have
          > any idea what's going on?
          >
          > --
          > Cheers,
          > --MarkM
          >


        • Mark S. Miller
          ... Hi Colin, I m using Firefox 2.0.0.7 on a Mac-x86. When I try your javascript: url I get also get a true. But when I use the squarefree shell bookmarklet, I
          Message 4 of 13 , Oct 9, 2007
          • 0 Attachment
            On 10/9/07, collin_jackson <collinj@...> wrote:
            > I was not able to reproduce this behavior. I tried this URL:
            >
            > javascript:(function(){alert(window===this);}).call(null);
            >
            > I got an alert of "true" on Firefox 2.0.0.7, Internet Explorer 6, and
            > Opera 9.23.
            >
            > What browser are you using?

            Hi Colin,

            I'm using Firefox 2.0.0.7 on a Mac-x86. When I try your javascript:
            url I get also get a true. But when I use the squarefree shell
            bookmarklet, I get the results previously posted. Interesting.


            --
            Cheers,
            --MarkM
          • Mike Samuel
            I believe the squarefree shell executes shell commands like with (shellScope) { eval(shellCommand); } If shellScope uses window as its prototype then it d
            Message 5 of 13 , Oct 9, 2007
            • 0 Attachment
              I believe the squarefree shell executes shell commands like
                with (shellScope) {
                  eval(shellCommand);
                }

              If shellScope uses window as its prototype then it'd inherit the window's toString method.




              On 09/10/2007, Mark S. Miller <erights@...> wrote:

              On 10/9/07, collin_jackson <collinj@...> wrote:
              > I was not able to reproduce this behavior. I tried this URL:
              >
              > javascript:(function(){alert(window===this);}).call(null);
              >
              > I got an alert of "true" on Firefox 2.0.0.7, Internet Explorer 6, and
              > Opera 9.23.
              >
              > What browser are you using?

              Hi Colin,

              I'm using Firefox 2.0.0.7 on a Mac-x86. When I try your javascript:
              url I get also get a true. But when I use the squarefree shell
              bookmarklet, I get the results previously posted. Interesting.

              --
              Cheers,
              --MarkM


            • Mike Samuel
              Mark, I can t repeat your example under the squarefree shell on FF2.0.0.7 on Linux. And I can t reproduce by playing around with with blocks, window
              Message 6 of 13 , Oct 9, 2007
              • 0 Attachment
                Mark,

                I can't repeat your example under the squarefree shell on FF2.0.0.7 on Linux.
                And I can't reproduce by playing around with 'with' blocks, window subclasses, or eval.call.

                mike


                On 09/10/2007, Mike Samuel <mikesamuel@...> wrote:
                I believe the squarefree shell executes shell commands like
                  with (shellScope) {
                    eval(shellCommand);
                  }

                If shellScope uses window as its prototype then it'd inherit the window's toString method.





                On 09/10/2007, Mark S. Miller < erights@...> wrote:

                On 10/9/07, collin_jackson <collinj@...> wrote:
                > I was not able to reproduce this behavior. I tried this URL:
                >
                > javascript:(function(){alert(window===this);}).call(null);
                >
                > I got an alert of "true" on Firefox 2.0.0.7, Internet Explorer 6, and
                > Opera 9.23.
                >
                > What browser are you using?

                Hi Colin,

                I'm using Firefox 2.0.0.7 on a Mac-x86. When I try your javascript:
                url I get also get a true. But when I use the squarefree shell
                bookmarklet, I get the results previously posted. Interesting.

                --
                Cheers,
                --MarkM



              • Ben Laurie
                ... It got bound to your shell window (try defining function foo() { this.close(); }) and see what happens. Not sure what it gets bound to in the first case -
                Message 7 of 13 , Oct 10, 2007
                • 0 Attachment
                  Mark S. Miller wrote:
                  >
                  >
                  > Let's refer to a Javascript function that mentions 'this' as a
                  > Javascript method. When a Javascript method is called as a function,
                  > it's 'this' gets bound to the global object.
                  >
                  > Because Caja code and Javascript code might call each other, Caja
                  > needs to rewrite function calls as follows:
                  >
                  > foo(args...)
                  >
                  > translates to
                  >
                  > foo.call(<useless-object>, args....)
                  >
                  > That way, even if Caja code calls a Javascript method as a function,
                  > it cannot trick that method into making unintended changes to the
                  > Javascript global object.
                  >
                  > An annoying question is what to use for <useless-object>. Crock
                  > informed me that neither null nor undefined would work, as Javascript
                  > systems will helpfully substitute the global object instead.
                  > Experimenting with this showed that it is indeed fatally dangerous,
                  > but in a mysterious way:
                  >
                  > function foo() { print(this); print(this === window); }
                  >
                  > foo()
                  > [object Window]
                  > true
                  >
                  > foo.call(undefined)
                  > [object Window]
                  > false
                  >
                  > foo.call(null)
                  > [object Window]
                  > false
                  >
                  > In the last two cases, 'this' did get bound to a Window object, but
                  > not the global 'window'. What did it get bound to? Does anyone have
                  > any idea what's going on?

                  It got bound to your shell window (try defining "function foo() {
                  this.close(); }) and see what happens.

                  Not sure what it gets bound to in the first case - I didn't see anything
                  close :-)

                  >
                  > --
                  > Cheers,
                  > --MarkM
                  >
                  >


                  --
                  http://www.apache-ssl.org/ben.html http://www.links.org/

                  "There is no limit to what a man can do or how far he can go if he
                  doesn't mind who gets the credit." - Robert Woodruff
                • Mark S. Miller
                  ... I ve just repeated it on FF2.0.0.7 on Linux. For all the tests I ve done on both, I haven t yet seen any difference between FF on Linux vs. Mac. Ben s msg
                  Message 8 of 13 , Oct 10, 2007
                  • 0 Attachment
                    On 10/9/07, Mike Samuel <mikesamuel@...> wrote:
                    > I can't repeat your example under the squarefree shell on FF2.0.0.7 on Linux.
                    > And I can't reproduce by playing around with 'with' blocks, window subclasses, or eval.call.

                    I've just repeated it on FF2.0.0.7 on Linux. For all the tests I've
                    done on both, I haven't yet seen any difference between FF on Linux
                    vs. Mac. Ben's msg led to some more experiments:

                    When I try this using the standalone squarefree shell page at
                    http://www.squarefree.com/shell/shell.html I don't get the peculiar
                    behavior. It only happens when I use the squarefree shell bookmarklet
                    available from http://www.squarefree.com/bookmarklets/webdevel.html .
                    When using the bookmarklet, it does open the shell up in a different
                    window from the one it's examining. The mystery window from my example
                    is the bookmarklet's new window. Typing

                    function foo() {return this;}
                    foo.call(null).close()

                    into the bookmarklet's shell does cause it to close itself.

                    --
                    Cheers,
                    --MarkM
                  • Mike Samuel
                    To make sure I m clear, you re using the square free bookmarklet (the first entry, [shell], at http://www.squarefree.com/bookmarklets/webdevel.html) not
                    Message 9 of 13 , Oct 10, 2007
                    • 0 Attachment
                      To make sure I'm clear, you're using the square free bookmarklet (the first entry, [shell], at http://www.squarefree.com/bookmarklets/webdevel.html ) not http://www.squarefree.com/shell/shell.html.

                      And then you do
                        function foo() { print(this); print(this === window); }
                        foo.call(undefined)
                      and you get the output
                        [Window]
                        false
                      ?

                      I can repeat using the squarefree bookmarklet, but not the shell webpage.






                      On 10/10/2007, Mark S. Miller <erights@...> wrote:

                      On 10/9/07, Mike Samuel <mikesamuel@...> wrote:
                      > I can't repeat your example under the squarefree shell on FF2.0.0.7 on Linux.
                      > And I can't reproduce by playing around with 'with' blocks, window subclasses, or eval.call.

                      I've just repeated it on FF2.0.0.7 on Linux. For all the tests I've
                      done on both, I haven't yet seen any difference between FF on Linux
                      vs. Mac. Ben's msg led to some more experiments:

                      When I try this using the standalone squarefree shell page at
                      http://www.squarefree.com/shell/shell.html I don't get the peculiar
                      behavior. It only happens when I use the squarefree shell bookmarklet
                      available from http://www.squarefree.com/bookmarklets/webdevel.html .
                      When using the bookmarklet, it does open the shell up in a different
                      window from the one it's examining. The mystery window from my example
                      is the bookmarklet's new window. Typing

                      function foo() {return this;}
                      foo.call(null).close()

                      into the bookmarklet's shell does cause it to close itself.

                      --
                      Cheers,
                      --MarkM


                    • Mark Miller
                      ... Yes exactly. -- Text by me above is hereby placed in the public domain Cheers, --MarkM
                      Message 10 of 13 , Oct 10, 2007
                      • 0 Attachment
                        On 10/10/07, Mike Samuel <mikesamuel@...> wrote:
                        > To make sure I'm clear, you're using the square free bookmarklet (the first entry, [shell], at
                        > http://www.squarefree.com/bookmarklets/webdevel.html ) not
                        > http://www.squarefree.com/shell/shell.html.
                        >
                        > And then you do
                        > function foo() { print(this); print(this === window); }
                        > foo.call(undefined)
                        > and you get the output
                        > [Window]
                        > false
                        > ?
                        >
                        > I can repeat using the squarefree bookmarklet, but not the shell webpage.


                        Yes exactly.


                        --
                        Text by me above is hereby placed in the public domain

                        Cheers,
                        --MarkM
                      • Mike Samuel
                        The reason for this is in the first line of the bookmarklet with(window.open(...)) { ... } Each window object has an eponymous property, window . This with
                        Message 11 of 13 , Oct 10, 2007
                        • 0 Attachment
                          The reason for this is in the first line of the bookmarklet
                              with(window.open(...)) { ... }

                          Each window object has an eponymous property, 'window'.

                          This 'with' block causes apparent globals to instead be interpreted as properties of the opened window, so this may still be the window that was in focus when you clicked the bookmark, but this.window !== this, since this.window is resolved as a property of the window.

                          I tried deleting the window and assigning window to this, but rerunning it doesn't change behavior.  I think that may be a cross-domain thing though.  window's are manipulable across domain since a window needs to be able to set a frame's location, but they don't allow setting of arbitrary properties such as "window" cross-domain.

                          mike




                          On 10/10/2007, Mike Samuel <mikesamuel@...> wrote:
                          To make sure I'm clear, you're using the square free bookmarklet (the first entry, [shell], at http://www.squarefree.com/bookmarklets/webdevel.html ) not http://www.squarefree.com/shell/shell.html.

                          And then you do
                            function foo() { print(this); print(this === window); }
                            foo.call(undefined)
                          and you get the output
                            [Window]
                            false
                          ?

                          I can repeat using the squarefree bookmarklet, but not the shell webpage.







                          On 10/10/2007, Mark S. Miller <erights@...> wrote:

                          On 10/9/07, Mike Samuel <mikesamuel@...> wrote:
                          > I can't repeat your example under the squarefree shell on FF2.0.0.7 on Linux.
                          > And I can't reproduce by playing around with 'with' blocks, window subclasses, or eval.call.

                          I've just repeated it on FF2.0.0.7 on Linux. For all the tests I've
                          done on both, I haven't yet seen any difference between FF on Linux
                          vs. Mac. Ben's msg led to some more experiments:

                          When I try this using the standalone squarefree shell page at
                          http://www.squarefree.com/shell/shell.html I don't get the peculiar
                          behavior. It only happens when I use the squarefree shell bookmarklet
                          available from http://www.squarefree.com/bookmarklets/webdevel.html .
                          When using the bookmarklet, it does open the shell up in a different
                          window from the one it's examining. The mystery window from my example
                          is the bookmarklet's new window. Typing

                          function foo() {return this;}
                          foo.call(null).close()

                          into the bookmarklet's shell does cause it to close itself.

                          --
                          Cheers,
                          --MarkM



                        • Mike Samuel
                          ... err assigning window to this - assigning window to this.window cross-domain thing though. window s are manipulable across domain since a
                          Message 12 of 13 , Oct 10, 2007
                          • 0 Attachment
                            On 10/10/2007, Mike Samuel <mikesamuel@...> wrote:
                            The reason for this is in the first line of the bookmarklet
                                with(window.open(...)) { ... }

                            Each window object has an eponymous property, 'window'.

                            This 'with' block causes apparent globals to instead be interpreted as properties of the opened window, so this may still be the window that was in focus when you clicked the bookmark, but this.window !== this, since this.window is resolved as a property of the window.

                            I tried deleting the window and assigning window to this, but rerunning it doesn't change behavior.  I think that may be a

                            err assigning window to this -> assigning window to this.window
                             

                            cross-domain thing though.  window's are manipulable across domain since a window needs to be able to set a frame's location, but they don't allow setting of arbitrary properties such as "window" cross-domain.

                            mike





                            On 10/10/2007, Mike Samuel < mikesamuel@...> wrote:
                            To make sure I'm clear, you're using the square free bookmarklet (the first entry, [shell], at http://www.squarefree.com/bookmarklets/webdevel.html ) not http://www.squarefree.com/shell/shell.html.

                            And then you do
                              function foo() { print(this); print(this === window); }
                              foo.call(undefined)
                            and you get the output
                              [Window]
                              false
                            ?

                            I can repeat using the squarefree bookmarklet, but not the shell webpage.







                            On 10/10/2007, Mark S. Miller <erights@...> wrote:

                            On 10/9/07, Mike Samuel <mikesamuel@...> wrote:
                            > I can't repeat your example under the squarefree shell on FF2.0.0.7 on Linux.
                            > And I can't reproduce by playing around with 'with' blocks, window subclasses, or eval.call.

                            I've just repeated it on FF2.0.0.7 on Linux. For all the tests I've
                            done on both, I haven't yet seen any difference between FF on Linux
                            vs. Mac. Ben's msg led to some more experiments:

                            When I try this using the standalone squarefree shell page at
                            http://www.squarefree.com/shell/shell.html I don't get the peculiar
                            behavior. It only happens when I use the squarefree shell bookmarklet
                            available from http://www.squarefree.com/bookmarklets/webdevel.html .
                            When using the bookmarklet, it does open the shell up in a different
                            window from the one it's examining. The mystery window from my example
                            is the bookmarklet's new window. Typing

                            function foo() {return this;}
                            foo.call(null).close()

                            into the bookmarklet's shell does cause it to close itself.

                            --
                            Cheers,
                            --MarkM




                          • Mike Samuel
                            The below causes the same symptoms in both squarefree shells: var f = document.createElement( iframe ); document.body.appendChild(f); with (f.contentWindow) {
                            Message 13 of 13 , Oct 10, 2007
                            • 0 Attachment
                              The below causes the same symptoms in both squarefree shells:
                                    var f = document.createElement('iframe');
                                    document.body.appendChild(f);
                                    with (f.contentWindow) {
                                      (function foo() { alert(this + ' : ' + (this === window)); }).call(null);
                                    }

                              If the goal is to detect at the beginning of a function body whether `this` is the global scope, I don't think there's any underlying equivalence between between 'this' and 'window' in a normal browser environment, but it does raise questions for applications that execute javascript cross-frame.

                              mike


                              On 10/10/2007, Mike Samuel <mikesamuel@...> wrote:


                              On 10/10/2007, Mike Samuel < mikesamuel@...> wrote:
                              The reason for this is in the first line of the bookmarklet
                                  with(window.open(...)) { ... }

                              Each window object has an eponymous property, 'window'.

                              This 'with' block causes apparent globals to instead be interpreted as properties of the opened window, so this may still be the window that was in focus when you clicked the bookmark, but this.window !== this, since this.window is resolved as a property of the window.

                              I tried deleting the window and assigning window to this, but rerunning it doesn't change behavior.  I think that may be a

                              err assigning window to this -> assigning window to this.window
                               

                              cross-domain thing though.  window's are manipulable across domain since a window needs to be able to set a frame's location, but they don't allow setting of arbitrary properties such as "window" cross-domain.

                              mike





                              On 10/10/2007, Mike Samuel <mikesamuel@...> wrote:
                              To make sure I'm clear, you're using the square free bookmarklet (the first entry, [shell], at http://www.squarefree.com/bookmarklets/webdevel.html ) not http://www.squarefree.com/shell/shell.html.

                              And then you do
                                function foo() { print(this); print(this === window); }
                                foo.call(undefined)
                              and you get the output
                                [Window]
                                false
                              ?

                              I can repeat using the squarefree bookmarklet, but not the shell webpage.







                              On 10/10/2007, Mark S. Miller <erights@...> wrote:

                              On 10/9/07, Mike Samuel <mikesamuel@...> wrote:
                              > I can't repeat your example under the squarefree shell on FF2.0.0.7 on Linux.
                              > And I can't reproduce by playing around with 'with' blocks, window subclasses, or eval.call.

                              I've just repeated it on FF2.0.0.7 on Linux. For all the tests I've
                              done on both, I haven't yet seen any difference between FF on Linux
                              vs. Mac. Ben's msg led to some more experiments:

                              When I try this using the standalone squarefree shell page at
                              http://www.squarefree.com/shell/shell.html I don't get the peculiar
                              behavior. It only happens when I use the squarefree shell bookmarklet
                              available from http://www.squarefree.com/bookmarklets/webdevel.html .
                              When using the bookmarklet, it does open the shell up in a different
                              window from the one it's examining. The mystery window from my example
                              is the bookmarklet's new window. Typing

                              function foo() {return this;}
                              foo.call(null).close()

                              into the bookmarklet's shell does cause it to close itself.

                              --
                              Cheers,
                              --MarkM





                            Your message has been successfully submitted and would be delivered to recipients shortly.