Real World Func Decl in Block Scope Breakages

Allen Wirfs-Brock allen at wirfs-brock.com
Wed Dec 26 14:22:57 PST 2012


On Dec 26, 2012, at 2:02 PM, David Herman wrote:

> Hi Brian,
> 
> Thanks for the data.
> 
> My understanding of the consensus was that block-local functions would only have the new semantics within strict code (which includes module code), so there would be no breakage of existing content.

That isn't my understanding.  Rather, it was that we would support block level function declarations in all code.  This was based upon the premise that the interoperable  intersection of the currently implemented semantics for block level function declarations is very small.  Essentially only,  uses of this form are currently interoperable among all major implementations:

if (condition) {
     function foo() {};
     foo();   //function declared and invoked in same conditional blocks.
} 

Other uses (without other explicit feature or browser detection logic being involved) are not likely to be interoperable.

I haven't looked in detail at all of Brian's snippets.  But several that I have glanced at look to me like they wouldn't be interoperable among current browsers.

Alen

> 
> That said, if we felt the breakage was acceptable, in the long run it'd be *preferable* to have consistent semantics of block-local functions everywhere. Data like this certainly helps to make more informed decision about that.
> 
> Dave
> 
> On Dec 26, 2012, at 1:04 PM, Brian Terlson <Brian.Terlson at microsoft.com> wrote:
> 
>> I have some data on patterns and sites that may break due to the proposed change to semantics of function decls in block scope. I am not advocating for any changes here but merely dumping some data I’ve gathered. I will continue gathering data about this breaking change and potentially others (eg. let[x] = 1), so any further data you folks are interested in let me know. I think the January meeting would be a good venue to discuss any of this in detail if warranted.
>> 
>> On December 17th, 2235 sites were crawled and their scripts downloaded. These scripts were then processed in an attempt to identify likely breakages due to the change to the semantics of func decls in block scope. In this dataset, 4% of the scripts contained a function declaration in block scope (mostly inside if and try, although pretty much every node contains a function somewhere in this dataset). However, most of these scripts use the function within the same block and so won’t be broken. 20 sites, however, will likely be broken by this change in some way. There is also a chance that the tool used to identify breakages has missed some code that will breka.
>> 
>> Below are some examples of code on the web today that will be broken. For each I include a snippet of code that is heavily edited in an attempt to convey the pattern used and the developer intent. I also attempt to identify what functionality will actually be broken.
>> 
>> Most of the breakages occur in non-library code, with two exceptions: qTip 1.0, and thickbox 3.
>> 
>> # http://ninemsn.com.au
>> 
>> RenderModal = function () {
>>    if (x) { // is an array of shortcuts that can be added. Is statically non-empty.
>>        function K() {
>>            // process the array of shortcuts in some way
>>        }
>>    }
>>    K();
>> };
>> 
>> ## Scenario
>> 
>> 1.       Navigate to main page.
>> 2.       Click “Add other shortcuts”
>> 3.       Click “View more shortcuts” – this will not work.
>> 
>> 
>> # http://yandex.ru
>> 
>> if (_ycssjs("BaH0Fmmo2Sg24lRmTPrK0B8qpaA")) {
>>    function cp(g, c, d) { /* ...*/ }
>> 
>>    function csh_ifgsid(c, b) { /*...*/ } }
>> 
>> // ... thousands of lines of code ...
>> 
>> 
>> if (_ycssjs("rO+QIoSf2L0NwDn6vjJjy+27nxI")) {
>>    function news() {
>>        csh_if_gsid();
>>    }
>> }
>> 
>> if (_ycssjs("YRPF0QVjJmhRiKRu6cvi3YXqYo8")) {
>>    // ... bunch of stuff ...
>>    cp();
>> }
>> 
>> ## Scenario
>> 
>> Unknown
>> 
>> 
>> # http://g.espncdn.com/nfl-primetime-payoff/en/module/entry?matchupid=478
>> 
>> if (isIE && isWin) {
>>    // ...
>> } else {
>>    function JSGetSwfVer(i){
>>        // ...
>>    }
>> }
>> 
>> function checkFlash(myRev) {
>>    // ...
>> 
>>    if (isIE && isWin) {
>>        // ...
>>    } else {
>>        aV = JSGetSwfVer(rV);
>>    }
>> 
>> }
>> 
>> ## Scenario
>> 
>> Can’t find a page which uses this code.
>> 
>> 
>> # http://www.t-online.de
>> 
>> if (!Adition_Environment) {
>>    var Adition_Environment = (function () {
>>        var _this = {};
>>        // ...
>>        _this.getPrf = function (cuId) {
>>            var prf = "";
>>            try {
>>                prf = Adition_Prfstr(cuId);
>>            } catch (e) { }
>>            return prf;
>>        };
>>        // ...
>>    })();
>> }
>> 
>> // snip 1k lines
>> if (typeof Adition_Prfstr == "undefined") {
>>    function Adition_Prfstr(ADITION_CONTENTUNIT_ID) {
>>        // ...
>>    }
>> }
>> 
>> ## Scenario
>> 
>> Required to display advertisements on the page.
>> 
>> 
>> 
>> # http://manormystery.com
>> 
>> if (!window._ate) {
>>    window._ate = { /* ... */ };
>>    function addthis_open() { /* ... */ } } else { _ate.inst++; }
>> 
>> if (_atc.abf) {
>>    addthis_open(document.getElementById("ab"), "emailab", window.addthis_url || "[URL]", window.addthis_title || "[TITLE]"); }
>> 
>> ## Scenario
>> 
>> Social sharing popups broken at least. This may be a general utility used in a number of places.
>> 
>> 
>> 
>> # http://manhunt.net (NSFW, DO NOT VISIT AT WORK)
>> 
>> /** @todo isFlashInstalled() should probably be gotten by include from js/cmmn/flashDetect.js or upfunc.js. */
>> 
>> if (typeof isFlashInstalled == 'undefined') {
>>    function isFlashInstalled() {
>>        var requiredMajorVersion = 6; // Major version of Flash required
>>        var requiredMinorVersion = 0;   // Minor version of Flash required
>>        var requiredRevision = 0;   // Minor version of Flash required
>>        var s = new SWFObject();
>>        if (!s) return false;
>>        var version = s.installedVer;
>>        if (!version) return false;
>>        return (version.major >= requiredMajorVersion && version.minor >= requiredMinorVersion && version.rev >= requiredRevision);
>>    }
>> }
>> isFlashInstalled();
>> 
>> ## Scenario
>> 
>> I avoided this site at work for obvious reasons, but it looks like all login functionality will be broken.
>> 
>> 
>> 
>> 
>> # http://www.163.com
>> 
>> NTESAD_Couplet.prototype = {
>>    NTESCreate: function () {
>> 
>>        var widthsmall = this.options.widthsmall;
>>        var width = this.options.width;
>> 
>>        if (this.options.leftbig != "" && this.options.leftsmall != "") {
>>            function bighide() {
>>                coupletLeft.style.display = "none";
>>                coupletLeftsmall.style.display = "block";
>>            }
>> 
>>            function smallhide() {
>>                coupletLeftsmall.style.display = "none";
>>                coupletLeft.style.display = "block";
>>            }
>>        }
>> 
>>        if (this.options.rightbig != "" && this.options.rightsmall != "") {
>>            function Rbighide() {
>>                coupletRight.style.display = "none";
>>                coupletRightsmall.style.display = "block";
>>            }
>>        }
>> 
>>        if (this.NTESPosition()) {
>>            if (this.options.leftbig != "" && this.options.leftsmall != "" && this.options.rightbig != "" && this.options.rightsmall != "") {
>>                this.NTESBind(coupletclose, "click", function () { bighide(); Rbighide(); coupletRightsmall.style.display = "none"; coupletLeftsmall.style.display = "none"; });
>>                this.NTESBind(coupletclose2, "click", function () { bighide(); Rbighide(); coupletRightsmall.style.display = "none"; coupletLeftsmall.style.display = "none"; });
>>            }
>>        }
>>    }
>> }
>> 
>> ## Scenario
>> 
>> Unknown.
>> 
>> 
>> 
>> # http://www22.verizon.com
>> 
>> if (floatStyle.match(/Content/)) {
>>    var contentDiv = d.getElementById(_b.Preferences.Render.main_content_id || "content");
>>    if (contentDiv == null) {
>>        floatStyle = this.Preferences.Render.float_style = 'fixed'
>>    }
>>    function getRightOfContent() {
>>        return contentDiv.offsetWidth + contentDiv.offsetLeft + 1
>>    }
>>    function fixBackground() {
>>        if (_b.Preferences.Render.fix_background) {
>>            db.style.backgroundAttachment = "scroll";
>>            var margin = null;
>>            if (document.defaultView && document.defaultView.getComputedStyle) {
>>                margin = parseInt(document.defaultView.getComputedStyle(contentDiv, null).getPropertyValue("margin-left"), 10)
>>            } else {
>>                margin = parseInt(contentDiv.currentStyle.marginLeft, 10)
>>            }
>>            if (isNaN(margin) || margin == 0) {
>>                margin = contentDiv.offsetLeft || 0
>>            }
>>            db.style.backgroundPosition = (Math.floor(contentDiv.scrollWidth * -0.5) - 2 + margin) + 'px 0'
>>        }
>>    }
>> }
>> 
>> // getRightOfContent/fixBackground used repeatedly after this.
>> 
>> ## Scenario
>> 
>> Couldn’t find a scenario where this code was hit, but the site is expansive. Also, the above code is found in at least 2 different scripts across the site.
>> 
>> 
>> 
>> 
>> # http://www.jeuxvideo.com
>> 
>> if (typeof getAppNexusMegaTag == 'undefined' || typeof getAppNexusMegaTag != 'function') {
>>    function getSize1080667() {
>>        return '250x250';
>>    }
>> }
>> 
>> if (typeof inFIF != "undefined" && inFIF == true) {
>>    try {
>>        parent.getSize1080667 = getSize1080667;
>>    } catch (e) { }
>> }
>> 
>> 
>> ## Scenario
>> Ad won’t display.
>> 
>> 
>> 
>> # http://msn.foxsports.com
>> /* this function is much faster, so if possible we use it. Some IEs are the only ones I know of that need the idiotic second function, generated by an if clause.  */ function add32(a, b) {
>>    return (a + b) & 0xFFFFFFFF;
>> }
>> 
>> if (md5('hello') != '5d41402abc4b2a76b9719d911017c592') {
>>    function add32(x, y) {
>>        var lsw = (x & 0xFFFF) + (y & 0xFFFF),
>>            msw = (x >> 16) + (y >> 16) + (lsw >> 16);
>>        return (msw << 16) | (lsw & 0xFFFF);
>>    }
>> }
>> 
>> ## Scenario
>> 
>> Nothing is necessary broken about this, as long as the first add32 functions properly (today everyone with this code is using the second function). This is a fairly common MD5 library (do a search for “idiotic second function” to get an idea, however this was only found once in the dataset).
>> 
>> 
>> 
>> 
>> 
>> # http://iwiw.hu/i/belepes
>> 
>> (function () {
>>    if (jQuery.fn.lazyload) {
>>        function a() {
>>            return typeof f !== "undefined" ? f : (f = jQuery("body").hasClass("lazyloadimages"))
>>        }
>>    }
>>    jQuery(function () {
>>        if (a()) {
>>            d.apply(document.body)
>>        }
>>    })
>> })();
>> 
>> ## Scenario
>> 
>> Unknown
>> 
>> 
>> 
>> 
>> # http://www.laposte.net
>> 
>> if (!window.$extend) {
>>    function $extend(c, a) {
>>        for (var b in (a || {})) {
>>            c[b] = a[b]
>>        } return c
>>    }
>> }
>> // $extend used repeatedly after this
>> 
>> ## Scenario
>> Unknown
>> 
>> 
>> 
>> # http://atpworldtour.com
>> 
>> /*
>> * Stores hash values for localization.
>> * Will need duplicating for each language.
>> */
>> 
>> if (typeof registerNS == "undefined") {
>>    function registerNS(ns) {
>>        var nsParts = ns.split(".");
>>        var root = window;
>>        for (var i = 0; i < nsParts.length; i++) {
>>            if (typeof root[nsParts[i]] == "undefined")
>>                root[nsParts[i]] = new Object();
>>            root = root[nsParts[i]];
>>        }
>>    }
>> }
>> 
>> registerNS("atp.utilities");
>> // called repeatedly after this.
>> 
>> ## Scenario
>> 
>> Entire site is unusable.
>> 
>> 
>> 
>> 
>> # http://atwiki.jp
>> 
>> if (typeof AddClipsFlag == "undefined") {
>>    var AddClipsFlag = 'addclips';
>>    // ...
>>    function AddClipsLoad() { /* ... */ }
>>    // ...
>> }
>> 
>> AddClipsLoad();
>> 
>> ## Scenario
>> 
>> RSS functionality broken. This appears to be a library of some kind (see www.addclips.org).
>> 
>> 
>> 
>> # Library: qTip 1.0: https://github.com/Craga89/qTip1/blob/master/1.0.0-rc3/jquery.qtip-1.0.0-rc3.js as seen on Zoompanel.com
>> 
>> if (t.options.hide.when.event == "inactive") {
>>    function y(z) {
>> 
>>    }
>> } else {
>>    // ...
>> }
>> function x(z) {
>>    if (t.options.hide.when.event == "inactive") {
>>        y()
>>    }
>> }
>> 
>> ## Scenario
>> 
>> Used on zoompanel.com. Tooltips will never disappear after showing up.
>> 
>> 
>> # Library: thickbox 3 (http://thickbox.net/), in use on runescape.com and baixaki.com.br if (!(TB_PrevHTML === "")) {
>>    function goPrev(){
>>    }
>>    $("#TB_prev").click(goPrev);
>> }
>> 
>> if (!(TB_NextHTML === "")) {
>>    function goNext(){
>>    }
>>    $("#TB_next").click(goNext);
>> 
>> }
>> 
>> document.onkeydown = function (e) {
>>    if (keycode == 190) { // display previous image
>>        if (!(TB_NextHTML == "")) {
>>            document.onkeydown = "";
>>            goNext();
>>        }
>>    } else if (keycode == 188) { // display next image
>>        if (!(TB_PrevHTML == "")) {
>>            document.onkeydown = "";
>>            goPrev();
>>        }
>>    }
>> }
>> 
>> ## Scenario
>> 
>> Going back/forward with keyboard is broken.
>> 
>> 
>> 
>> 
>> # http://kankan.com
>> Snippet
>> if (typeof getCookie == 'undefined') {
>>    function getCookie(name) {
>> 
>>    }
>> }
>> 
>> // ...
>> 
>> if (getCookie('tpar')) {
>>    var irStartTime = new Date().getTime();
>>    window.attachEvent('onunload', irTimeStat); }
>> 
>> ## Scenario
>> Unknown, possibly just for tracking purposes.
>> 
>> 
>> # Google +1 library (only seen on TMZ.com, possibly this lib is out of date) try {
>>    function h(a) {
>>        throw a;
>>    }
>>    // plus a ton of other decls
>> } catch (e) { }
>> 
>> try {
>>    h(Error("foo"));
>>    // plus a ton of calls to other block scoped functions } catch (e) { }
>> 
>> ## Scenario
>> 
>> Plus one button is broken.
>> 
>> 
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
> 
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
> 



More information about the es-discuss mailing list