Array.prototype.values is not web compat (even with unscopables)

# Erik Arvidsson (9 years ago)

We learnt this the hard way.

There are pages [1] out there that check if "values" in object and now that ends up being true for Array instances.

[1] Microsoft Outlook Calendar web app (part of Exchange Outlook Web Access)

# Jeff Walden (9 years ago)

On 10/17/2014 01:53 PM, Erik Arvidsson wrote:

[1] Microsoft Outlook Calendar web app (part of Exchange Outlook Web Access)

Microsoft could ship a fix in a point release, right? They surely already provide security patches that admins must install anyway, if they want to keep their users (and their data) safe. If the fix is small, is there any reason why it couldn't be part of such a patch?

# Erik Arvidsson (9 years ago)

Here is some more info.

windowssystemspecialist.blogspot.com/2014/10/fixing-blank-calendar-with-chrome-38.html

(This blog post would have been useful when we tracked down what caused OWA to fail.)

# Fabrício Matté (9 years ago)

Here is a related Twitter discussion: twitter.com/domenic/status/523202298466418688

To highlight the main points:

Domenic Denicola claims that extending built-in prototypes is not web-compatible.

Indeed, if we consider all possible corner-cases and ignore best practices (which is often the case for the Web), adding new prototype properties or global identifiers can break existing code.

However, it is basic knowledge that 3rd-party code and future ECMAScript versions can and will extend the built-in prototypes, and host environments can inject new global identifiers. If developers do not keep this in mind, they are writing what I call "code waiting to be broken".

Developers already have the means to write future-proof code. For instance, I believe Outlook's code could be made future-proof by simply using .hasOwnProperty() instead of the in operator.

IMO, developers should be more mindful about future-proofness, and new developers should be educated in this vein. This must happen in order for ECMAScript to keep evolving without revolving around ugly/unnecessary syntax such as pragmas and core library imports. "Code waiting to be broken" should be of no concern to TC39.

But in reality, many developers simply won't follow the best practices, and as Domenic said, browser vendors don't want to ship changes that break existing code.

Looks like we have reached a stalemate, and I believe this is something that should be addressed before ES6 is officially publicized.

O.T.: although I've been accompanying ES Discuss for a good while, this is my first post here and I'd like to thank all TC39 members and contributors for the awesome work so far.

# Benjamin Gruenbaum (9 years ago)

Just as a note - I think that if we learned anything in this regard it's that standards should guide and not dictate.

It׳s rather impossible to break reasonable user level code and I don't think it's reasonable to expect developers to be fortune tellers :)

(I like the idea though)

# Fabrício Matté (9 years ago)

@Benjamin

Not sure if I understand what you mean.

If standards don't "dictate", then how are we supposed to expect interoperable implementations?

By "impossible" I suspect you mean something that browser vendors should never do. I understand back-compatibility with the Web is a must for browser vendors, and that is good for us developers, too. After all, that is what "One JS" is all about.

However, it does not take a fortune teller to take minimal precautions, such as not walking up an (extendable) prototype chain when checking for property existence in objects. I believe future ECMAScript versions have the right to extend built-in prototypes, and developers must be aware of that. This, however, may not be "web-compatible", as it breaks code that contains the aforementioned code smell.

Can the TC39 and browser vendors solve this in a reasonable manner?

# Andy Wingo (9 years ago)

On Sun 19 Oct 2014 02:46, Fabrício Matté <ultcombo at gmail.com> writes:

But in reality, many developers simply won't follow the best practices, and as Domenic said, browser vendors don't want to ship changes that break existing code.

Looks like we have reached a stalemate, and I believe this is something that should be addressed before ES6 is officially publicized.

There is no way it can be addressed in general -- we want to be able to define new names on prototypes, but this desire is always limited by "web reality". All we can do is instrument, measure, guess, try, and, in sad cases like this one, admit defeat if some names just don't work.

Andy

# Katelyn Gadd (9 years ago)

Has the C# approach to namespace extension been considered at all? With extension methods (one of the foundational primitives used to implement their LINQ querying system) they address this by making extension namespaces 'opt-in' - extension methods are only 'available' on an object if you've imported the namespace (or module, if you like) that contains the extension methods. And extension methods only live on static classes, so they don't get pulled in by accident if you follow some basic guidelines.

The other thing they do here is (IIRC) an extension method never obscures a member that is already on the object, and they don't show up in reflection - they are not members of the object(s) they extend, they're just callable on that object thanks to some compiler machinery.

Hypothetically (I haven't given this a ton of thought), how this might apply to JS:

The new API extensions for prototypes like Array and String and so on are opt-in, through importing the module that contains them, or perhaps explicitly importing the new API python-style: from es6 import newAPIs This is also something you could polyfill given a working module loader implementation. I guess one downside is this introduces another 'use strict' style mode, which is particularly gross.

If that's not enough, you find a way to introduce the resolution behavior I described from C#, where the properties aren't enumerable on the objects they're attached to (so no 'in', etc), they can be overwritten, and they never shadow existing values. Sadly there isn't a direct analogue here, since C# implements this behavior at compile time - the 'method invocations' get mapped to static method calls by the compiler. A downside to this would be that it makes it impossible to tell whether the builtins are available to call - I don't know how you'd fix that. Maybe expose the information in places existing code doesn't look, like make getOwnPropertyDescriptor still return the property, just with the relevant non-visibility properties set.

# Brendan Eich (9 years ago)

Katelyn Gadd wrote:

Has the C# approach to namespace extension been considered at all?

Yes. ES4 has namespaces, after Common Lisp symbol packages.

Scoped object extensions were proposed four years ago for ES6, but foundered on the same thing that killed ES4 namespaces: adding a second lookup parameter besides property name. See esdiscuss.org/topic/may-24-26-rough-meeting-notes (search for "Scoped Object Extensions:" after picking "View Original" from the in-page toolbar), and then see esdiscuss.org/topic/scoped-binding-of-a-method-to-an-object#content-48 from last year, where Andreas Rossberg wrote:

"My take-away was that scoped extension methods are only bearable in a language with a static, nominal class system (like C#), where the additional lookup dimension can be resolved at compile time."

# Mike Taylor (9 years ago)

On 10/17/14, 16:13, Jeff Walden wrote:

On 10/17/2014 01:53 PM, Erik Arvidsson wrote:

[1] Microsoft Outlook Calendar web app (part of Exchange Outlook Web Access)

Microsoft could ship a fix in a point release, right? They surely already provide security patches that admins must install anyway, if they want to keep their users (and their data) safe. If the fix is small, is there any reason why it couldn't be part of such a patch?

I filed webcompat/web-bugs#388 to track Microsoft adding the forOwnProperty fix. Microsoft's @TheWebJustWorks team has been really helpful in the past for these kinds of issues.