Callable RegExp vs. typeof (was: Re: Draft of Function.prototype.bind.)

# Brendan Eich (16 years ago)

On Nov 4, 2008, at 10:43 AM, David-Sarah Hopwood wrote:

The bug that Brendan and I were referring to was 61911: bugzilla.mozilla.org/show_bug.cgi?id=61911

For reference so new readers don't have to look far back in the old
thread.

On FF3.0.3, a bit of testing reveals that RegExp instances are indeed callable as functions, which presumably means they have an internal
[[Call]] property. And they are clearly native objects, not host objects.
However, unlike Rhino or WebKit, of FF3.0.3 at least, typeof of a RegExp
does return "object". I don't see any way to rationalize this as conforming to
the spec.

I agree; that's the same reasoning I was using.

Agreed, still.

Note that in the comments of bug 61911, Brendan used the argument that regexp objects were proposed to be callable in ES4, but that is
presumably back up for discussion in Harmony. I would recommend against it:

Still agreed ;-).

callable regexps were a SpiderMonkey extension never adopted by any non-Mozilla JavaScript implementation AFAIK, and they introduce an irregularity in the language.

Not so. See bugs.webkit.org/show_bug.cgi?id=28117 in
particular bugs.webkit.org/show_bug.cgi?id=28117#c12 (quoting
Luke Smith's words here):

"I found that /a/("abc") is implemented (inconsistently) in Firefox
3.0, Firefox 3.5, Safari 3.2.1, Safari 4, Opera 9.6.3, Opera 10 beta2,
Chrome 3 beta, and the WebKit nightlies. It is not implemented in IE6,
IE7, IE8, or Chrome 2."

My comment at bugs.webkit.org/show_bug.cgi?id=28117#c21 opines
that we may find it hard to remove callability, but it's even harder
to make typeof /a/ return "function".

This is an issue still.

# Juriy Zaytsev (16 years ago)

On Aug 13, 2009, at 1:07 PM, Brendan Eich wrote:

On Nov 4, 2008, at 10:43 AM, David-Sarah Hopwood wrote:

[...]

callable regexps were a SpiderMonkey extension never adopted by any non- Mozilla JavaScript implementation AFAIK, and they introduce an irregularity
in the language.

Not so. See bugs.webkit.org/show_bug.cgi?id=28117 in
particular bugs.webkit.org/show_bug.cgi?id=28117#c12
(quoting Luke Smith's words here):

"I found that /a/("abc") is implemented (inconsistently) in Firefox
3.0, Firefox 3.5, Safari 3.2.1, Safari 4, Opera 9.6.3, Opera 10
beta2, Chrome 3 beta, and the WebKit nightlies. It is not
implemented in IE6, IE7, IE8, or Chrome 2."

My comment at bugs.webkit.org/show_bug.cgi?id=28117#c21
opines that we may find it hard to remove callability, but it's even
harder to make typeof /a/ return "function".

This is an issue still.

There was a discussion of this ticket on Hacker News this morning and
we had this slight confusion on whether giving RegExp objects a
[[Call]] property is permitted by spec <news.ycombinator.com/item?id=760529

. I thought it was, since section 2 clearly states that

implementation can introduce its own extensions, but then someone made
a point about exact wording in that section and how it seems that
implementation can only add properties that spec doesn't mention (i.e.
additional ones) and not those that spec mentions (such as [[Call]])
but doesn't specify them on certain objects.

Could someone please clarify this?

Thank you.

# Brendan Eich (16 years ago)

On Aug 13, 2009, at 1:28 PM, Juriy Zaytsev wrote:

There was a discussion of this ticket on Hacker News this morning
and we had this slight confusion on whether giving RegExp objects a
[[Call]] property is permitted by spec <news.ycombinator.com/item?id=760529

. I thought it was, since section 2 clearly states that
implementation can introduce its own extensions, but then someone
made a point about exact wording in that section and how it seems
that implementation can only add properties that spec doesn't
mention (i.e. additional ones) and not those that spec mentions
(such as [[Call]]) but doesn't specify them on certain objects.

Could someone please clarify this?

Good point. I seem to recall that David-Sarah Hopwood made it already,
but I'm having trouble finding his message right now.

ES3 Chapter 16 says:

"An implementation may provide additional types, values, objects,
properties, and functions beyond those described in this
specification. This may cause constructs (such as looking up a
variable in the global scope) to have implementation-defined behaviour
instead of throwing an error (such as ReferenceError)."

As the ycombinator thread correspondent says, this is ambiguous: does
"may provide ... properties ... beyond those described by this
specification" mean [[Call]] on a native object specified without
[[Call]] by ES3 is ok? Or does it mean that only properties whose
identifiers are not defined at all for any object may be added? Or
should internal properties be excluded in any event?

The practical issue of typeof /a/ == "function" being misleading and
causing compatibility problems is paramount. Fixing that by ruling
that extending RegExp to have a [[Call]] internal property violates
ES3 is plausible in theory, but again in practice hard if enough
content depends on /a/(s).

# Juriy Zaytsev (16 years ago)

