Open Bug 652140 Opened 14 years ago Updated 2 years ago

`window.Moz`: JavaScript "vendor prefixing" *and* solid user-agent detection

Categories

(Core :: DOM: Core & HTML, enhancement, P5)

enhancement

Tracking

()

People

(Reporter: getify, Unassigned)

References

Details

In a discussion on the dev-tools team today, the topic was brought up of doing a "vendor-prefix" for a new JavaScript component (global object) that's being experimented with. Apparently the previous approach to this has been to just put "Moz" at the beginning of some JavaScript object name. That discussion sparked this feature request. Also, as backstory... there are unfortunately still some things in the web dev world which require user-agent detection. UA string sniffing is obviously the less desirable way (compared to straight feature detection). Opera has long had something which is quite helpful in this regard: `window.opera`. Not only is the DOM object present in all builds of Opera, but it's got a special internal class that cannot be faked, so a web dev has a pretty reliable test that if the `window.opera` is present and is of the right "type", then the browser is almost surely Opera. Chrome recently followed suit (sort of) with `window.chrome`, but they have failed as of yet to give it the special internal class, so it's a less reliable detect. At the moment, projects that need to detect FF (as unfortunate as those situations are) have to detect with something like what I do in LABjs: `("MozAppearance" in document.documentElement.style)`. -------- So, I have the idea that both the JavaScript "vendor-prefixing" (aka, namespacing) and the better user-agent detection can be birds killed with one stone. I would like us to add a `window.Moz` or `window.mozilla` or (even `window.gecko`) property, with the special internal class like [[object Mozilla]]. Then, this object would serve for solid/non-hacky UA detection, and it would also serve as the object "namespace" where experimental JavaScript objects can be hung off of. When such object APIs are standardized and no longer need prefixing, the whole object can easily move off of (or just be aliased off of) `window.Moz.foo` and onto something like `window.foo`, etc. This type of "prefixing" (using JavaScript object namespacing convention) is I think better than having an entire API nameset change, like removing the leading "Moz" from the name of every function, etc. And it's especially true if we move the object to `window` but leave an alias on `window.Moz`, then developers have an easier time of making the transition from the usage of prefixed API to the eventual standardized API.
Version: unspecified → Trunk
Why do you need to detect "gecko" as opposed to detecting specific capabilities? In the past, sites that do the former break when Gecko's capabilities change....
@Boris- there are, unfortunately, still some things which are not feature-detectable, but which in fact must be "detected" for various JavaScript functionality. In that case, one has to fall back on browser inferences. I could make a long list of such feature peculiarities, but I'll just give one example to illustrate: The nature (async or not, parallel or not) of dynamic script loading behavior differs wildly between browsers. As of FF4 (and the HTML spec recently), we have `script.async==true` as a test, as I'm sure you recall. But prior to FF4, the only option was to rely on a known set of behavior based on browser version> This is why LABjs still has the `("MozAppearance" in document.documentElement.style)` browser inference detect in it, because LABjs still supports FF2.0+. So, LABjs first feature-detects for the `script.async==true`, but if it's not found, then it falls back on browser inferencing for legacy support. I don't really wanna get in the weeds of whether browser inferencing is good or not, nor do I want to rehash the script loading topic again. I think it's clear this is just one of many examples of browser oddities which are not feature detectable, but nevertheless, web devs have to fork behavior to get desired cross-browser functionality. Other examples are quirks like how opacity works, how fonts render, etc. IIRC, Paul Irish compiled a long list of non-feature-detectable differences in browsers. I can try to dig up a link if you're interested. --------- In any case, the point of this enhancement request is not JUST about browser inferencing. It's partly that, and equally (or more so) about a perhaps better way to handle "vendor prefixing" on JavaScript APIs.
Version: Trunk → unspecified
I'd also like to make it clear... I'm not in ANY way suggesting that `window.Moz` would be a substitute for feature-detection. Responsible web dev would be to always feature-detect first, if possible, and only fall back on inferences like this when there was no other better information.
From an #devtools IRC chat: [11:30] <getify> but i believe there will always be quirks which are not feature detectable [11:30] <getify> and thus there will always be web devs who need to fork [11:30] <robcee> I think in the end you're still going to need to do feature-detection plus the object lookup [11:30] <getify> absolutely [11:30] <robcee> since the object won't be strictly reliable [11:30] <getify> feature detection first, like LABjs does [11:31] <robcee> and then you're back in the same boat [11:31] <robcee> and jquery and most other modern libs [11:31] <getify> there's a hierarchy of "goodness" in this realm... 1) feature detection 2) feature inference 3) browser inference 4) UA sniffing (browser "detection") [11:32] <getify> but with respect to some other browser coping `window.Moz`... they haven't done that with any of our "MozAppearance" stuff... I see no reason why they would do that here. also, Opera and Chrome have already set the precedent for an identifier that's more reliable than UA sniffing [11:33] <getify> The likelihood of Chrome or IE or Opera or Safari doing a `window.Mozilla` is pretty slim, I think [11:34] <getify> and giving it a special internal non-fakeable class means that user-land scripts can't trip you up <getify> which is exactly what a lot of script loaders do with `window.opera` right now [11:39] <robcee> maybe so [11:40] <robcee> back in the day when UAs were novel, everybody put a Mozilla in there to mock compatibility [11:40] <getify> yes, they're still there [11:40] <getify> but i think the landscape of web browser behavior is quite diff than it used to be [11:41] <robcee> prolly true [11:42] <getify> i can't imagine the community allowing any browser to get away with such shenanigans in today's web
I should note that I was initially skeptical but Kyle's won me over a bit. It could be a useful feature in addition to feature interrogation.
I believe this would be a pretty strong signal to web developers that they don't need to bother with feature detection, and as such, I would not be happy if this was implemented. Note that this would not help for older features, and I believe we do attempt to make new features detectable.
(in reply to Comment #6) > I believe this would be a pretty strong signal to web developers that they don't need to bother with feature detection Feature detection is still practiced (and strongly preferred) in both Chrome and Opera, where they have `window.opera` and `window.chrome`, respectively. I don't think there's any evidence to suggest that our browser's devs would somehow be different/regressive enough to rip out their feature-detection code and start using sub-optimal browser inferences instead. Plus, the issue of what the right steps are in web dev (feature detection first, inferences second, sniffing third, etc), is purely an educational thing. We can't force users not to do wrong things. Simply adding `window.Moz` is not forcing (or even encouraging) bad behavior, it's just replacing the more hacky `("MozAppearance" in document.documentElement.style)` type of "detection" (that lots of devs already do!) with something that's more reliable and semantic. Nothing changes about the fact that browser inferencing remains second or third on the totem pole of best practices. > Note that this would not help for older features, and I believe we do attempt to make new features detectable. It wouldn't help older browser versions, but it would ABSOLUTELY help existing (aka "old") features that are still present in our newest/next versions of FF. It's an admirable goal to have every single quirk of behavior about a browser be detectable with a semantic FT, but it's not reality, nor will it be for a LONG time. Again, there's a long list of browser behaviors that are not currently feature detectable, so the task of making every single such behavior fully detectable is FAR more difficult and out of scope as compared to giving a decent fallback like `window.Moz`.
Also, on the topic of adding things which might "enable" devs to do less-than-best-practice things... if we ignore my suggestion entirely, and go forward with adding a "prefixed" JavaScript API called `window.MozCrypt`... that is just as much fodder for improper/lazy browser inferencing, because devs *could* say: "well, if `MozCrypt` is present, then it's surely a Mozilla browser..." But allowing "MozCrypt" into the wild, to be eventually picked up on my lazy devs, as a browser inference is more hacky and far less future-proof reliable, since eventually that prefixed API name is gonna go away entirely. OTOH, something like `window.Moz` as a container for the prefixing of all future APIs is a little more reliable, since `window.Moz` would remain even after `window.Moz.Crypt` eventually went away. ------ Moreover, since this bug is only HALF about the better browser-inferencing, and the other (perhaps more important) half about providing a better pattern for "vendor prefixing" of JavaScript API's, can we talk about the suggestion in its full context, instead of getting into rabbit trails about what devs should and shouldn't do in the greater web dev ecosystem?
I'd like to voice support for namespacing new APIs this way. I think this represents an incremental improvement over existing feature detection practices, if only to encourage a standard like this. I agree that developer laziness can/will persist regardless of the implementation :)
Had a good discussion this morning and out of that came a useful suggestion for an addition to this proposal. The usefulness of the addition is primarily from the perspective of web devs using these experimental features across various browsers that have each implemented their respective `window.XYZ` property as prefixing namespace. It would be helpful to have an alias reference, such as `window.vendor` (*not* `navigator.vendor`) that points to each browser vendor's respective object namespace. For instance: `window.vendor === window.firefox`. It could also be `window.experimental` or something like that. In this way, a dev could access (or test for) a feature either using the vendor-prefixed way (`window.firefox.FooBar`), if they care about a specific vendor version of an API, or in a vendor agnostic way (`window.vendor.FooBar`) if they don't care about vendor diffs. And a shim for browsers which don't have this alias (but do have the vendor-specific window.XYZ object) might be: https://gist.github.com/940603
Earlier in this thread the question was asked, why isn't feature detection sufficient (why would you ever need to UA detect)? Here's that list: https://github.com/Modernizr/Modernizr/wiki/Undetectables
So looking at that list, a bunch of them have to do with UAs having bugs where they expose an object but just have it behave wrong. Some others are just wrong (e.g. you can feature-detect &shy; and <wbr> as far as I can tell). And the thing about non-hardware-accelerated transitions is just bizarre; that shouldn't happen unless you're using a way lower frame rate with setTimeout.
Component: DOM: Mozilla Extensions → DOM
https://bugzilla.mozilla.org/show_bug.cgi?id=1472046 Move all DOM bugs that haven’t been updated in more than 3 years and has no one currently assigned to P5. If you have questions, please contact :mdaly.
Priority: -- → P5
Component: DOM → DOM: Core & HTML
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.