I recently found a bug in one of my codeplex projects Export Version History. A user was able to see the Export Version History option in Edit Control block aka ECB menu even if the user did not have ViewVersions permissions.

ECB Menu

Notice that in the above screenshot 'Export Version History' menu item is available whereas the out of the box 'Version History' menu item is correctly not available as current user does not have ViewVersions permissions. Also note that versioning is on in the list. 
One of my previous posts shows how a delegate control can be used to conditionally show menu item in ECB Menu. Time to revisit that code and see how this bug can be fixed. Following is the code from that post. It checks verEnabled property of Out of the box ctx object and if it is present it shows the ECB menu.
<script type="text/javascript">
    function Custom_AddListMenuItems(m, ctx) {
        AddECBMenuItems(m, ctx);  
    }

    function Custom_AddDocLibMenuItems(m, ctx) {
        AddECBMenuItems(m, ctx);
    }

    function AddECBMenuItems(m, ctx) {
        var pageUrl = ctx.HttpRoot + "/_layouts/NY.ExportVersionHistory/ExportVersionHistory.aspx?ID=" + currentItemID + "&amp;List=" + ctx.listName;
        if (ctx.verEnabled) {
            CAMOpt(m, "Export Version History", "window.open('" + pageUrl + "');", "/_layouts/images/NY.ExportVersionHistory/Excel_Small.png");
            CAMSep(m);
        }
    }
</script>
Now we need to check whether current user has ViewVersions permissions on the current item. So, I thought of writing the code in SharePoint JavaScript client object model. As client object model code runs asynchronously, it was obvious that ECB menu will be rendered before the async call is completed. Therefore, I started to write client object model code using JQuery deferred/Promises and came up with the following code:
function AddECBMenuItems(m, ctx) {
    var pageUrl = ctx.HttpRoot + "/_layouts/NY.ExportVersionHistory/ExportVersionHistory.aspx?ID=" + currentItemID + "&amp;List=" + ctx.listName;
    getItemPermissions(ctx.listName, currentItemID).then(
    function (permissions) {
        if (permissions.has(SP.PermissionKind.viewVersions)) {
            if (ctx.verEnabled) {
                CAMOpt(m, "Export Version History", "window.open('" + pageUrl + "');", "/_layouts/images/NY.ExportVersionHistory/Excel_Small.png");
                CAMSep(m);
            }
        }
    },
    function (sender, args) {
        console.log('An error occured while retrieving list item:' + args.get_message());
    });    
}

var getItemPermissions = function (listId, itemId) {
    var deferred = $.Deferred();
    var context = SP.ClientContext.get_current();
    var web = context.get_web();
    var list = web.get_lists().getById(listId);
    var item = list.getItemById(itemId);
    context.load(item, 'EffectiveBasePermissions');
    context.executeQueryAsync(
       Function.createDelegate(this,
           function () {
               var permissions = item.get_effectiveBasePermissions();
               deferred.resolve(permissions);
           }),
       Function.createDelegate(this,
           function (sender, args) { deferred.reject(sender, args); }));

    return deferred.promise();
};
Putting above code to test, I was surprised to see that that Export Version History menu item was not available even if the list had versioning enabled and current user had ViewVersions permissions on the list item. It turns out that ECB menu is immediately rendered as can be seen from the following screenshot. By the time code in the if statement is hit, ECB is already created.

But the question is how come OOB Version History is working properly. The answer to this question is present in SharePoint JavaScript file CORE.js. This file contains functions for creating ECB and it resides in Layouts folder. open the debug version of this file named CORE.debug.js as opposed to minified version as reading the latter file can be difficult. Find a function named AddVersionsMenuItem. This function is used by SharePoint to decide whether to show OOB Version History menu item or not. Here is the code of this function.
function AddVersionsMenuItem(m, ctxt, url) {
    if (currentItemID != null) {
        var strCurrentItemID = currentItemID.toString();

        if (strCurrentItemID.indexOf(".0.") >= 0)
            return;
    }
    var fixedItemId = currentItemID;

    if (currentItemIsEventsExcp) {
        if (currentItemID.indexOf(".") != -1)
            fixedItemId = (currentItemID.split("."))[0];
    }
    if (!HasRights(0x0, 0x40))
        return;
    var strDisplayText = Strings.STS.L_Versions_Text;
    var strAction = "NavigateToVersionsAspxV4(event, '" + ctxt.HttpRoot + "', 'list=" + ctxt.listName + "&ID=" + fixedItemId + "&FileName=" + url + "')";
    var strImagePath = ctxt.imagesPath + "versions.gif";
    var menuOption = CAMOpt(m, strDisplayText, strAction, strImagePath, null, String(800));

    CUIInfo(menuOption, "ViewVersions", ["ViewVersions"]);
    menuOption.id = "ID_Versions";
}
As can be see a call is made to HasRights function with two parameters. The first parameter is a hex representation of EmptyMask permission and second is the hex representation of ViewVersions.   
This page has hex and decimal values of SharePoint base permissions. So the simple change which needs to be done in order to fix the bug is to make a call to HasRights function to check the permissions. 
Finally, the updated code:
<script type="text/javascript">
    function Custom_AddListMenuItems(m, ctx) {
        AddECBMenuItems(m, ctx);  
    }

    function Custom_AddDocLibMenuItems(m, ctx) {
        AddECBMenuItems(m, ctx);
    }

    function AddECBMenuItems(m, ctx) {
        var pageUrl = ctx.HttpRoot + "/_layouts/NY.ExportVersionHistory/ExportVersionHistory.aspx?ID=" + currentItemID + "&amp;List=" + ctx.listName;
        if (ctx.verEnabled && HasRights(0x0, 0x40)) {
            CAMOpt(m, "Export Version History", "window.open('" + pageUrl + "');", "/_layouts/images/NY.ExportVersionHistory/Excel_Small.png");
            CAMSep(m);
        }
    }
</script>

SharePoint 2013 has an object called WPQ2FormCtx which holds plenty of useful information about the List and List Item in List pages like DisplayForm.aspx, EditForm.aspx and NewForm.aspx. I needed to know whether versioning is enabled in a list in the displayform of a list item. 
I did not want to write any JavaScript object model code to check that. Since display form already has Version History button which is either enabled or disabled based on whether versioning is enabled or not; I thought that this information must be available out of the box. I opened IE developer tools and started looking for this information. 
I found WPQ2FormCtx object and surprisingly it contains lots of useful information. WPQ2FormCtx.ListAttributes contains information about the list. Here I found EnableVersioning property as can be seen in the screenshot:

List Attributes

It also has ListData and ListSchema properties. ListData contains the data of the fields whereas ListSchema has the information about the type of fields. Here is the screenshot of ListData.

List Data

Similarly, it has several other important properties like ItemAttributes, ItemContentTypeId, ItemContentTypeName and even WebAttributes which contains information about the parent web object.

My SharePoint CodePlex Projects

SharePoint 2010 Autocomplete Lookup Field

Export Version History Of SharePoint 2010 List Items to Microsoft Excel.