Unsafe Names for HTML Form Controls

Event Handler Scope

Event Handler Content Attributes and Augmented Scope Chain

Event Handler Content Attributes are event handler attributes that appear in the HTML source.

When an element has an event handler content attribute, the value of that attribute becomes the FunctionBody of a function that the browser calls when it fires that event.

Modern browsers augment the FunctionBody's scope chain with the element, the element's FORM (if it is a form control), and document. There is no official standard for this augmented scope chain.

Older browsers, such as Safari 2, Mozilla 1.x, Opera 7, differ. Scope augmentation occurs for all event handler content attributes with the notable exception of the body element, for which event handler scope is not consistently augmented across event types and implementations.

The context (thisArg) is (with the exception of body), the element itself. In the browsers that implement DOM Events [DOMEvents], the event handler function has a single parameter named event.

Given the following markup:

<p onclick="self.alert(event);"></p>

The augmented scope chain, if written in ECMAScript, would look like:

function onclick(event) {
  with(document) {
    with(this.form) {
      with(this) {
        self.alert(event);
      }
    }
  }
}

Note that some browsers will not supply an event parameter.

Example 3: Augmented Scope Chain

This example shows how window and document are shadowed:

Source:
<form action="">
  <input type="hidden" name="document">  
  <button type="button" name="window" 
  onclick="self.alert([window.tagName, document.tagName])">self.alert([window.tagName, document.tagName])</button>
</form>

The augmented scope chain, if written in ECMAScript, would look like:

function onclick(event) {
  with(document) {
    with(this.form) {
      with(this) {
        self.alert([title, files, focus == window.focus]);
          var e = event||window.event;
          if(e && e.preventDefault) e.preventDefault();
          e.returnValue = false;
      }
    }
  }
}

For all intents and purposes, the browser's window property of the global object is an alias to the the global object itself.

Relying on an augmented scope chain to resolve properties may have unexpected results in different environments (i.e. browsers). The following example shows how in at least two browsers, files is resolved as a property of an input element.

<script type="text/javascript">
var files = [1,2,3];
</script>

<form action="">
 <input onclick="self.alert([title, files, focus == window.focus]);
 var e = event||window.event;
 if(e && e.preventDefault) e.preventDefault();
 e.returnValue = false;" type="file">
</form>

Result

Firefox 3, Safari 3:
",[object FileList],false"
Opera 9.5, IE7, IE8:
",1,2,3,false"

The identifier files is resolved on the input element in Firefox 3 and Safari 3. In IE8 or Opera 9.5, files is resolved on the window object.

A modified example from c.l.js thread "Works in ie and opera not mozilla", by Richard Cornford.

Browsers Tested:

Results:

ex0 = global
ex1 = document #document
ex2 = document #document
ex3 = document #document
ex4 = 4 FORM
ex5 = 4 FORM
ex6 = 4 FORM
ex7 = 7 INPUT
ex8 = 7 INPUT
ex9 = 7 INPUT

// First link

ex0 = global
ex1 = document #document
ex2 = document #document
ex3 = document #document
ex4 = document #document
ex5 = document #document
ex6 = document #document
ex7 = document #document
ex8 = 8 A
ex9 = 8 A

// Second link

ex0 = global
ex1 = document #document
ex2 = document #document
ex3 = document #document
ex4 = document #document
ex5 = document #document
ex6 = document #document
ex7 = document #document
ex8 = document #document
ex9 = 9 A

Most of the above results were provided by Juriy Zaytsev on thread Cross-Browser Mouse Event Handling.

Older Browsers

Less recent browsers, including Safari 2.0.4, Mozilla 1.x, and Opera 7, featured different scope chains.

Exception: The BODY Tag.

The body tag's event handler attributes are either mapped to window (which has no tag) or to the BODY element. Results vary based on the event and the browser. Do not use event handler attributes for the body element.

Problem

An augmented scope chain, combined with event handler content attributes, means that properties of the element itself, the element's form (if it is a form control), and document, may shadow properties of the window object. As explained in: select?, and hashchange only dispatched in history traversal, comments by Garrett Smith. Shortened code excerpt:

<img name='alert' alt="Alert!" src="alert.jpg">
<button onclick="self.alert(alert);">self.alert(alert);</button>
Alert!

Result

Alerts [object HTMLImageElement] (or similar implementation-dependent string).

By using an unsafe name of "alert" for an IMG, The window's alert property identifier is shadowed by document's alert property identifier because document is in the event handler's augmented scope before window.

By using event handler content attributes and unsafe names, document and window, the respective identifiers are resolved on the augmented scope chain.

The augmented scope chain creates more ambiguity and increases the number of unsafe names.

Solution

Table of Contents