On Aug 13, 2009, at 4:44 PM, Brendan Eich wrote:

On Aug 13, 2009, at 1:28 PM, Juriy Zaytsev wrote:

There was a discussion of this ticket on Hacker News this morning
and we had this slight confusion on whether giving RegExp objects a
[[Call]] property is permitted by spec <news.ycombinator.com/item?id=760529

. I thought it was, since section 2 clearly states that
implementation can introduce its own extensions, but then someone
made a point about exact wording in that section and how it seems
that implementation can only add properties that spec doesn't
mention (i.e. additional ones) and not those that spec mentions
(such as [[Call]]) but doesn't specify them on certain objects.

Could someone please clarify this?

Good point. I seem to recall that David-Sarah Hopwood made it
already, but I'm having trouble finding his message right now.

ES3 Chapter 16 says:

"An implementation may provide additional types, values, objects,
properties, and functions beyond those described in this
specification. This may cause constructs (such as looking up a
variable in the global scope) to have implementation-defined
behaviour instead of throwing an error (such as ReferenceError)."

As the ycombinator thread correspondent says, this is ambiguous:
does "may provide ... properties ... beyond those described by this
specification" mean [[Call]] on a native object specified without
[[Call]] by ES3 is ok? Or does it mean that only properties whose
identifiers are not defined at all for any object may be added? Or
should internal properties be excluded in any event?

The practical issue of typeof /a/ == "function" being misleading and
causing compatibility problems is paramount. Fixing that by ruling
that extending RegExp to have a [[Call]] internal property violates
ES3 is plausible in theory, but again in practice hard if enough
content depends on /a/(s).

Thank you.

Whatever the consensus is, could the relevant section in ES5 be made
less ambiguous in to internal properties (perhaps with an
example of [[Call]] being allowed/disallowed on objects that don't
explicitly have it)?

# Allen Wirfs-Brock (16 years ago)

I think an important part of the "may add" allowance that is somewhat implicit that the only changes to the existing spec. that can be made to accommodate such extension is to cause error conditions to no longer be errors. If your extensions requires/implies other changes to the spec. then it isn't a valid extension but rather a change to the specification.

# Luke Smith (16 years ago)

On Aug 13, 2009, at 1:44 PM, Brendan Eich wrote:

ES3 Chapter 16 says:

"An implementation may provide additional types, values, objects,
properties, and functions beyond those described in this
specification. This may cause constructs (such as looking up a
variable in the global scope) to have implementation-defined
behaviour instead of throwing an error (such as ReferenceError)."

As the ycombinator thread correspondent says, this is ambiguous:
does "may provide ... properties ... beyond those described by this
specification" mean [[Call]] on a native object specified without
[[Call]] by ES3 is ok? Or does it mean that only properties whose
identifiers are not defined at all for any object may be added? Or
should internal properties be excluded in any event?

The practical issue of typeof /a/ == "function" being misleading and
causing compatibility problems is paramount. Fixing that by ruling
that extending RegExp to have a [[Call]] internal property violates
ES3 is plausible in theory, but again in practice hard if enough
content depends on /a/(s).

Certainly the story is muddied by supporting /a/(str) and reporting
typeof /a/ == 'function', but limiting the types of invocation
available vs those available to actual functions. No constructor
invocation, apply invocation, etc, and in fact
hostObj.myRegExpObj(str) 'this' is presumably always the RegExp
instance. Comprehending function invocation is confusing enough for
js developers.

Practically, I see no value in the extension, since it is just
shorthand for an existing API. And the fact that it has repercussions
elsewhere in the runtime is another point against it.

Luke

# Brendan Eich (16 years ago)

On Aug 13, 2009, at 2:07 PM, Luke Smith wrote:

Practically, I see no value in the extension, since it is just
shorthand for an existing API. And the fact that it has
repercussions elsewhere in the runtime is another point against it.

Luke

You don't need to convince me! But the extension is old, it has grown
a user base, and it's now hard to remove. If it spread via Mozilla
compatibility due to the way JS is user-agent-forked in Web content,
then I'm skeptical that this extension common among non-IE browsers
can be revoked in a coordinated and timely way.

I don't agree with Mark that fixing Array.prototype.indexOf in draft
ES5 to match all the real, shipping implementations is equivalent to
revising the typeof sub-spec per David-Sarah's proposal to match
callable-RegExp reality. That latter bit of reality is mixed: some
browsers (IE versions) do not implement RegExp [[Call]]. Others do,
but those others do not all report "function" from typeof /a/.

The messiness is not just a difference in degree of de-facto standards
agreement compared to indexOf. It also shows greater complexity in the
particulars, and in the ambiguous ES3 chapter 16 language.

So until just recently (today ;-), I was content to defer David- Sarah's fix while we (Mozilla) tried to find a way to remove
callability from our RegExp implementation. But your summary in that
webkit.org bug shed light (for me at least) on how far this bad old
extension has spread. It's not just us at Mozilla who would have to
remove callability, which seems hard enough by itself. Could all the
non-IE implementations revoke this extension?

Anyway, thanks for your comments in that webkit bug!