Cannot convert a BigInt value to a number

When my project is packaged into the subnet, an error message appears

{
                 key: "covariant",
                 value: function(A) {
                 -> var t = Math.pow(BigInt(2), BigInt(this._bits-1)) * BigInt(-1)
                 ->, e = Math.pow(BigInt(2), BigInt(this._bits-1))-BigInt(1);
                     if ("bigint" === typeof A)
                         return A >= t && A <= e;
                     if (Number.isInteger(A)) {
                         var n = BigInt(A);
                         return n >= t && n <= e
                     }
                     return !1
                 }
            

WX20210624-101357

Uncaught (in promise) TypeError: Cannot convert a BigInt value to a number

I think when using Math, BigInt format should not be passed in as a parameter

Math.pow doesn’t support bigints.

If you wanna compute x to the power of y, you need to do x ** y.

Funny enough, x ** y doesn’t work in React Native, so I think I’ll have to implement my own pow function for bigints.

Tried to rewrite the pow function, but caused other errors,

//This is a simple rewritten pow method
Math.pow = (...arg)=>{
     for(let z of arg){
         if (typeof z === "bigint"){
             z = Number(z);
         }
     }
     return pow(arg[0], arg[1]);
}
function pow(x, n) {
     let result = x;
  
     for (let i = 1; i <n; i++) {
       result *= x;
     }
  
     return result;
   }

WX20210624-102813

This kind of error makes me very confused. I don’t know if it is the reason after babel is packaged, or the problem of dfinity package package after package.

It’s a babel problem, it converts ** to .pow in the idl.js file (under the covariant functions)

1 Like

Fascinating… so I guess OP is trying to transpile to a much older JS version

At a certain point, it might be worth it to have a dedicated native-js package without BigInt, TextEncoder, or other assumptions from the browser/node package

1 Like

I manually edited the idl.js file in the node_modules/@dfinity/agent/lib dir and switched the use of ** to a switch statement - it’s to determine if a given variable is within the bounds of the bit type etc. Bound to be simpler ways though (I couldn’t get babel skipping @babel/plugin-transform-exponentiation-operator disabled tho, which is the babel plugin causing the issues - probably the best solution).

2 Likes

How does exponentiation translate to a switch?

Oh wait, @avi never said that they’re targeting React Native. If you are encountering the Math.pow error, consider updating your target ES version to ES2020. We don’t officially support anything older than that. Depending on your setup, that will be a tsconfig or browserslist update. We had that issue in GitHub - dfinity/cancan: A scalable video sharing service. and now have working configurations

2 Likes

Mine is a React Web project, I try to force configuration to use ES2020 under babel

Try adding

"browserslist": {
      "last 2 chrome version",
      "last 2 firefox version",
      "last 2 safari version",
      "last 2 edge version"
},

to your package.json

1 Like
        switch(this.bits){
            case 8:
              max = 256n;
              break;
            case 16:
              max = 65536n;
              break;
            case 32:
              max = 4294967296n;
              break;
            case 64:
              max = 18446744073709551616n;
         }

as opposed to the way it does it:

const max = 2 ** (this.bits);

Thank you, you just saved me a migraine.

1 Like