- From: Brendan Eich <brendan@mozilla.com>
- Date: Sat, 11 Aug 2012 19:42:08 -0700
- To: Cameron McCormack <cam@mcc.id.au>
- CC: Boris Zbarsky <bzbarsky@mit.edu>, public-script-coord@w3.org, es-discuss@mozilla.org
Cameron McCormack wrote: > Brendan Eich: >> As bz and others point out, the object detection w/ var pattern can >> arise for operations, e.g. for requestAnimationFrame, using the same >> >> var requestAnimationFrame = window.mozRequestAnimationFrame || ... || >> window.requestAnimationFrame; >> >> pattern. So WebIDL operations (JS methods) on the global would be >> promoted to "own" too. They'd be configurable, if I recall correctly, >> and either writable or replaceable. Do I have that right? > > OK. So one thing that I think has been pointed out is that moving > properties for operations on to window makes it harder to monkeypatch > addEventListener and friends. This is a recent feature, right? I can't even find EventTarget in Opera 12, e.g. It's plausible the global object exception breaks symmetry here. Could we live with the inability to monkey-patch? As Jonas points out, playing deep prototype chain games with the global object when var (and function) shadow as in ES6 or ES5.1+erratum-fix is just bug-making and confusing. > We *could*, if we thought it was important, have the properties on > window forward on to the ones from the prototype. Less magic if we can avoid it. > Some other questions on specifics: > > 1. If we don't do that auto-forwarding, does Window.prototype still > need to exist? What should window.__proto__ be? There's no need to over-invent for uniformity, if the global object is exceptional. The simpler the exception, the better. However, implementations (at least Gecko) give window a proto chain that is "interesting": -- [19:29:57.405] Object.prototype.toString.call(window.__proto__).slice(8,-1) [19:29:57.408] "XPC_WN_ModsAllowed_NoCall_Proto_JSClass" -- [19:30:06.143] Object.prototype.toString.call(window.__proto__.__proto__).slice(8,-1) [19:30:06.145] "Global Scope Polluter" -- [19:30:11.629] Object.prototype.toString.call(window.__proto__.__proto__.__proto__).slice(8,-1) [19:30:11.631] "Object" -- [19:30:18.373] Object.prototype.toString.call(window.__proto__.__proto__.__proto__.__proto__).slice(8,-1) [19:30:18.375] "Null" This is from a stable-release Firefox Web Console. I believe it matches a real DOM content window. I don't see EventTarget, because its methods get flattened into the direct proto, Window.prototype: [19:33:30.076] Window.prototype === this.__proto__ [19:33:30.077] true -- [19:33:50.323] Object.getOwnPropertyNames(this.__proto__) [19:33:50.325] ["addEventListener", "removeEventListener", "dispatchEvent", "dump", "name", "parent", "top", "self", "sessionStorage", "localStorage", "onmouseenter", "onmouseleave", "getSelection", "scrollByLines", "getComputedStyle", "__lookupGetter__", "__lookupSetter__", "__defineGetter__", "__defineSetter__", "toString", "QueryInterface", "window", "document", "location", "history", "locationbar", "menubar", "personalbar", "scrollbars", "statusbar", "toolbar", "status", "close", "stop", "focus", "blur", "length", "opener", "frameElement", "navigator", "applicationCache", "alert", "confirm", "prompt", "print", "showModalDialog", "postMessage", "atob", "btoa", "matchMedia", "screen", "innerWidth", "innerHeight", "scrollX", "pageXOffset", "scrollY", "pageYOffset", "scroll", "scrollTo", "scrollBy", "screenX", "screenY", "outerWidth", "outerHeight", "scrollByPages", "sizeToContent", "content", "closed", "crypto", "pkcs11", "controllers", "defaultStatus", "mozInnerScreenX", "mozInnerScreenY", "scrollMaxX", "scrollMaxY", "fullScreen", "back", "forward", "home", "moveTo", "moveBy", "resizeTo", "resizeBy", "updateCommands", "find", "mozPaintCount", "mozRequestAnimationFrame", "mozCancelAnimationFrame", "mozCancelRequestAnimationFrame", "mozAnimationStartTime", "URL", "onafterprint", "onbeforeprint", "onbeforeunload", "onhashchange", "onmessage", "onoffline", "ononline", "onpopstate", "onpagehide", "onpageshow", "onresize", "onunload", "ondevicemotion", "ondeviceorientation", "ondeviceproximity", "onuserproximity", "ondevicelight", "setTimeout", "setInterval", "clearTimeout", "clearInterval", "setResizable", "captureEvents", "releaseEvents", "routeEvent", "enableExternalCapture", "disableExternalCapture", "open", "openDialog", "frames", "onabort", "onblur", "oncanplay", "oncanplaythrough", "onchange", "onclick", "oncontextmenu", "ondblclick", "ondrag", "ondragend", "ondragenter", "ondragleave", "ondragover", "ondragstart", "ondrop", "ondurationchange", "onemptied", "onended", "onerror", "onfocus", "oninput", "oninvalid", "onkeydown", "onkeypress", "onkeyup", "onload", "onloadeddata", "onloadedmetadata", "onloadstart", "onmousedown", "onmousemove", "onmouseout", "onmouseover", "onmouseup", "onmozfullscreenchange", "onmozfullscreenerror", "onmozpointerlockchange", "onmozpointerlockerror", "onpause", "onplay", "onplaying", "onprogress", "onratechange", "onreset", "onscroll", "onseeked", "onseeking", "onselect", "onshow", "onstalled", "onsubmit", "onsuspend", "ontimeupdate", "onvolumechange", "onwaiting", "oncopy", "oncut", "onpaste", "onbeforescriptexecute", "onafterscriptexecute", "indexedDB", "performance"] The global object's prototype chain must end with Object.prototype (ES5 says so, IIRC). But the exact chain is not something that should be standardized in detail. > 2. If Window.prototype still does exist, should it be empty? Rather have no Window.prototype if everything currently there becomes "own" in each window object, than have an empty proto as an attractive nuisance. You can't patch if shadowed by an own property, but it might seem like you ought to be able to. > > 3. The only writable IDL attributes on Window are: > > attribute DOMString name; > attribute DOMString status; > attribute WindowProxy? opener; > > and all of the event handler attributes like "onclick". How do these > need to behave if script blithely tries to use variables of the same > name? With this: > > <script> > alert([window.status, typeof window.status]); > window.status = "hello"; > alert([window.status, typeof window.status]); > </script> > <script> > var status; > alert([window.status, typeof window.status]); > status = 1; > alert([window.status, typeof window.status]); > </script> > > Gecko and Opera alert: > > ,string > hello,string > ,undefined > 1,number Yes, this is more lossage compared to historical norms that WebKit-based browsers still uphold. The lack of a var initialiser means that the (historically own) status accessor must have its getter or setter invoked. 'var' doesn't replace an existing own property in any scenario, historical or ES5+erratum-fix. > while Chrome and Safari alert: > > ,string > hello,string > hello,string > 1,string > > which seems to indicate that they're setting the IDL attribute. Did you try IE8, 9 and 10? I suspect they match but can't test. > I guess this is related to whether we want "function onclick(){}" to > invoke the setter. We decided (as Allen points out; related to the var issue but distinct from it) we do not. But function onmessage(){} in a worker script then doesn't do what some devs seem to like (or at least expect) from Chrome and Safari. > With this: > > <body onerror="alert('exception')"> > <script> > alert([String(window.onclick), typeof window.onclick)]); > </script> > <script> > var onclick = 1; > alert([String(window.onclick), typeof window.onclick]); > </script> > > Gecko, Opera and Chrome alert: > > null,object > 1,number > > which could mean shadowing or treating "onclick" as IDL type "any" and > treating non-Function values as null, while Safari alerts: > > null,object > null,object > > which looks like it's invoking the setter but ignoring the assignment > of a non-Function value. Seems a Safari deviation. /be
Received on Sunday, 12 August 2012 02:43:14 UTC