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
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 -
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
Oops. ECMA-262 Edition 3 does *not* specify a [[Call]] internal method for RegExp objects. Was that an oversight, or intentional? /be
waldemar, pls. advise and reassign to rogerl or mark INVALID. Thanks, /be
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.
Marking Verified -
*** Bug 93589 has been marked as a duplicate of this bug. ***
*** Bug 353448 has been marked as a duplicate of this bug. ***
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".
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
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
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?
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
Created attachment 239320 [details] [diff] [review] Removed regexp class from this special case 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.
(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?
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).
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.
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
Created attachment 241749 [details] [diff] [review] cleanup per brendan's suggestions
Probably still need the code from comment #2 to land, then mark fixed?
> Probably still need the code from comment #2 to land, then mark fixed? Sorry wrong window, disregard.
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
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.
Yes, this should be trunk only. /be
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
(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:220.127.116.11) Gecko/20070914 Firefox/18.104.22.168 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
Created attachment 285135 [details] Call RegExp with Function.prototype.call throws TypeError Testcase showing how RegExp cannot be called using Function.prototype.call. ======================================================================== 22.214.171.124 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. ========================================================================
Created attachment 285138 [details] Call RegExp with Function.prototype.call throws TypeError Better conditional check for window.console vs. alert.
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
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