If you think a bug might affect users in the 57 release, please set the correct tracking and status flags for Release Management.

RegExp objects do not implement call or apply

RESOLVED WONTFIX

Status

()

Core
JavaScript Engine
P4
enhancement
RESOLVED WONTFIX
12 years ago
9 years ago

People

(Reporter: Erik Arvidsson, Assigned: brendan)

Tracking

Trunk
Points:
---
Bug Flags:
in-testsuite ?

Firefox Tracking Flags

(Not tracked)

Details

(Reporter)

Description

12 years ago
In Spidermonkey one can use a regular expression object like a function:

var re = /f./;
re('foo'); // returnd 'fo'

Also 'typeof re' returns 'function' (all other browsers return 'object'). If this kind of behavior is supposed to be supported 'call' and 'apply' should really work on regexp objects.

Comment 1

12 years ago
typeof returning "function" is just a result of having a [[Call]] property and doesn't mean it is an instance of Function. As far as I can tell we implement ECMA 3 properly here.

What you are asking for is an enhancement to add more Function type properties to RegExp. What is the benefit considering the other browsers don't consider a regular expression instance to be calleable?
Severity: normal → enhancement
OS: Linux → All
Hardware: PC → All
(Reporter)

Comment 2

12 years ago
Agreed. Shouldn't we be able to use call and apply from scripts then?

re.call -> undefined
re.apply -> undefined

The problem is with code like this:

if (typeof obj == 'function') {
   obj.call(...);
}
(Assignee)

Comment 3

12 years ago
This seems more like a bug against ECMA-262.  It may be useful to prototype some possible fixes here, but really, we (or at least I) need to interact with ECMA TG1 about the lack of a universal apply (call is an optimization) operator.  Such an operator, if done right, should be a combinator with operator new, so that one can construct using an array of arguments.

/be
Assignee: general → brendan
(Assignee)

Comment 4

