Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'username' and 'password' in inline Javascript event handler in Chrome/Firefox

The variables username and password do not retain their original value (as defined in the script tag) or are not accessible from the onclick event, however making a function call that outputs the variables does. It seems as though the variables are being redefined inside that scope because they are not undefined even if I don't define them.

It appears to be due to the variables being named username and password, as shown in the code sample below (usr and passwd work as expected.)

There is reason to believe this behaviour has been introduced into recent versions of the browser as older Firefox doesn't exhibit it.

Here is a reproducible code sample (tested in Google Chrome 32 / Firefox 26 - however some users are reporting that it does not work for them):

<html>
<head>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <script>
        var username = "Administrator";
        var password = "AdminPass";

        var usr = "Jordan";
        var passwd = "JordanPass";

        function printCredentials() {
            $("#out").append("username is: " + username + "<br/>");
            $("#out").append("password is: " + password + "<br/>");
            $("#out").append("usr is: " + usr + "<br/>");
            $("#out").append("passwd is: " + passwd + "<br/>");
        }
    </script>
</head>
<body>
    <a href="#" onclick="printCredentials()">This works</a><br/>
    <a href="#" onclick="$('#out').append('username is: ' + username + '<br/>'); $('#out').append('password is: ' + password + '<br/>'); $('#out').append('usr is: ' + usr + '<br/>');  $('#out').append('passwd is: ' + passwd + '<br/>');">But this doesn't (properly)</a><br/>
    <div id="out" style="background: yellow"></div>
</body>
</html>

JSFiddle demo

Using jQuery is optional, the same happens with regular JS.

Clicking the second link prints out usr and passwd as expected but username and password are blank. Curiously, it works as expected (all fields printed) in Internet Explorer.

What is going on here?

like image 375
Elle Avatar asked Jan 30 '14 03:01

Elle


People also ask

How should I store my username and password in HTML?

On submit javascript posts the username and password to a php script on the server which returns 'true' or 'false'. When the authentication returns true the app changes the html5 page and stores the username and password in html5 local storage.

What is inline JavaScript event handling?

An event handler is a JavaScript function that runs when an event fires. An event listener attaches responsiveness to a given element, which allows the element to wait or “listen” for the given event to fire. Events can be assigned to elements via inline event handlers, event handler properties & event listeners.

How are event handlers registered in JavaScript?

You can register event handlers for either phase, bubbling or capturing, by using the function addEventListener(type, listener, useCapture) . If useCapture is set to false , the event handler is in the bubbling phase. Otherwise it's in the capture phase. The order of the phases of the event depends on the browser.


1 Answers

Here's a break down why you can't see username and password attribute

First of all, <a> tag is capable of parsing the url in href attribute and make the parsed values into its own property.

NOTE URL syntax <protocol>://<user>:<password>@<host>:<port>/<url-path>

var a = document.createElement('a');
a.setAttribute('href', 'http://john:[email protected]');

// Do you get the idea now?
a.username // prints "john"
a.password // prints "doe"

That's it, your inline onclick is being executed against a's scope which already has both username and password property defined (with "" values)

+----------------+
| window.username|  <-- your "Administrator"
|                |
| +------------+ |
| | a.username | |  <-- empty by default ""
| +------------+ |
+----------------+

EDIT: In case you would like to see the Chrome's source code where it defines username/password interface & implementation

Interface: https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/core/dom/DOMURLUtils.h&l=47&rcl=1391416355

Implementation: https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/core/dom/DOMURLUtils.cpp&l=48&rcl=1391416355

Explanation: When I answer this question I assumed that everyone already knows about this keyword in onclick event and Scope in javascript, but looks like it's not clear enough (my bad).

This line "is being executed against <a>'s scope" means that,

onclick="alert(username)" === onclick="alert(this.username)"

That is, you can think of anything in onclick is an anonymous function which is bound to <a> tag so

onclick = function() {
    log(this);     // 1. bound to `<a>` not `window`
    log(username); // 2. implies `this.username` unless you explicitly declare 'var username`
}

How Javascript scope works is, if it can't find that variable (username) in local scope, it will look at the outer scope for it window.username.

Hope that should make it more clearer.

like image 137
Rezigned Avatar answered Oct 15 '22 21:10

Rezigned