Proposed change to typeof (was: Draft of Function.prototype.bind)
Mark S. Miller wrote:
For Cajita, the only issue is RegExps. Host objects are such a disaster of unspecified vagueness and random browser behavior that we never expose hosts objects directly to cajoled code. Rather, we intermediate all access to host objects through our taming layer. Other secure JS variants -- ADsafe, FBJS, Jacaranda, MS WebSandbox, dojox.secure -- do likewise.
Within Cajita, RegExps are non-callable and are not functions, irrespective of the underlying JS's behavior. Therefore, within Cajita, |typeof F === 'function'| iff the [[Class]] property of F is "Function". In Cajita, therefore, there is no difference between "being callable" and "being a function".
Because Rhino and WebKit say that typeof a RegExp is 'function', we need to translate all Cajita typeof operations. Because Valija -- the full ES3.1-strict emulation layer build on Cajita -- uses typeof in performance critical places, this translation turned out to be costly.
I suggest that, for non-host objects, we change the ES3.1 spec so that |typeof F === 'function'| iff the [[Class]] property of F is "Function". For host objects, the spec would continue to allow them to return whatever the func they want ;). This proposed change is acceptable to all participants on this morning's ES3.1 call, pending your reactions on these lists.
I object. The Jacaranda runtime depends on being able to distinguish callable from noncallable objects. With this change, it has no reliable way to do so. (For the specific case of RegExp objects, there is no direct security problem because they do not use the value of 'this' when called. However, the proposed change in the spec would allow other native objects to be undetectably callable.)
The correct fix is to make RegExp objects noncallable. This matches IE and Opera's behaviour and so will not "break the web".
On Nov 4, 2008, at 19:11 , Mark S. Miller wrote:
I suggest that, for non-host objects, we change the ES3.1 spec so
that |typeof F === 'function'| iff the [[Class]] property of F is
"Function". For host objects, the spec would continue to allow them
to return whatever the func they want ;). This proposed change is
acceptable to all participants on this morning's ES3.1 call,
pending your reactions on these lists.
FWIW: That's what jQuery ended up using--after much tergiversation
On Nov 4, 2008, at 12:11 PM, David-Sarah Hopwood wrote:
The correct fix is to make RegExp objects noncallable. This matches IE and Opera's behaviour and so will not "break the web".
Careful. We can reason about breaking the web if something disagrees
with IE, but not all JS implementations agree with IE JScript (e.g.
otherWindow.eval in IE does dynamic scope based on interleaving of
active function objects' globals on the call stack!). No one proposes
that all IE JScript quirks become normative standards.
From the complaints we've heard, making typeof /hi/ == "function"
broke compatibility badly enough that we regretted the change, and
reverted it. But we kept regexps callable for those Mozilla-platform
consumers who may care. Finding out what breaks will require an open
source release cycle, at least.
I agree with Maciej that we don't know enough to say that too much
breaks if regexps become non-callable in Firefox and Safari. We don't
know that too little, or nothing, breaks, either. Citing Opera and IE
doesn't help, since web JS is often user-agent forked on "isIE" tests,
and Opera masquerades as IE (sometimes).
On Nov 4, 2008, at 10:11 AM, Mark S. Miller wrote:
On Mon, Nov 3, 2008 at 10:55 PM, Maciej Stachowiak <mjs at apple.com>
wrote: I'm sure people may have an opinion one way or the other, I just
don't know of any Web content actually broken by this in practice. I
don't have strong feelings on the matter in either direction, just
reporting our experience.For Cajita, the only issue is RegExps. Host objects are such a
disaster of unspecified vagueness and random browser behavior that
we never expose hosts objects directly to cajoled code. Rather, we
intermediate all access to host objects through our taming layer.
Other secure JS variants -- ADsafe, FBJS, Jacaranda, MS WebSandbox,
dojox.secure -- do likewise.Within Cajita, RegExps are non-callable and are not functions,
irrespective of the underlying JS's behavior. Therefore, within
Cajita, |typeof F === 'function'| iff the [[Class]] property of F is
"Function". In Cajita, therefore, there is no difference between
"being callable" and "being a function".Because Rhino and WebKit say that typeof a RegExp is 'function', we
need to translate all Cajita typeof operations. Because Valija --
the full ES3.1-strict emulation layer build on Cajita -- uses typeof
in performance critical places, this translation turned out to be
costly.
I suggest that, for non-host objects, we change the ES3.1 spec so
that |typeof F === 'function'| iff the [[Class]] property of F is
"Function". For host objects, the spec would continue to allow them
to return whatever the func they want ;). This proposed change is
acceptable to all participants on this morning's ES3.1 call, pending
your reactions on these lists.
Practically, the only difference this will make is to mandate that
typeof a RegExp be "object", not "function", whether or not RegExps
are callable on that platform. Given that this matches IE's and FF's
current behavior, this change will not break the web. This would
have the unpleasant consequence of causing WebKit and Rhino to
become out of conformance with ES3.1 because they correctly
implemented this clause of ES3. If they do not object, does anyone
see any other downsides to this suggestion?
Given Mozilla's behavior, I am willing to believe it is safe to make
typeof a RegExp be "object", and furthermore it seems better to make
this consistent rather than implementation dependent. Thus:
- I support this spec change.
- I think it would be good to make the change in WebKit/
JavaScriptCore even in advance of the spec, for interoperability and
to match developer expectations, so I filed <bugs.webkit.org/show_bug.cgi?id=22082
.
In the long term, we might want to remove the callable regexp
extension entirely. That change would require more testing than just
the typeof change, so we probably won't do it right away.
, Maciej
On Mon, Nov 3, 2008 at 10:55 PM, Maciej Stachowiak <mjs at apple.com> wrote:
For Cajita, the only issue is RegExps. Host objects are such a disaster of unspecified vagueness and random browser behavior that we never expose hosts objects directly to cajoled code. Rather, we intermediate all access to host objects through our taming layer. Other secure JS variants -- ADsafe, FBJS, Jacaranda, MS WebSandbox, dojox.secure -- do likewise.
Within Cajita, RegExps are non-callable and are not functions, irrespective of the underlying JS's behavior. Therefore, within Cajita, |typeof F === 'function'| iff the [[Class]] property of F is "Function". In Cajita, therefore, there is no difference between "being callable" and "being a function".
Because Rhino and WebKit say that typeof a RegExp is 'function', we need to translate all Cajita typeof operations. Because Valija -- the full ES3.1-strict emulation layer build on Cajita -- uses typeof in performance critical places, this translation turned out to be costly.
I suggest that, for non-host objects, we change the ES3.1 spec so that |typeof F === 'function'| iff the [[Class]] property of F is "Function". For host objects, the spec would continue to allow them to return whatever the func they want ;). This proposed change is acceptable to all participants on this morning's ES3.1 call, pending your reactions on these lists.
Practically, the only difference this will make is to mandate that typeof a RegExp be "object", not "function", whether or not RegExps are callable on that platform. Given that this matches IE's and FF's current behavior, this change will not break the web. This would have the unpleasant consequence of causing WebKit and Rhino to become out of conformance with ES3.1 because they correctly implemented this clause of ES3. If they do not object, does anyone see any other downsides to this suggestion?