Opt-out schemes for ECMAScript 3.1

William Edney bedney at technicalpursuit.com
Tue Nov 18 20:34:40 PST 2008


All -

In reviewing the proposed ECMAScript 3.1 specification, we have  
identified what we feel is a grave situation for the ECMAScript  
community and the Web at large: the omission of an explicit opt-in  
mechanism for ECMAScript 3.1.

In the nine years since ECMAScript 3.0 was finalized, the amount of  
code written against the ES 3.0 standard has grown by leaps and  
bounds. There are literally millions of lines of code written against  
this standard.

In the course of writing so much script, developers of both frameworks  
and individual applications invariably chose property names, global  
variable names, etc. that are now colliding with those chosen for the  
ES 3.1 specification.

These decisions were made by well-intentioned developers who were all  
under the impression, from looking at drafts of the JavaScript 2.0 /  
ES edition 4 specifications all the way back to 1999, that the next  
version of ECMAScript would have some sort of 'explicit opt-in'  
versioning mechanism.

Since the momentous August 2008 decision to split the upcoming work  
into ES 3.1 and ES Harmony initiatives, work has progressed on the ES  
3.1 specification, but with no mention of the ability to explicitly  
opt-in or opt-out of this version of the language.

In his August 2008 posting announcing the split, Brendan had this to  
say:

"... Both the appropriateness of new syntax, and the need to make  
incompatible (with ES3 extensions) semantic changes, motivate opt-in  
versioning of harmonized successor edition. ..."

so we know that 'explicit opt-in' is coming for Harmony. That's great,  
but what about ES 3.1? There are property additions, global namespace  
additions, etc. that make it incompatible with same-named developer  
extensions.

We've worked directly over the years with numerous small web firms  
which have extensive HTML/CSS skill but limited JS expertise. It is  
important for the authors of this specification to understand that  
there are millions of lines of JavaScript that are in *production use*  
in an environment where:

- There is no expertise to change / upgrade the code.

- There may be an available HTML developer who can tweak an HTML tag  
to specify a version number to 'make that script work again'.

- Upgrades to the browser are dependent on scripts continuing to work  
with little or no maintenance. If incompatible changes to JavaScript  
are made 'silently', and scripts stop working, browsers stop getting  
upgraded. This is *definitely* not in the best interest of the Web as  
a whole.

These issues have been debated elsewhere and a variety of counter- 
arguments have been put forth. However, in our view:

1. It is insufficient to claim that 'these changes are minor'. This is  
irrelevant since they overlay existing semantics, no matter how  
'minor' they are. They have the potential to break the Web, and that's  
not 'minor'. For example, when 'foreach' is defined on Array.prototype  
by a JS library, Mozilla engines implementing JavaScript 1.6 hang.

2. It is insufficient to claim that 'object testing can be performed  
to work around new features that are unwanted'. Again, this is not  
relevant. Scripts in the field authored years ago by a long-gone  
developer cannot be magically upgraded via time machine to do object  
testing for features that are now being standardized or implemented by  
a browser vendor or specification committee.

3. It is insufficient to claim that 'if you define these properties,  
they'll just overlay ones that we're defining for ES 3.1'. Many of  
these same-named properties have different semantics that vary from  
library to library. What about new ES 3.1 engine code that is calling  
this new functionality and is now dealing with a JS-defined property  
that behaves very differently? This is related to point #1. Many  
libraries out there add a 'bind' property to Function.prototype, and  
at least the ones we know of don't take a varargs list for their  
version of 'bind'.

4. It's been said that 'since no one really complained when Brendan  
added new functionality for JavaScript 1.6 - 1.8, no one must really  
care all that much'. This is not a good rationale at all. Some of us  
have already had to dodge these new additions in the Mozilla engine  
and we personally know of one case where we were using a third party  
library that defined an incompatible 'foreach' method on the Array  
object that had to be renamed to avoid collision. Additionally, what  
we're talking about now is wholesale additions and changes to a multi- 
vendor standard, not a few additions made by one vendor - and one who  
was responsible enough (at least for JavaScript 1.7/1.8) to *require*  
a version be specified in the <script> tag.

