Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Uncaught (in promise) TypeError in e.Index.load in Chrome Canary / Chrome v132 #540

Open
surajsharma opened this issue Jan 11, 2025 · 4 comments

Comments

@surajsharma
Copy link

surajsharma commented Jan 11, 2025


Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'id')
    at e.TokenSet.toString (lunr.js:7:13980)
    at e.TokenSet.Builder.minimize (lunr.js:7:15583)
    at e.TokenSet.Builder.insert (lunr.js:7:15031)
    at e.Index.load (lunr.js:7:19374)
    at loadSearchIndex (search.js?v=1736601832:190:24)
    at search.js?v=1736601832:258:45

Chrome canary latest nightly, works fine elsewhere.

@surajsharma surajsharma changed the title Uncaught (in promise) TypeErro in e.Index.load in Chrome Canary Uncaught (in promise) TypeError in e.Index.load in Chrome Canary Jan 14, 2025
@bukowskiadam
Copy link

bukowskiadam commented Jan 20, 2025

Hey, I got exactly same issue, but not in Chrome Canary, but in Chrome v132. I suggest changing the title of the issue as it might affect more people now. I nailed it down to chrome not liking the very big, plan JS objects. Replacing some internal code to use JS Map makes it working.

Replace this internal function with the one provided below:

lunr.TokenSet.Builder.prototype.minimize = function (downTo) {
for (var i = this.uncheckedNodes.length - 1; i >= downTo; i--) {
var node = this.uncheckedNodes[i],
childKey = node.child.toString()
if (childKey in this.minimizedNodes) {
node.parent.edges[node.char] = this.minimizedNodes[childKey]
} else {
// Cache the key for this node since
// we know it can't change anymore
node.child._str = childKey
this.minimizedNodes[childKey] = node.child
}
this.uncheckedNodes.pop()
}
}

This is ours fixed lunr implementation (fixing some other bug + this one)

import lunr from 'lunr';

declare global {
  namespace lunr {
    interface TokenSet {
      _str: string;
      final: boolean;
      edges: Record<string, lunr.TokenSet>;
      id: number;
    }
  }
}

/**
 * This is a workaround for a bug in the lunr library described in this issue,
 * which also provides a solution that works for us:
 * https://github.com/olivernn/lunr.js/issues/503
 */
lunr.TokenSet.prototype.toString = function () {
  if (this._str) {
    return this._str;
  }

  var str = this.final ? '1' : '0',
    labels = Object.keys(this.edges).sort(),
    len = labels.length;

  for (var i = 0; i < len; i++) {
    var label = labels[i],
      node = this.edges[label];

    str = str + ', L(' + label + ')I(' + node.id + ')';
  }

  return str;
};

/**
 * Reimplement internal function to use `new Map()`, instead of the `{}` object.
 * https://github.com/olivernn/lunr.js/blob/aa5a878f62a6bba1e8e5b95714899e17e8150b38/lib/token_set_builder.js#L52-L69
 * Because of this issue in Chrome v132 and newer:
 * https://github.com/olivernn/lunr.js/issues/540
 */
// @ts-expect-error I had a problem how to defined Builder type, so just ignore it
lunr.TokenSet.Builder.prototype.minimize = function (downTo: number) {
  if (!(this.minimizedNodes instanceof Map)) {
    this.minimizedNodes = new Map(Object.entries(this.minimizedNodes));
  }

  for (var i = this.uncheckedNodes.length - 1; i >= downTo; i--) {
    var node = this.uncheckedNodes[i],
      childKey = node.child.toString();

    if (this.minimizedNodes.has(childKey)) {
      node.parent.edges[node.char] = this.minimizedNodes.get(childKey);
    } else {
      // Cache the key for this node since
      // we know it can't change anymore
      node.child._str = childKey;

      this.minimizedNodes.set(childKey, node.child);
    }

    this.uncheckedNodes.pop();
  }
};

export default lunr;

Please, let me know if it fixes the problem for you.

Maybe it should be applied in the core code as Map is widely supported.

@surajsharma surajsharma changed the title Uncaught (in promise) TypeError in e.Index.load in Chrome Canary Uncaught (in promise) TypeError in e.Index.load in Chrome Canary / Chrome v132 Jan 25, 2025
@surajsharma
Copy link
Author

@bukowskiadam thanks for your response, however i have stuff in production i don't want to mess around with unless you plan to incorporate this fix into an offical release.

@bukowskiadam
Copy link

Hey, I think it's not needed anymore. Chrome got it fixed in the most recent version. It turned out it's a Chrome issue with objects.
https://issues.chromium.org/issues/390568195

@surajsharma
Copy link
Author

@bukowskiadam i knew it! thanks anyway!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants