Closed
Bug 61911
Opened 24 years ago
Closed 18 years ago
typeof(/regExp/) should return "object", not "function"
Categories
(Core :: JavaScript Engine, defect, P3)
Core
JavaScript Engine
Tracking
()
VERIFIED
FIXED
People
(Reporter: afranke, Assigned: crowderbt)
References
()
Details
Attachments
(2 files, 2 obsolete files)
1.24 KB,
patch
|
brendan
:
review+
|
Details | Diff | Splinter Review |
888 bytes,
text/html
|
Details |
Found on http://www.oreilly.com/news/petition_1100.html :
> November 13th, 2000 8:29 AM
>
> Here's one I hadn't encountered before...
>
> Per ECMA 262, typeof should only return "function" if the object is native
> and implements a .call() method (printed page 47-48; PDF page 58-59). Regular
> expressions are a native object type and do not implement a call method.
> Therefore, this JavaScript URL:
>
> javascript:alert(typeof(/regExp/));< /a>
>
> should return "object", not "function". It does return "object" in Explorer
> and Opera, but returns "function" in Navigator (4.7 and 6pr3).
>
> Dave Brown
I am submitting this just so that it doesn't get lost. I don't know if it's a
valid bug, but I verified that mozilla mtrunk from 11/26 shows "function".
Comment 1•24 years ago
|
||
Andreas, thanks -
For convenience, here is the ECMA reference:
11.4.3 The typeof Operator
The production UnaryExpression:typeof UnaryExpression is evaluated as follows:
1. Evaluate UnaryExpression.
2. If Type(Result(1)) is not Reference, go to step 4.
3. If GetBase(Result(1)) is null, return "undefined".
4. Call GetValue(Result(1)).
5. Return a string determined by Type(Result(4)) according to the following table
Type Result
Undefined "undefined"
Null "object"
Boolean "boolean"
Number "number"
Object (native and doesn’t implement [[Call]]) "object"
Object (native and implements [[Call]]) "function"
Object (host) Implementation-dependent
Comment 2•24 years ago
|
||
I believe the bug is invalid. RegExp objects are "callable" in this sense:
js> var re = new RegExp('abc')
js>
js> re.exec("Learn your abc's")
abc
I don't think the ECMA spec is saying they have to have a method named "call"
in order to be considered of function type; they just have to be "callable".
cc'ing Brendan to make sure this bug is indeed invalid -
Comment 3•24 years ago
|
||
phil: re("learn your abc's") shows how a regexp is callable; that's short for a
call to re.exec passing the same arguments. This is all well-specified in ECMA
Edition 3. The "Dave" who complained in the oreilly.net petition misstates the
standard, which talks only about a [[Call]] internal method, not any named .call
method.
/be
Status: NEW → RESOLVED
Closed: 24 years ago
Resolution: --- → INVALID
Comment 4•24 years ago
|
||
Oops. ECMA-262 Edition 3 does *not* specify a [[Call]] internal method for
RegExp objects. Was that an oversight, or intentional?
/be
Status: RESOLVED → REOPENED
Resolution: INVALID → ---
Comment 5•24 years ago
|
||
waldemar, pls. advise and reassign to rogerl or mark INVALID. Thanks,
/be
Assignee: rogerl → waldemar
Status: REOPENED → NEW
Comment 6•24 years ago
|
||
It's a judgment call here. The standard doesn't say anything about an
implementation adding extra internal properties to an object, but I believe that
this is allowed, just as adding extra properties is allowed. As long as our
implementation has the [[call]] property on RegExp instances, their type should
be "function". Were the standard interpreted as disallowing defining [[call]]
on RegExp instances, then we'd have to remove [[call]] and change the type to
"object". That would break many scripts.
I'm going with the first interpretation and marking INVALID.
Status: NEW → RESOLVED
Closed: 24 years ago → 24 years ago
Resolution: --- → INVALID
Comment 9•18 years ago
|
||
*** Bug 353448 has been marked as a duplicate of this bug. ***
Comment 10•18 years ago
|
||
I believe the resolution of this bug was a mistake.
As Brendan realized in comment #4, ECMA-262 does not define [[Call]] for regexp instances.
"Extending the standard" in this manner is going against the spirit of the standard and is simply hurting developers and causes confusion. I have never seen /reg/(str) used anywhere and I don't see why it's useful. In a scenario where a function expects either an object or a function reference as argument, Gecko would misbehave here for no good reason.
Other browsers do this properly, including IE, Opera, Safari and Omniweb. I strongly believe this should be changed to conform more fully, since this extension is not just another method or property added to the object, it actually has consequences.
And finally, to quote the standard (not in an exact context, but it demonstrates the spirit of it): "Implementations that add additional capabilities to the set of built-in functions are encouraged to do so by adding new functions".
Comment 11•18 years ago
|
||
I think we should match other browsers. We should return "function" for Function objects, and little else. Comment 10's final paragraph citing standard verbiage is on target.
/be
Comment 12•18 years ago
|
||
BTW, alert should be a function object, although this is outside the scope of ECMA-262. IE should not make alert an alien "host object" lacking .apply, etc.
/be
Assignee | ||
Comment 13•18 years ago
|
||
I'm not seeing any other gripes in bugzilla about Bad Things that happened when we made typeof(/re/) == object, so a patch is coming right up. There is another bug in the database that looks, sounds and smells a lot like this one, though it is clearly a different breed of duck: bug 268945. Should this be fixed, also? Is the "alert" remark an action-item for us, or just an observation of IE wonkiness?
Status: VERIFIED → REOPENED
Resolution: INVALID → ---
Assignee | ||
Updated•18 years ago
|
Status: REOPENED → ASSIGNED
Comment 14•18 years ago
|
||
See bug 289933 comment 10. I found that bug via cvs annotate jsapi.c | less and searching for TypeOfValue and looking for recent changes to-do with the logic governing "function" type.
My alert comment was more about how even though I agree that typeof /a/ should not be function, my statement that typeof should return "function" pretty much only for Function objects should not be taken so narrowly that "host" functions such as alert are not function objects. That alert is not a function object in IE is a bug in IE, and any DOM level 0 standard should say so.
/be
Assignee | ||
Comment 15•18 years ago
|
||
So this isn't so much a bug (in the sense of an unintended or unexpected behavior in the code) as a matter of interpretation of the spec. I have not pored over the spec for many moons as have others, no doubt. We essentially implemented our own interpretation very deliberately, this patch reverses that interpretation in the case of regular expressions (only). Does this reversal cause problems elsewhere? Who relies on regexp being functions and not objects? Hopefully browser people or embedders who care will chime in. I personally think matching other browsers (if the spec doesn't provide a specific answer) is the Right Thing to Do.
Assignee: waldemar → crowder
Attachment #239320 -
Flags: review?(mrbkap)
Assignee | ||
Comment 16•18 years ago
|
||
(In reply to comment #14)
> See bug 289933 comment 10. I found that bug via cvs annotate jsapi.c | less
> and searching for TypeOfValue and looking for recent changes to-do with the
> logic governing "function" type.
Bleah. I suppose it would be easy to debate one way or another over which assumption is wrong. RegExp are more than functions (since they are, in fact, objects internally) and more than objects (since they have syntactic sugar that makes them behave like functions sometimes). It seems that the Right Thing to Do is get closer to the behavior supported by other browsers, until the spec is more explicit, and try to offer some viable workable for people who otherwise need to distinguish regexp from other object types. Perhaps an "isRegexp" function in the RegExp class?
Comment 17•18 years ago
|
||
Brian,
The reason typeof currently thinks a regexp instance is a function is because it has what the standard calls a [[Call]] member (not sure what you call it internally in your code). According to previous comments, someone mapped [[Call]] in regexp instances to the .exec method. This is totally non-standard and not useful in any way.
My recommendation is to remove that mapping and you will not need to do anything else (because no [[Call]] will be defined, typeof will realize it should return "object" and not "function", according to the standard).
Distinguishing between objects is already well taken care of by instanceof and .constructor, there's really no need to add a method (see obj instanceof RegExp and obj.constructor==RegExp).
Assignee | ||
Comment 18•18 years ago
|
||
Actually this fix doesn't concern itself with the [[Call]] member (check out the patch). We were actually going out of our way to special-case regexp to be reported as typeof == function. This patch stops doing that. instanceof is, as you suggest, a much better solution for the other bug, imho.
Updated•18 years ago
|
QA Contact: pschwartau → general
Assignee | ||
Updated•18 years ago
|
Attachment #239320 -
Flags: review?(mrbkap) → superreview?(brendan)
Comment 19•18 years ago
|
||
Comment on attachment 239320 [details] [diff] [review]
Removed regexp class from this special case
>- if ((ops == &js_ObjectOps)
>- ? (clasp->call
>- ? (clasp == &js_RegExpClass || clasp == &js_ScriptClass)
>- : clasp == &js_FunctionClass)
>+ if ((ops == &js_ObjectOps)
Trailing space added on this line.
>+ ? (clasp->call ? (clasp == &js_ScriptClass)
Nits: don't parenthesize == unnecessary; do keep the ? term on its own line as it was before.
/be
Assignee | ||
Comment 20•18 years ago
|
||
per brendan's suggestions
Attachment #239320 -
Attachment is obsolete: true
Attachment #241749 -
Flags: superreview?(brendan)
Attachment #239320 -
Flags: superreview?(brendan)
Assignee | ||
Comment 21•18 years ago
|
||
Probably still need the code from comment #2 to land, then mark fixed?
Whiteboard: [checkin needed]
Assignee | ||
Comment 22•18 years ago
|
||
> Probably still need the code from comment #2 to land, then mark fixed?
Sorry wrong window, disregard.
Comment 23•18 years ago
|
||
Comment on attachment 241749 [details] [diff] [review]
cleanup
Cool, a one-liner.
r+me (no super-review required or even optional typically in js/src -- occasionally someone requests it, but most often cuz bugzilla makes it hard to ask for second-review from the get-go).
/be
Attachment #241749 -
Flags: superreview?(brendan) → review+
Comment 24•18 years ago
|
||
mozilla/js/src/jsapi.c 3.284
Status: ASSIGNED → RESOLVED
Closed: 24 years ago → 18 years ago
Resolution: --- → FIXED
Whiteboard: [checkin needed]
Comment 25•18 years ago
|
||
Maybe it's just me, but this doesn't seem like a fix which should go on a stable branch which promises some level of behavioral compatibility with 1.5. (See also bug 289933 comment 10.) I suspect the only way to find out for sure would be to try it and see if anything breaks, which seems shaky to me since I doubt point version nightlies get the testing trunk nightlies get, which still might not even be enough to catch something here.
Comment 26•18 years ago
|
||
Yes, this should be trunk only.
/be
No longer blocks: js1.7src
Flags: blocking1.8.1.1?
Comment 27•18 years ago
|
||
modify test to test for typeof regexp == object. This will fail on pre 1.9.0 builds.
Checking in regexparg-1.js;
/cvsroot/mozilla/js/tests/js1_2/function/regexparg-1.js,v <-- regexparg-1.js
new revision: 1.5; previous revision: 1.4
Comment 28•17 years ago
|
||
(In reply to comment #17)
> Brian,
>
> The reason typeof currently thinks a regexp instance is a function is because
> it has what the standard calls a [[Call]] member (not sure what you call it
> internally in your code). According to previous comments, someone mapped
> [[Call]] in regexp instances to the .exec method. This is totally non-standard
> and not useful in any way.
>
Then why not remove it?
> My recommendation is to remove that mapping and you will not need to do
> anything else (because no [[Call]] will be defined, typeof will realize it
> should return "object" and not "function", according to the standard).
>
I agree. It makes no sense. Nobody calls a RegExp with (); that is what exec() is for.
> Distinguishing between objects is already well taken care of by instanceof and
> .constructor, there's really no need to add a method (see obj instanceof RegExp
> and obj.constructor==RegExp).
>
Not between frames.
isPrototypeOf has the same problem there, too. Typeof is necessary.
I'm not sure if this can really be RESOLVED FIXED. The behavior seems wrong to me.
Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8.1.7) Gecko/20070914 Firefox/2.0.0.7
var r = /foo/;
typeof r; // "function" <-- THIS SEEMS WRONG.
r("foo"); // <-- This should not be possible.
Function.prototype.call.call(x, x, "bar")// <-- error.
Function.prototype.call called on incompatible /bar/
[Break on this error] undefined
Comment 29•17 years ago
|
||
Testcase showing how RegExp cannot be called using Function.prototype.call.
========================================================================
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.
========================================================================
Comment 30•17 years ago
|
||
Better conditional check for window.console vs. alert.
Attachment #285135 -
Attachment is obsolete: true
Comment 31•17 years ago
|
||
Pay attention! This bug is indeed fixed in the CVS trunk for Mozilla 1.9 / Firefox 3. The patch is not going into a Firefox 2.0.0.x update.
Also, the latest from ECMA TG1 on JS2/ES4:
* typeof f == "function" iff f instanceof Function *for some Function constructor* (i.e., works when f was created in another window from the one loading the script doing the typeof test).
* ES4 is making regexps callable as shorthand for exec, based on the SpiderMonkey extension. This is convenient as shorthand; love it or live with it. But per the first point, typeof /hi/ == "object" in ES4.
* If you want to test whether arbitrary x is callable, write
if (x is Callable) ...
/be
Status: RESOLVED → VERIFIED
Comment 32•17 years ago
|
||
I forgot to mention two more ES4 bits of news:
* Function call and apply will work on any x for which (x is Callable).
* There will be static generic Function.call and Function.apply counterparts to the Function.prototype call and apply, for shorter invocation on non-functions.
/be
You need to log in
before you can comment on or make changes to this bug.
Description
•