Script Preparation code:
x
 
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var getObjectKeys = Object.keys;
var __objRest = (source, exclude) => {
  var target = {};
  for (var prop in source)
    if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
      target[prop] = source[prop];
  if (source != null && __getOwnPropSymbols)
    for (var prop of __getOwnPropSymbols(source)) {
      if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
        target[prop] = source[prop];
    }
  return target;
};
var GlobalContextName = /* @__PURE__ */ ((GlobalContextName2) => {
  GlobalContextName2["ApplicationContext"] = "ApplicationContext";
  GlobalContextName2["CookieIdContext"] = "CookieIdContext";
  GlobalContextName2["HttpContext"] = "HttpContext";
  GlobalContextName2["IdentityContext"] = "IdentityContext";
  GlobalContextName2["InputValueContext"] = "InputValueContext";
  GlobalContextName2["LocaleContext"] = "LocaleContext";
  GlobalContextName2["MarketingContext"] = "MarketingContext";
  GlobalContextName2["PathContext"] = "PathContext";
  GlobalContextName2["SessionContext"] = "SessionContext";
  return GlobalContextName2;
})(GlobalContextName || {});
var LocationContextName = /* @__PURE__ */ ((LocationContextName2) => {
  LocationContextName2["ContentContext"] = "ContentContext";
  LocationContextName2["ExpandableContext"] = "ExpandableContext";
  LocationContextName2["InputContext"] = "InputContext";
  LocationContextName2["LinkContext"] = "LinkContext";
  LocationContextName2["MediaPlayerContext"] = "MediaPlayerContext";
  LocationContextName2["NavigationContext"] = "NavigationContext";
  LocationContextName2["OverlayContext"] = "OverlayContext";
  LocationContextName2["PressableContext"] = "PressableContext";
  LocationContextName2["RootLocationContext"] = "RootLocationContext";
  return LocationContextName2;
})(LocationContextName || {});
var ContextNames = new Set([...Object.keys(LocationContextName), ...Object.keys(GlobalContextName)]);
var isAbstractContext = (context) => {
  if (typeof context !== "object" || context === null || context === void 0) {
    return false;
  }
  if (!context.__instance_id || !context._type || !context.id) {
    return false;
  }
  return ContextNames.has(context._type);
};
window.isContextEqual = (a, b) => {
  if (!isAbstractContext(a) || !isAbstractContext(b)) {
    return false;
  }
  const aKeys = getObjectKeys(a);
  const aLength = aKeys.length;
  if (aLength !== getObjectKeys(b).length) {
    return false;
  }
  for (let i = 0; i < aLength; i++) {
    if (!b.hasOwnProperty(aKeys[i])) {
      return false;
    }
  }
  for (let i = 0; i < aLength; i++) {
    const aKey = aKeys[i];
    if (a[aKey] !== b[aKey]) {
      return false;
    }
  }
  return true;
};
window.fdeq = function equal(a, b) {
    if (a === b) return true;
    if (a && b && typeof a == 'object' && typeof b == 'object') {
        if (a.constructor !== b.constructor) return false;
        var length, i, keys;
        if (Array.isArray(a)) {
            length = a.length;
            if (length != b.length) return false;
            for (i = length; i-- !== 0;)
                if (!equal(a[i], b[i])) return false;
            return true;
        }
        if ((a instanceof Map) && (b instanceof Map)) {
            if (a.size !== b.size) return false;
            for (i of a.entries())
                if (!b.has(i[0])) return false;
            for (i of a.entries())
                if (!equal(i[1], b.get(i[0]))) return false;
            return true;
        }
        if ((a instanceof Set) && (b instanceof Set)) {
            if (a.size !== b.size) return false;
            for (i of a.entries())
                if (!b.has(i[0])) return false;
            return true;
        }
        if (ArrayBuffer.isView(a) && ArrayBuffer.isView(b)) {
            length = a.length;
            if (length != b.length) return false;
            for (i = length; i-- !== 0;)
                if (a[i] !== b[i]) return false;
            return true;
        }
        if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;
        if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();
        if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();
        keys = Object.keys(a);
        length = keys.length;
        if (length !== Object.keys(b).length) return false;
        for (i = length; i-- !== 0;)
            if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;
        for (i = length; i-- !== 0;) {
            var key = keys[i];
            if (!equal(a[key], b[key])) return false;
        }
        return true;
    }
    // true if both NaN, false otherwise
    return a !== a && b !== b;
};
function shuffle(array) {
  let currentIndex = array.length,  randomIndex;
  // While there remain elements to shuffle.
  while (currentIndex != 0) {
    // Pick a remaining element.
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex--;
    // And swap it with the current element.
    [array[currentIndex], array[randomIndex]] = [
      array[randomIndex], array[currentIndex]];
  }
  return array;
}
window.contexts = [];
for(let i=0; i<10000;i++){
  window.contexts.push({__instance_id: crypto.randomUUID(), _type: 'PressableContext', id: i})
}
for(let i=0; i<10000;i++){
  window.contexts.push({__instance_id: crypto.randomUUID(), _type: 'PressableContext', id: i})
}
for(let i=0; i<10000;i++){
  window.contexts.push({__instance_id: crypto.randomUUID(), _type: 'PressableContext', id: i})
}
shuffle(window.contexts);
Tests:
  • isContextEqual

     
    const contexts = window.contexts;
    while(contexts.length){
      if(contexts.length > 1) {
        isContextEqual(contexts.pop(), contexts.pop())
      }
    }
  • fast-deep-equal

     
    const contexts = window.contexts;
    while(contexts.length){
      if(contexts.length > 1) {
        fdeq(contexts.pop(), contexts.pop())
      }
    }
Rendered benchmark preparation results:

Suite status: <idle, ready to run>

Previous results

Experimental features:

  • Test case name Result
    isContextEqual
    fast-deep-equal

    Fastest: N/A

    Slowest: N/A

Latest run results:
Run details: (Test run date: 2 years ago)
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36
Chrome 103 on Mac OS X 10.15.7
View result in a separate tab
Test name Executions per second
isContextEqual 11014536.0 Ops/sec
fast-deep-equal 11159724.0 Ops/sec