Thursday, 5 March 2020

Error when using ajax.js (Commerce) and JSON.parse

I found an issue today with the ajax.js file that comes with Sitecore Commerce in Sitecore 9.2.  

I was trying to get a third party js component (Chute) working in Sitecore which loads scripts dynamically, but the component wouldn't display any content.  This particular component displays images in either a carousel or grid.  But after the initial load nothing appeared except for an error in my browser console:

TypeError: data is null  ajax.js:  156:24


This same component worked without any issue, in a non-commerce environment.

After some investigations, it became apparent that the issue was down to the fact that someone at Sitecore had decided to replace the standard JSON.parse function with a function of their own and had forgotten to do a null check inside that function.  I know that as developer we all do this...  I want to highlight the issue, to save someone some grief when trying to figure out what is going on...

The file in question can be found in the Sitecore content tree here: /sitecore/media library/Base Themes/Commerce Services Theme/Scripts/ajax

Once you down load the media content you will get a script called ajax.js.

The offending code @ line 156, can be found just after the JSON.parse equals statement in the block of code shown below:

(function (root, factory) {
    'use strict';
    if (typeof define === 'function' && define.amd) {
      // use AMD define funtion to support AMD modules if in use
      define(['exports'], factory);
    } else if (typeof exports === 'object') {
      // to support CommonJS
      factory(exports);
    }

    // browser global variable
    var AjaxService = {};
    root.AjaxService = AjaxService;
    factory(AjaxService);
  })(this, function (AjaxService) {
    'use strict';

    // Hack >>
    // When debugging is on, Sitecore is returning extra information, we need to strip it from the JSON string
    var jsonParseRef = JSON.parse;

    JSON.parse = function (data) {

      var debugIndex = data.indexOf('<div title="Click here to view the profile."');
      if (debugIndex > 0) {
        data = data.substring(debugIndex, 0, debugIndex);
      }

      return jsonParseRef(data);
    };



You will see in the above function that JSON.parse is updated with a new function, unfortunately the data variable is not checked for null before being used.

Changing the JSON.parse function to: 

JSON.parse = function (data) {

      if(data==null)return null;

      var debugIndex = data.indexOf('<div title="Click here to view the profile."');

      if (debugIndex > 0) {
        data = data.substring(debugIndex, 0, debugIndex);
      }

      return jsonParseRef(data);
    };

What worries me slightly is the commentary in the file, where it says 'hack', this suggests to me that perhaps this js file is not ready for production use.

Hopefully this might help someone.