Various mechanisms can cause author-provided executable code to run in the context of a document. These mechanisms include, but are probably not limited to:
script elements.
javascript: URIs (e.g. the src attribute of img elements, or an @import
rule in a CSS style element block).
addEventListener(), by explicit event
handler content attributes, by event handler DOM
attributes, or otherwise.
User agents may provide a mechanism to enable or disable the execution of author-provided code. When the user agent is configured such that author-provided code does not execute, or if the user agent is implemented so as to never execute author-provided code, it is said that scripting is disabled. When author-provided code does execute, scripting is enabled. A user agent with scripting disabled is a user agent with no scripting support for the purposes of conformance.
Access to certain APIs is granted or denied to scripts based on the origin of the script and the API being accessed.
The origin of a script depends on the context of that script:
script element
Document to
which the script element belongs.
javascript: URI in an attribute
Document of the element
on which the attribute is found.
javascript: URI in a style sheet
Document to which the
style sheet applies.
javascript: URI to which a browsing context is being navigated, the URI having been provided by the user
(e.g. by using a bookmarklet)
Document of the browsing context's active
document.
javascript: URI to which a browsing context is being navigated, the URI having been declared in markup
Document of the element
(e.g. an a or area element) that declared the URI.
javascript: URI to which a browsing context is being navigated, the URI having been provided by script
The origin of scripts thus comes down to finding the origin of
Document objects.
The origin of a Document or image that was served over the
network and whose address uses a URI scheme with a server-based naming
authority is the tuple consisting of the <scheme>,
<host>/<ihost>, and <port> parts of the
Document's full URI. [RFC3986] [RFC3987]
The origin of a Document or image that was generated from a
data: URI found in another Document or in a
script is the origin of the Document or script.
The origin of a Document or image that was generated from a
data: URI from another source is a globally unique identifier
assigned when the document is created.
The origin of a Document or image that was generated from a
javascript: URI is the same as the origin of
that javascript: URI.
The string representing the script's domain in IDNA format is obtained as follows: take the domain part of the script's origin tuple and apply the IDNA ToASCII algorithm and then the IDNA ToUnicode algorithm to each component of the domain name (with both the AllowUnassigned and UseSTD3ASCIIRules flags set both times). [RFC3490]
If ToASCII fails to convert one of the components of the string, e.g. because it is too long or because it contains invalid characters, or if the origin of the script has no domain part, then the string representing the script's domain in IDNA format cannot be obtained. (ToUnicode is defined to never fail.)
It's been suggested that we should put IP addresses into the origin tuple, to mitigate DNS rebinding attacks. However that would kill multi-homed systems like GMail. Should we do something like have a DNS record say whether or not to include the IP in the origin for a host?
When two URIs are to be compared to determine if they have the same scheme/host/port, it means that the following algorithm must be invoked, where uri1 and uri2 are the two URIs.
First, both uri1 and uri2 must be normalized to obtain the two tuples (scheme1, host1, port1) and (scheme2, host2, port2), by applying the following subalgorithm to each URI:
Let uri be the URI being normalized.
Parse uri according to the rules described in RFC 3986 and RFC 3987. [RFC3986] [RFC3987]
If uri does not use a server-based naming authority, then fail the overall algorithm — the two URIs do not have the same scheme/host/port.
Let scheme be the <scheme> component of the URI. If the UA doesn't support the given protocol, then fail the overall algorithm — the two URIs do not have the same scheme/host/port.
Let host be the <host>/<ihost> component of the URI.
Apply the IDNA ToASCII algorithm to host, with both the AllowUnassigned and UseSTD3ASCIIRules flags set. Let host be the result of the ToASCII algorithm.
If ToASCII fails to convert one of the components of the string, e.g. because it is too long or because it contains invalid characters, then fail the overall algorithm — the two URIs do not have the same scheme/host/port. [RFC3490]
If no port is explicitly listed, then let port be the default port for the protocol given by scheme. Otherwise, let port be the <port> component of the URI.
Return the tuple (scheme, host, port).
If scheme1 is not case-insensitively identical to scheme2, or if host1 is not case-insensitively identical to host2, or if port1 is not identical to port2, then fail the overall algorithm — the two URIs do not have the same scheme/host/port.
Otherwise, the two URIs do have the same scheme/host/port.
Define security exception.
javascript: protocolA URI using the javascript: protocol must, if
evaluated, be evaluated using the in-context evaluation operation defined
for javascript: URIs. [JSURI]
When a browsing context is navigated to a javascript: URI, and the active document of that browsing context has the same
origin as the URI, the dereference context must be
the browsing context being navigated.
When a browsing context is navigated to a javascript: URI, and the active document of that browsing context has a
different origin than the URI, the
dereference context must be an empty object.
Otherwise, the dereference context must the browsing context of the Document to
which belongs the element for which the URI is being dereferenced, or to
which the style sheet for which the URI is being dereferenced applies,
whichever is appropriate.
URIs using the javascript: protocol should be
evaluated when the resource for that URI is needed, unless scripting is disabled or the Document
corresponding to the dereference context (as defined above), if any, has
designMode enabled.
If the dereference by-product is void (there is no return value), then the URI must be treated in a manner equivalent to an HTTP resource with an HTTP 204 No Content response.
Otherwise, the URI must be treated in a manner equivalent to an HTTP
resource with a 200 OK response whose Content-Type metadata is text/html and whose response body is the dereference
by-product, converted to a string value.
Certain contexts, in particular img elements, ignore the Content-Type metadata.
So for example a javascript: URI for a src attribute of an img element would be evaluated in the context of
the page as soon as the attribute is set; it would then be sniffed to
determine the image type and decoded as an image.
A javascript: URI in an href attribute of an a element would only be evaluated when the link was
followed.
The src
attribute of an iframe element would
be evaluated in the context of the iframe's own browsing
context; once evaluated, its return value (if it was not void) would
replace that browsing context's document, thus
changing the variables visible in that browsing
context.
We need to define how to handle events that are to be
fired on a Document that is no longer the active document of its browsing
context, and for Documents that have no browsing context. Do the events
fire? Do the handlers in that document not fire? Do we just define
scripting to be disabled when the document isn't active, with events still
running as is? See also the script
element section, which says scripts don't run when the document isn't
active.
HTML elements can have event handler attributes specified. These act as bubbling event listeners for the element on which they are specified.
Each event handler attribute has two parts, an event handler content
attribute and an event handler DOM attribute. Event handler attributes must
initially be set to null. When their value changes (through the changing
of their event handler content attribute or their event handler DOM
attribute), they will either be null, or have an
EventListener object assigned to them.
Objects other than Element objects, in particular Window, only have event handler DOM attribute (since they have
no content attributes).
Event handler content attributes, when specified,
must contain valid ECMAScript code matching the ECMAScript FunctionBody production. [ECMA262]
When an event handler content attribute is set, its new value must be
interpreted as the body of an anonymous function with a single argument
called event, with the new function's scope chain being
linked from the activation object of the handler, to the element, to the
element's form element if it is a form control, to the
Document object, to the browsing
context of that Document. The function's
this parameter must be the Element object
representing the element. The resulting function must then be set as the
value of the corresponding event handler attribute, and the new value must
be set as the value of the content attribute. If the given function body
fails to compile, then the corresponding event handler attribute must be
set to null instead (the content attribute must still be updated to the
new value, though).
See ECMA262 Edition 3, sections 10.1.6 and 10.2.3, for more details on activation objects. [ECMA262]
How do we allow non-JS event handlers?
Event handler DOM attributes, on setting, must set the corresponding event handler attribute to their new value, and on getting, must return whatever the current value of the corresponding event handler attribute is (possibly null).
The following are the event handler attributes that must be supported by
all HTML elements, as both content attributes
and DOM attributes, and on Window
objects, as DOM attributes:
onabort
Must be invoked whenever an abort event is targeted at or bubbles through
the element.
onbeforeunload
Must be invoked whenever a beforeunload event is targeted at or
bubbles through the element.
onblurMust be invoked whenever a blur event is
targeted at or bubbles through the element.
onchangeMust be invoked whenever a change
event is targeted at or bubbles through the element.
onclickMust be invoked whenever a click event
is targeted at or bubbles through the element.
oncontextmenuMust be invoked whenever a contextmenu event is targeted at or
bubbles through the element.
ondblclickMust be invoked whenever a dblclick
event is targeted at or bubbles through the element.
ondrag
Must be invoked whenever a drag event is targeted at or bubbles through the
element.
ondragend
Must be invoked whenever a dragend event is targeted at or bubbles
through the element.
ondragenter
Must be invoked whenever a dragenter event is targeted at or bubbles
through the element.
ondragleave
Must be invoked whenever a dragleave event is targeted at or bubbles
through the element.
ondragover
Must be invoked whenever a dragover event is targeted at or bubbles
through the element.
ondragstartMust be invoked whenever a dragstart event is targeted at or bubbles
through the element.
ondrop
Must be invoked whenever a drop event is targeted at or bubbles through the
element.
onerrorMust be invoked whenever an error event is targeted at or bubbles through
the element.
The onerror handler is also used for reporting script errors.
onfocusMust be invoked whenever a focus event
is targeted at or bubbles through the element.
onkeydownMust be invoked whenever a keydown
event is targeted at or bubbles through the element.
onkeypressMust be invoked whenever a keypress
event is targeted at or bubbles through the element.
onkeyupMust be invoked whenever a keyup event
is targeted at or bubbles through the element.
onloadMust be invoked whenever a load event is targeted at or bubbles through
the element.
onmessageMust be invoked whenever a message event is targeted at or bubbles
through the element.
onmousedownMust be invoked whenever a mousedown event is targeted at or bubbles
through the element.
onmousemoveMust be invoked whenever a mousemove event is targeted at or bubbles
through the element.
onmouseoutMust be invoked whenever a mouseout
event is targeted at or bubbles through the element.
onmouseoverMust be invoked whenever a mouseover event is targeted at or bubbles
through the element.
onmouseupMust be invoked whenever a mouseup
event is targeted at or bubbles through the element.
onmousewheelMust be invoked whenever a mousewheel event is targeted at or bubbles
through the element.
onresizeMust be invoked whenever a resize
event is targeted at or bubbles through the element.
onscrollMust be invoked whenever a scroll
event is targeted at or bubbles through the element.
onselectMust be invoked whenever a select event is targeted at or bubbles through
the element.
onsubmitMust be invoked whenever a submit
event is targeted at or bubbles through the element.
onunloadMust be invoked whenever an unload
event is targeted at or bubbles through the element.
When an event handler attribute is invoked, its argument must be set to
the Event object of the event in question. If the function
returns the exact boolean value false, the event's
preventDefault() method must then invoked. Exception: for
historical reasons, for the HTML mouseover event, the
preventDefault() method must be called when the function
returns true instead.
When scripting is disabled, event handler attributes must do nothing.
When scripting is enabled, all event handler
attributes on an element, whether set to null or to a function, must be
registered as event listeners on the element, as if the addEventListenerNS()
method on the Element object's EventTarget
interface had been invoked when the element was created, with the event
type (type argument) equal to the type
described for the event handler attribute in the list above, the namespace
(namespaceURI argument) set to
null, the listener set to be a target and bubbling phase listener (useCapture argument set to false), the
event group set to the default group (evtGroup argument set to null), and the
event listener itself (listener
argument) set to do nothing while the event handler attribute is null, and
set to invoke the function associated with the event handler attribute
otherwise.
maybe this should be moved higher up (terminology? conformance? DOM?) Also, the whole terminology thing should be changed so that we don't define any specific events here, we only define 'simple event', 'progress event', 'mouse event', 'key event', and the like, and have the actual dispatch use those generic terms when firing events.
Certain operations and methods are defined as firing events on elements.
For example, the click()
method on the HTMLElement
interface is defined as firing a click
event on the element. [DOM3EVENTS]
Firing a click event means that a click
event with no namespace, which bubbles and is cancelable, and which uses
the MouseEvent interface, must be dispatched at the given
element. The event object must have its screenX,
screenY, clientX, clientY, and button attributes set
to 0, its ctrlKey, shiftKey,
altKey, and metaKey attributes
set according to the current state of the key input device, if any (false
for any keys that are not available), its detail
attribute set to 1, and its relatedTarget attribute
set to null. The getModifierState() method on the
object must return values appropriately describing the state of the key
input device at the time the event is created.
Firing a change event means that a change
event with no namespace, which bubbles but is not cancelable, and which
uses the Event interface, must be dispatched at the given
element. The event object must have its detail
attribute set to 0.
Firing a contextmenu event means that a contextmenu event with no namespace, which
bubbles and is cancelable, and which uses the Event
interface, must be dispatched at the given element. The event object must
have its detail attribute set to 0.
Firing a simple event called
e means that an event with the name e, with no namespace, which does not bubble but is
cancelable, and which uses the Event interface, must be
dispatched at the given element.
Firing a show event means firing a simple event called show. Actually this should
fire an event that has modifier information (shift/ctrl etc).
Firing a load event means firing a simple event called load.
Firing an error event means firing a simple event called error.
Firing a progress event called e means something that hasn't yet been defined, in the [PROGRESS] spec.
The default action of these event is to do nothing unless otherwise stated.
If you dispatch a custom "click" event at an element that would normally have default actions, should they get triggered? If so, we need to go through the entire spec and make sure that any default actions are defined in terms of any event of the right type on that element, not those that are dispatched in expected ways.
Window objectWhen an event is dispatched at a DOM node in a Document in
a browsing context, if the event is not a load event, the user agent
must also dispatch the event to the Window, as follows:
Window object before being dispatched to any of
the nodes.
Window object at the end of the phase, unless
bubbling has been prevented.
This section only applies to user agents that support scripting in general and ECMAScript in particular.
Whenever a runtime script error occurs in one of the scripts associated
with the document, the value of the onerror event handler DOM
attribute of the Window object
must be processed, as follows:
The function referenced by the onerror attribute must be invoked with three
arguments, before notifying the user of the error.
The three arguments passed to the function are all
DOMStrings; the first must give the message that the UA is
considering reporting, the second must give the URI to the resource in
which the error occured, and the third must give the line number in that
resource on which the error occured.
If the function returns false, then the error should not be reported to the user. Otherwise, if the function returns another value (or does not return at all), the error should be reported to the user.
Any exceptions thrown or errors caused by this function must be reported to the user immediately after the error that the function was called for, without calling the function again.
null
The error should not reported to the user.
The error should be reported to the user.
The initial value of onerror must be undefined.