12 years ago
(In reply to comment #2)
> Agreed.

With which comment?

> Shouldn't we be able to use call and apply from scripts then?
> 
> re.call -> undefined
> re.apply -> undefined
> 
> The problem is with code like this:
> 
> if (typeof obj == 'function') {
>    obj.call(...);
> }

ECMA-262 does *not* guarantee that you can do that.

/be
Status: NEW → ASSIGNED
Priority: -- → P4
Target Milestone: --- → mozilla1.9beta

Comment 5

12 years ago
(In reply to comment #2)
 if (obj instanceof Function) {
    obj.call(...);
 }
(Assignee)

Comment 6

12 years ago
(In reply to comment #1)
> typeof returning "function" is just a result of having a [[Call]] property and
> doesn't mean it is an instance of Function. As far as I can tell we implement
> ECMA 3 properly here.

Except that ECMA does not specify [[Call]] as a shorthand for exec for RegExp objects.  Except that extensions to the spec are allowed.

typeof is a mess, we'll try to clean it up for Ed. 4.

/be

Comment 7

12 years ago
I'll add a test when this is resolved.
Flags: testcase?

Comment 8

12 years ago
15.3.4.4 Function.prototype.call(thisArg [ , arg1 [ , arg2, ... ] ] ) 
| The call method takes one or more arguments, thisArg and (optionally)
| arg1, arg2 etc, and performs a function call using the [[Call]] property
| of the object. If the object does not have a [[Call]] property,
| a TypeError exception is thrown. The called function is passed
| arg1, arg2, etc. as the arguments.

The spec does not require RegExp instances to have call() method.
However, Function.prototype.call() should accept any object
that has [[Call]] property as |this| value, shouldn't it?

var rx = /x/;
rx.call = Function.prototype.call;
rx.call(null, "x"); // currently, throws an exception
(Assignee)

Comment 9

12 years ago
(In reply to comment #8)
> 15.3.4.4 Function.prototype.call(thisArg [ , arg1 [ , arg2, ... ] ] ) 
> | The call method takes one or more arguments, thisArg and (optionally)
> | arg1, arg2 etc, and performs a function call using the [[Call]] property
> | of the object. If the object does not have a [[Call]] property,
> | a TypeError exception is thrown. The called function is passed
> | arg1, arg2, etc. as the arguments.
> 
> The spec does not require RegExp instances to have call() method.

Right, see comment 6 and section 16 of the spec.  Extensions are allowed, but adding [[Call]] to other objects does not imply Function.prototype.apply/call work on those other objects, in the spec.  But I agree this is desirable.

> However, Function.prototype.call() should accept any object
> that has [[Call]] property as |this| value, shouldn't it?
> 
> var rx = /x/;
> rx.call = Function.prototype.call;
> rx.call(null, "x"); // currently, throws an exception

Yeah, this could work.  Even better would be Function.call(rx, "x") in the same way we've made generic static method counterparts to Array and String prototype methods.  Better yet would be an apply operator.  This is the bug for all such [[Call]] goodness to be recorded, fed into ECMA TG1, and fixed.

/be

Comment 10

10 years ago
Just so I don't have to open a new bug about this...

Why does typeof /some regexp/ == "function", but /some regexp/ instanceof Function == false? From a user's perspective, if typeof x == "function", then it should act as though it were an instance of Function. I know Bob cleared up the implementation aspect of this in the second comment, but this is the first object I've discovered across browsers that hasn't acted as such.

(By the way, isn't /rgx/("test") acting the same as /rgx/.exec("test") nonstandard behavior?)
(In reply to comment #10)
> Why does typeof /some regexp/ == "function", but /some regexp/ instanceof
> Function == false?

It's two separate mechanisms.  For typeof == "function" the object merely has to implement [[Call]].  Nothing says that RegExp doesn't implement it (and the spec explicitly allows extensions), except cross-engine compatibility and user expectations.  For instanceof, |O instanceof F| just walks up O's prototype chain and returns true if it finds an object P such that |P === F.prototype|.  For a regular expression, the chain is RegExp.prototype->Object.prototype->null, so |/f/ instanceof Function| returns false.


> From a user's perspective, if typeof x == "function", then
> it should act as though it were an instance of Function.

The spec's type-determination mechanisms may be specified, but that doesn't mean they're specified in the most user-intuitive way.


> (By the way, isn't /rgx/("test") acting the same as /rgx/.exec("test")
> nonstandard behavior?)

Again, it's an extension allowed by section 16 of ECMA-262 3rd ed.  SpiderMonkey and other JS engines have lots of extensions like these, some of which are moderately cross-browser (__proto__ for one) and some of which are not (like the function-call shorthand for exec).
(Assignee)

Comment 12

10 years ago
(In reply to comment #11)
> (In reply to comment #10)
> > From a user's perspective, if typeof x == "function", then
> > it should act as though it were an instance of Function.
> 
> The spec's type-determination mechanisms may be specified, but that doesn't
> mean they're specified in the most user-intuitive way.

In this case, though, what Scott wrote: "instance of Function", directly translates to instanceof, not to typeof.

The idea with typeof x == "function" was to enable "can I call x?" tests. Better in hindsight to add a callable(x) predicate, but that ship sailed long ago.

/be
(Assignee)

Comment 13

10 years ago
Not sure they should: re.call(thisre, arg1, ... argN) where thisre is another regexp object (and re could be RegExp.prototype) should just be thisre(arg1, ... argN). For apply, the proposed JS2 / ES4 "splat" operator is universal: re.apply(thisre, argsArray) becomes thisre(...argsArray).

This goes for all callable objects; nothing special about regexps. However it's not clear making regexp callable as a short-hand for exec is worth the trouble. We have backed off on typeof /hi/ == "function". RegExp and Function are related only to Object as a supertype.

/be
(Assignee)

Updated

10 years ago
Target Milestone: mozilla1.9alpha8 → ---
(Assignee)

Comment 14

9 years ago
Sentiment even before ES4 fell was negative on callable regexps being standardized. As David-Sarah Hopwood has pointed out, ES3 does not allow regexps to implement [[Call]] -- its definitions for internal methods and native objects is exhaustive. So this is WONTFIX (or WFM, but I'll stick with WONTFIX).

/be
Status: ASSIGNED → RESOLVED
Last Resolved: 9 years ago
Resolution: --- → WONTFIX
You need to log in before you can comment on or make changes to this bug.