5. It is insufficient to claim that 'well, we've surveyed a lot of  
code out there and so far haven't found any conflicts with what we're  
proposing'. There's a lot of JavaScript that doesn't exist on the  
Internet. It exists in non-public web sites by the truckload and is  
not visible to us. This community is not omniscient around how  
JavaScript is being used 'out in the wild'.

In particular, we know of a large JavaScript framework in continuous  
use with over 300K lines of JavaScript. Here is a survey we made of  
that the specification with regards to that library (or general  
comments with regards to language usage):

-------

isCallable operator
    New operator checks for a call method and will return inconsistent  
results across browsers (RegExp in some implementations will return  
true but not in others since RegExp.prototype.call isn't part of the  
standard).
    Conflicting framework implementation accepts any object and  
returns true if the object is a) a Function instance, b) not marked as  
a DNU.

10.0 Executable Code and Execution Contexts:
    What is the characterization of code which is added to a program  
dynamically by adding a <script>inline_code_here</script> tag? Is that  
considered "eval code" or are the separate contents treated as global,  
function, and eval code respectively?
    As a related question, what is the strict lexical context of such  
code? (currently it would appear to be the global context which seems  
appropriate)

10.1.1 Strict Mode Code
    Is the intent here that different <script> nodes would be able to  
define different settings for strict vs. unrestricted?

11.1.5
    In the syntax discussion on PropertyAssignment the verbs "get" and  
"set" are used. Are these going to be treated like keywords? Reserved  
words? Something else? They will likely conflict heavily with  
frameworks which already use get/set "bean-like" APIs for  
encapsulating property access.
    As an aside, getters can take parameters too, at least in the  
environments I've worked with in the past, so not supporting a  
parameter list for getters might restrict their value in those more  
complex cases.

12.1 Block Scope
    Please clarify, it appears this will continue to work for existing  
code due to how lexical contexts are mapped. Is that correct? In other  
words, will the current functionally-scoped vars etc be visible to the  
block? Presumably yes.

15.2.3.5 Object.create
    Conflicts with frameworks which have already implemented this  
method as an alternative constructor to using raw "new X" calls for  
object creation. In particular, create is overridden by subtypes and  
performs differing operations depending on the type.

15.2.3.14 Object.keys
    Conflicts with frameworks which have already implemented keys  
properties, particularly for custom Hash object types.

15.3.4.5 Function.prototype.bind
    Almost certain to conflict with all major AJAX frrameworks, since  
they almost all implement a bind method whose signature and semantics  
are somewhat different.

15.3.5.4 Function.prototype.name
    This will conflict with at least one framework which currently  
sets a name property on Function instances to store their name, and  
which assigns 'anonymous' as the name when not found.

15.4.3.2 Array.isArray
    Admittedly this is a "type method" rather than an instance method,  
but the isArray function has historically returned true if the  
argument was a Java array (due to LiveConnect) so this would change  
the semantics depending on the context.

Date.now
    Collision

*.prototype.toJSON
    Collision

15.5.4.20 String.prototype.trim
    Collision

Additional Array iterators.

15.4.4.15 Array.prototype.lastIndexOf
15.4.4.14 Array.prototype.indexOf
    Will conflict with frameworks already implementing this function.  
The semantics do appear to be consistent with those of the  
implementations I'm aware of though, so this probably won't cause  
failures.

15.12 JSON
    Conflicts with frameworks which have already implemented this  
object.

Annex D
    Changes to RegExp.prototype will cause isRegExp() in at least one  
framework to break since it relies on the fact that RegExp objects  
currently return Object as a way of distinguishing them from Function  
instances which also implement both apply and call in certain browsers  
(thanks to prior releases of new functionality).

-------

If future versions continue to define properties with no explicit opt- 
in / opt-out mechanisms in place, the consequences get more serious  
with each passing year as JavaScript's popularity curve is increasing,  
not decreasing. There may be an ES 3.2... who knows?

For that reason we strongly urge the committee to consider using the  
same opt-in approach for ES 3.1 that will be required for ES Harmony.  
Failure to require an opt-in approach with the standard _will_ break  
existing scripts.

Should that be unacceptable for some reason we would urge adoption of  
an opt-out approach. While this approach won't keep existing scripts  
from breaking it would at least provide those without access to ES  
expertise to make minor changes to their script tags to restore their  
applications to a functional state.

