npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

bigint-lib

v1.1.0

Published

Use BigInt in library code, whether native or polyfilled

Downloads

13

Readme

Build Status codecov HitCount dependencies

bigint-lib

Use BigInt in library code, whether native or polyfilled.


Installation

npm install --save bigint-lib

Usage

If polyfilling, polyfill BigInt first.

Then,

import {bigIntLib} from "bigint-lib";

/**
 * `true` if natively supported; `false` otherwise
 */
bigIntLib.isNativelySupported();

/**
 * `true` if considered a `BigInt`
 */
bigIntLib.isBigInt(x);

/**
 * Creates a `BigInt` instance
 */
bigIntLib.BigInt(0);

See API for more details

Since this library is meant for library authors, reading the source code to understand how it works internally is recommended.


Motivation

Not all browsers support BigInt natively.

https://caniuse.com/#feat=mdn-javascript_builtins_bigint


Application code can use polyfills for BigInt easily.

https://github.com/GoogleChromeLabs/jsbi


However, libraries cannot assume that BigInt is natively supported, or polyfilled.

A library has to check.

If it is natively supported, we can use BigInt and all built-in operations directly.

If it is polyfilled, we cannot assume the shape of the exposed API for built-in operations.

Is addition done with x.add(y)? Or Polyfill.add(x, y)? Or x.plus(y)? Is it even implemented at all?

What about every other operation?


This library provides a unified API for all built-in BigInt operations, regardless of whether BigInt is natively supported, or polyfilled.


How it works

This library's only dependency is jsbi.

We have three cases to handle,

  • BigInt is natively supported

    We use the built-in operations directly.

    This is the most efficient.

    See src/native.ts for more details.

  • BigInt is polyfilled using jsbi

    We use jsbi for built-in operations.

    This is still pretty efficient.

    See src/jsbi-polyfill.ts for more details.

  • BigInt is polyfilled using some other library

    We convert the other library's BigInt to JSBI, use jsbi for built-in operations, and convert the result back to the other libary's BigInt.

    This is the least efficient, but saves us from having to worry about the exposed API of the other library.

    See src/non-jsbi-polyfill.ts for more details.


Expected Polyfill

This library assumes polyfills conform to some minimal API.


Polyfill with JSBI

To polyfill using jsbi,

import JSBI from "jsbi";
global.BigInt = JSBI.BigInt;

At the moment, using jsbi+TypeScript with esModuleInterop:false may cause the import to fail during run-time.

You may set esModuleInterop:true to fix the problem. However, setting esModuleInterop:true may cause other imports to fail.

You may choose to keep esModuleInterop:false and change the import to,

import {JSBI} from "bigint-lib/dist/jsbi";
global.BigInt = JSBI.BigInt;

Polyfill with Other Library

If polyfilling with some other library, the library must, minimally, have the following API,

class MyPolyfill {
    constructor (mixed : any) {
        //snip https://tc39.es/ecma262/#sec-bigint-constructor
    }

    toString () {
        return //snip base-10 string
    }
}
global.BigInt = (mixed : any) => new MyPolyfill(mixed);

The polyfill must also satisfy the following properties,

BigInt(0) instanceof MyPolyfill
> true
Object.getPrototypeOf(BigInt(0)).constructor === MyPolyfill
> true

API

The following are exported by this library,


BigIntLib

The interface is mostly the same as jsbi's

| Operation | native BigInt | bigint-lib | Note |---|---|---|---| |Creation from String | a = BigInt("456") | a = biLib.BigInt("456") |Creation from Number | a = BigInt(789) | a = biLib.BigInt(789) |Creation from BigInt | a = BigInt(a) | a = biLib.BigInt(a) |Conversion to String | a.toString(radix) | biLib.toString(a, radix) | radix defaults to 10; must be in [2, 36] |Conversion to Number | Number(a) | biLib.toNumber(a) | May result in precision loss |Truncation | BigInt.asIntN(width, a) | biLib.asIntN(width, a) | Throws if width is negative | | BigInt.asUintN(width, a) | biLib.asUintN(width, a) | Throws if width is negative |Type check | typeof a === "bigint" | biLib.isBigInt(a) |Native BigInt check | typeof BigInt(0) === "bigint" | biLib.isNativelySupported()


| Operation | native BigInt | bigint-lib | Note |---|---|---|---| |Arithmetic | | |Unary minus | b = -a | b = biLib.unaryMinus(a) |Addition | c = a + b | c = biLib.add(a, b) |Subtraction | c = a - b | c = biLib.subtract(a, b) |Multiplication | c = a * b | c = biLib.multiply(a, b) |Division | c = a / b | c = biLib.divide(a, b) | Throws if b is zero |Remainder | c = a % b | c = biLib.remainder(a, b) | Throws if b is zero |Exponentiation | c = a ** b | c = biLib.exponentiate(a, b) | Throws if b is negative |Bitwise | | |Left-shift | c = a << b | c = biLib.leftShift(a, b) | Allows negative shift |Signed right-shift | c = a >> b | c = biLib.signedRightShift(a, b) | Allows negative shift |Bitwise NOT | b = ~a | c = biLib.bitwiseNot(a) |Bitwise AND | c = a & b | c = biLib.bitwiseAnd(a, b) |Bitwise OR | c = a \| b | c = biLib.bitwiseOr(a, b) |Bitwise XOR | c = a ^ b | c = biLib.bitwiseXor(a, b) |Comparison | a == b | biLib.equal(a, b) | | a != b | biLib.notEqual(a, b) | | a < b | biLib.lessThan(a, b) | | a <= b | biLib.lessThanOrEqual(a, b) | | a > b | biLib.greaterThan(a, b) | | a >= b | biLib.greaterThanOrEqual(a, b) |Unsupported | | |Literals | a = 123n | N/A |Increment | a++/++a | N/A | | a + 1n | biLib.add(a, biLib.BigInt(1)) |Decrement | a--/--a | N/A | | a - 1n | biLib.subtract(a, biLib.BigInt(1))


nativeOrJsbiLib

If global.BigInt is natively supported, returns nativeBigIntLib. Otherwise, returns jsbiPolyfillBigIntLib.

This is useful for libraries that need to perform many complex BigInt operations before returning a result.


import {bigIntLib, nativeOrJsbiLib} from "bigint-lib";

const my1 = nativeOrJsbiLib.BigInt(1);

//Takes native or JSBI polyfilled bigints
//Will return a native or JSBI polyfilled bigint
function myComplexFunctionImpl (m : bigint, n : bigint) : bigint {
    if (nativeOrJsbiLib.equal(m, 0)) {
        return nativeOrJsbiLib.add(n, my1);
    }
    if (nativeOrJsbiLib.equal(n, 0)) {
        return myComplexFunctionImpl(
            nativeOrJsbiLib.subtract(m, my1),
            my1
        );
    }
    return myComplexFunctionImpl(
        nativeOrJsbiLib.subtract(m, my1),
        myComplexFunctionImpl(m, nativeOrJsbiLib.subtract(n, 1))
    );
}

//Takes native, JSBI polyfilled, or other polyfilled bigints
//Must return a `bigint` that may be native, polyfilled with JSBI, or polyfilled with other libraries
function myComplexFunction (m : bigint, n : bigint) : bigint {
    //Will be a native or JSBI polyfilled `bigint`
    const myM = nativeOrJsbiLib.BigInt(m.toString());
    const myN = nativeOrJsbiLib.BigInt(n.toString());
    const myResult = myComplexFunctionImpl(myM, myN);

    //Convert the result to a `bigint` type the same as its input
    return bigIntLib.BigInt(myResult.toString());
}

Using nativeOrJsbiLib saves the time needed to convert between JSBI and other polyfill libraries, if other polyfill libraries are used.


Polyfilling with node

  1. Have your polyfill code in a .js file.
  2. node -r my-polyfill.js my-entry-point.js

Polyfilling with ts-node

  1. Have your polyfill code in a .ts file.
  2. ts-node -r my-polyfill.ts my-entry-point.ts

Development

  1. git clone https://github.com/AnyhowStep/bigint-lib.git
  2. npm install
  3. npm run sanity-check to build and run tests.
  4. npm run to see a list of commands.