This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.
I was browsing Kangax's strict mode test result page (http://kangax.github.com/es5-compat-table/strict-mode/ ) and I noticed that he listed the recognition of a use strict directive of a event handler as a "non-standard" feature that he tests for. This spiked my curiosity as my recollection was the HTML5 event handler content attribute was specified to be text that is an ECMAScript FunctionBody. FunctionBody may contain a Directive Prologue that includes a use strict directive so, from an ECMAScript perspective, there shouldn't be anything non-standard about a strict mode event handler. To be sure, I checked the event handler section of the HTML5 spec (http://dev.w3.org/html5/spec/Overview.html#event-handler-attributes) and to my surprise I discovered that it specifies the creation of the handler function in a manner that, at first glance, seems to explicitly cause the presence of a use strict directive to be ignored. Essentially it seems to specify that event handlers specified using the event handler attribute are never executed in ECMAScript 5 strict mode. I don't know whether or not this was intentional, but it certainly seems wrong. The "strictness" of an ECMAScript function is an internal and local characteristic of the function. For a ECMAScript host to say that a use strict directive is ignored is really no different from saying that IfStatements or any other syntactically valid element of a FunctionBody will be ignored. The HTML5 spec. get into this trouble because of the way it uses the abstract operation for creating function objects defined by section 13.2 of the ES5 specification (http://www.ecma-international.org/publications/standards/Ecma-262.htm). In step 2 of the algorithm in HTML5 6.1.6.1 it unconditionally uses False as the Strict parameter to the ES5 13.2 algorithm. That might seem to exclude the function from strict mode, however that isn't actually the case. All the Strict parameter to 13.2 controls is whether or not "poison-pill" properties for 'caller' and 'arguments' are created for the function object. The semantics of strict mode are specified throughout the ES5 specification and are control by the actual lexical occurrence of a use strict directive. The Strict parameter to 13.2 does not alter this semantics. The HTML5 spec. also contains another related bug. Step three says "If the previous steps failed to compile the script, then ..." where the "previous steps" pretty clearly references the use of ES5 13.2 in the immediately preceding step 2. However, there is nothing in ES5 13.2 that concerns the compilation of ECMAScript source text. Instead 13.2 expects to be passed an valid FunctionBody. That validation ("compilation") must occur somewhere else. It appears to me that these problem are probably the result of the HTML5 algorithm being patterned after the wrong parts of the ES5 spec. The appropriate part of the ES5 spec. to use as a model is steps 8-11 of ES5 15.3.2.1. This is the definition of the Function constructor. These steps correctly take care of parsing the FunctionBody and handling any resulting syntax errors. It also calls 13.2 with a correct Strict parameter. Replacing HTML5 6.1.6.1 steps 2-3 with steps modeled after ES5 15.3.2.1 steps, 8, 9, and 11 (step 10 is not applicable) should correct these issues. Finally, Kangax also lists as a "non-standard" feature the recognition of strict coder as the string argument to setTimeout. I couldn't find anything the HTML5 spec. that could be interpreted as excluding strict ECMAScript code in this context. Here is better language to use in 6.1.6.1: replace existing steps 2-3 with: ---------------------- 2. Let body be the event handler content attribute's new value. 3. If body cannot be parsed as an ECMAScript FunctionBody as specified in [ECMA262] clause 13, then set the corresponding event handler to null and abort these steps. 4. Using this script execution environment from step 1, create a function object (as defined in ECMAScript edition 5 section 13.2 Creating Function Objects), with: Parameter list FormalParameterList If the attribute is the onerror attribute of the Window object Let the function have three arguments, named event, source, and fileno. Otherwise Let the function have a single argument called event. Function body FunctionBody The event handler content attribute's new value. Lexical Environment Scope Let Scope be the result of NewObjectEnvironment(the element's Document, the global environment). If the element has a form owner, let Scope be the result of NewObjectEnvironment(the element's form owner, Scope). Let Scope be the result of NewObjectEnvironment(the element's object, Scope). NewObjectEnvironment() is defined in ECMAScript edition 5 section 10.2.2.3 NewObjectEnvironment (O, E). [ECMA262] Boolean flag Strict If body is strict mode code let Strict be true, otherwise let Strict be false. Let this new function be the only entry in the script's list of code entry-points. --------------------- Renumber existing steps 4&5 as 5&6
Thanks, will look into this.
EDITOR'S RESPONSE: This is an Editor's Response to your comment. If you are satisfied with this response, please change the state of this bug to CLOSED. If you have additional information and would like the editor to reconsider, please reopen this bug. If you would like to escalate the issue to the full HTML Working Group, please add the TrackerRequest keyword to this bug, and suggest title and text for the tracker issue; or you may create a tracker issue yourself, if you are able to do so. For more details, see this document: http://dev.w3.org/html5/decision-policy/decision-policy.html Status: Accepted Change Description: see diff given below Rationale: Concurred with reporter's comments. Based on my reading the spec, it looks like we actually need to do a little more than was proposed in comment 0, so please do check to make sure I didn't screw anything up. It would be really nice if the JS spec could just give us hooks that we could use so that we didn't have to worry about updating HTML every time the JS spec revs.
Checked in as WHATWG revision r5933. Check-in comment: Be better about how we define the creation of scripts for event handler attributes (specifically, how we interact with the JS spec). http://html5.org/tools/web-apps-tracker?from=5932&to=5933
(In reply to comment #2) > > Based on my reading the spec, it looks like we actually need to do a little > more than was proposed in comment 0, so please do check to make sure I didn't > screw anything up. > Step 4 should (its also wrong in ES5 15.3.2.1) be: <p>If <var title="">body</var> is not parsable as <i>FunctionBody</i> or if parsing detects an early error then abort these steps.</p> <p class="note"><i>FunctionBody</i> is defined in ECMAScript edition 5 section 13 Function Definition. "Early error" is defined in ECMAScript edition 5 section 16 Errors.<a href="#refsECMA262">[ECMA262]</a></p> Step 6 is unnecessary, as the specific strict mode restrictions in ES5 section 13.1 relate to the naming of the formal parameters of a function and the fixed set of names you provide in step 7 don't violate any of those restrictions. > It would be really nice if the JS spec could just give us hooks that we could > use so that we didn't have to worry about updating HTML every time the JS spec > revs. I agree with the goal, but there are some missing ES semantics we still need to address. In this particular case, I think we may be able to describe the desired semantics as a source-to-source transformation of the ES code and avoid having to explicitly reach into the ES5 internal spec. mechanisms.
Will fix the issues you raise, thanks. > > It would be really nice if the JS spec could just give us hooks that we could > > use so that we didn't have to worry about updating HTML every time the JS spec > > revs. > > I agree with the goal, but there are some missing ES semantics we still need to > address. In this particular case, I think we may be able to describe the > desired semantics as a source-to-source transformation of the ES code and avoid > having to explicitly reach into the ES5 internal spec. mechanisms. I really would like to avoid defining a source transformation because that often ends up having far more complicated side-effects than one would expect. What I mean by a "hook" is just that the ES spec could say "When a specification needs to create a foo using a list of arguments bar and a body baz, it must follow these steps, which return a quux and a gizmo: 1. do something, 2. do something else, 3. do yet more things". Then instead of having to reference specific sections or talk about specific grammar constructs, we can just say "and then create a foo as defined in the ES spec". There's a number of places where hooks like that would be useful.
(In reply to comment #5) > > I really would like to avoid defining a source transformation because that > often ends up having far more complicated side-effects than one would expect. > I actually think that in some of these cases source transformation is going to be more reliable and durable then hooking into the spec. language. Basically, the source language and its semantics are managed to ensure a very high degree of backwards compatibility while the internal specification language changes from edition to edition as necessary to define new constructs that are introduced into the language. The internal spec. language historically has not been design with long term stability as a one of its goals. Here is a first cut at defining event handlers as such a transformation: 1 Set the corresponding event handler to null. 2 Set up a script execution environment for JavaScript. 3 Let /body/ be the event handler context attribute's new value. 4 If /body/ is can not be parsed as /FunctionBody/ then abort these steps. 5 Let /F/ and /E/ be the text of any two ECMAScript identifiers that do not occur in /body/. 6 If the element has a form owner let /prefix/ be the string "(function (__F__, __E__) {with (__F__) with (__E__) {" otherwise let /prefix/ be the string "(function (__E__) {with (__E__) {" . 7 Replace all occurrences of "__F__" and "__E__" within /prefix/ with the values of /F/ and /E/ respectively 8 If the attribute is the onerror attribute of the Window object let /funcHeader/ be the string "return function (event, source, fileno) {" otherwise let /funcHeader/ be the string "return function (event) {". 9 Let /handlerMaker/ be a string consisting of the in order concatenation of /prefix/, /funcHeader/, /body/, and "}}})". 10 Create an ECMAScript language script from the node on which the attribute is being set using the string value of /handlerMaker/ as the script source. 11 Let /result/ be the value of the initial code entry-point of this script. If an exception was raised, let /result/ be void instead. 12 If /result/ is void, abort these steps. 13 If the element has a form owner call the function that is the the value of /result/ passing the element's form owner , and the element's object as arguments; 14 otherwise call the function that is the the value of /result/ passing the element's object as the sole argument. 15 Set the corresponding event handler to the value returned by the function call in step 13 or 14. Note: The script text for a /handerMaker/ for an element with a formowner and which is not a onerror attribute of a Window object: // If "__F__" or "__S__" occur in <<body>> they are replaced with identifiers that do no occur. (function (__F__, __S__) { with (__F__) with (__S__) { return function (event) { <<body>> } } }) The result value computed in step 11 is the outer function above. Step 13/14 calls that function to create a closure of the inner function closed over the optional form owner and the element's object. That function is the event handler value. ------------------------ I think the above formulation is clearer and is going to be much more durable. I see minimal risk of unintended side effects and it will be easier to analyze for such than re-purposed ES5 specification pseudo-code. > What I mean by a "hook" is just that the ES spec could say "When a > specification needs to create a foo using a list of arguments bar and a body > baz, it must follow these steps, which return a quux and a gizmo: 1. do > something, 2. do something else, 3. do yet more things". Then instead of having > to reference specific sections or talk about specific grammar constructs, we > can just say "and then create a foo as defined in the ES spec". > > There's a number of places where hooks like that would be useful. The idea of stable interface points between specifications is an interesting one. Where possible, I still think an "as if" transformation to the source language is preferable but for situations where that isn't expressive enough then a stable inter-specification interface my be a good way to make durable connections between specs. However, we should probably continue this discussion somewhere other than in this bug.
(In reply to comment #6) > The idea of stable interface points between specifications is an interesting > one. Where possible, I still think an "as if" transformation to the source > language is preferable but for situations where that isn't expressive enough > then a stable inter-specification interface my be a good way to make durable > connections between specs. IMO, inter-specification interfaces are much better than string concatenation, as they tend to be much easier to check for unintended side-effects. We've been moving toward this way of specifiying, at least in DOM specs. See, for example, the definition of the FormData constructor [1], which defers to the "constructing the form data set" algorithm in HTML, which should be the most stable approach. [1] http://dev.w3.org/2006/webapi/XMLHttpRequest-2/#dom-formdata-form
EDITOR'S RESPONSE: This is an Editor's Response to your comment. If you are satisfied with this response, please change the state of this bug to CLOSED. If you have additional information and would like the editor to reconsider, please reopen this bug. If you would like to escalate the issue to the full HTML Working Group, please add the TrackerRequest keyword to this bug, and suggest title and text for the tracker issue; or you may create a tracker issue yourself, if you are able to do so. For more details, see this document: http://dev.w3.org/html5/decision-policy/decision-policy.html Status: Partially Accepted Change Description: see diff given below Rationale: see comment 4
Checked in as WHATWG revision r6099. Check-in comment: Fix event handler attribute interaction with ES http://html5.org/tools/web-apps-tracker?from=6098&to=6099
mass-moved component to LC1