Our proposed opt-out approach would take the following form:

An addendum to the specification whereby ES engine vendors agree to  
use a host-language mechanism that will cause their engines to shift  
into 'ES 3.0 only' mode, ignoring all of the new properties and  
features of ES 3.1.

For HTML/SVG hosted applications of ECMAScript, this 'ES 3.0 *only*  
mode' mechanism could take the form of a 'version' identifier placed  
behind the MIME type in the <script> tag, as implemented by Mozilla  
for JavaScript 1.7 & 1.8:

Here is an example of what we would propose:

<script type="application/javascript;version=1.5">...</script>

A second form (for those in the pure ECMAScript world):

<script type="application/ecmascript;version=3.0">...</script>

Note that this has the distinct advantage of being able to be used by  
markup developers with no ECMAScript development experience who can  
'tweak their script tag to make their scripts run again'.

For those of us kicking around the JS world for a while, this smacks a  
bit of the old, de-facto, but never standardized:

<script language="JavaScript1.5">...</script>

Unfortunately, the 'strict backwards compatibility' feature of this  
version identifier doesn't seem to be honored or is inconsistently  
applied within various browsers:

1. In Mozilla 1.9 / Firefox 3.0.4, even though the <script  
language="JavaScript1.5"> syntax is used, 'Array.prototype.indexOf ===  
undefined' returns false. Array's 'indexOf' was introduced in  
JavaScript 1.6.

2. Ditto for Safari 3.1.2.

3. IE7 doesn't respond to this directive. It only works with version- 
specific values up to "JavaScript1.3". This is very confusing as  
JScript 5.5 and above is supposed to be JavaScript 1.5 compliant  
(although we all know there's still work to be done here).

Additionally, the 'language' attribute was never really standardized  
and so is probably a poor choice for this capability. The Mozilla crew  
seems comfortable with using a 'version=' after the MIME type, so  
that's fine. The point is strict adherence to the defined version,  
unlike the loose interpretation we see with the 'language' attribute.  
As with the older 'language="..."' attribute, if the value of the  
'type' attribute is just 'application/javascript' (or 'application/ 
ecmascript'), then the latest version of JavaScript will be used.

Therefore, we would like these statements to be confirmed, discussed,  
debated by the committee:

1. ES Harmony will have an explicit opt-in mechanism, either through  
the 'language' it is being hosted in (HTML, SVG, etc.) or via a  
statement in the language itself.

2. The latest version of ECMAScript will be available in the current  
execution environment if the following script tag syntax is used:

	<script type="application/javascript">....</script>

3. When a version is explicitly given the engine will respect the  
boundaries of that version, restricting the language to only those  
features/properties standardized in the given version. Version numbers  
and their related standards are:

	JavaScript 1.5:

	<script type="application/javascript;version=1.5">...</script>

	OR

	<script type="application/ecmascript;version=3.0">...</script>


	JavaScript 1.6 (currently Mozilla-only):

	<script type="application/javascript;version=1.6">...</script>


	JavaScript 1.7 (currently Mozilla-only):

	<script type="application/javascript;version=1.7">...</script>


	JavaScript 1.8 (currently Mozilla-only):

	<script type="application/javascript;version=1.8">...</script>


	JavaScript 1.9:

	<script type="application/javascript;version=1.9">...</script>

	OR

	<script type="application/ecmascript;version=3.1">...</script>


So, for those of you on the committee, 'ES 3.0 *only* mode' means  
exclusion of all of that "red stuff" we see when we download versions  
of the 3.1 specification :-). No additions to any objects, no new  
global functions, no 'cautious' mode, no new semantics of any kind. It  
is the language as it was frozen in November 1999.

The Web is no longer in its nascent phase. JavaScript is the COBOL of  
the Web (with all due apologies to Brendan for *that* statement ;-) ).  
Real, live production systems with millions of lines of ES edition 3.0  
compliant JavaScript are in use everywhere, especially in places where  
you can't see them. ES edition 3.0 is it for the foreseeable future  
for many of these folks, no matter how 'flawed' it may be.

Thanks for listening.

- Bill Edney & Scott Shattuck



More information about the Es-discuss mailing list