electric-sql / electric-sql/pglite
PgliteWorker: Failed to execute 'postMessage' on Number(value) // and BigDecimal(value)
- Dominant language
- TypeScript
- Stars
- 16k
- Forks
- 442
- Avg merge
- 20h 19m
- Merged PRs (30d)
- 7
Description
```
Uncaught (in promise) DataCloneError: Failed to execute 'postMessage' on 'Worker': (value) => {
return Number(value);
} could not be cloned.
at F.K (index.ts:160:26)
at async F.create (index.ts:281:3)
```
I am using PGliteWorker and am trying to parse Numerics into Number. I have a class called BigDecimal that I would prefer to use (added below). Whenever I try to use either of them, I get an error as above.
These are the relevant issues I saw, but don't see a fix in them: https://github.com/electric-sql/pglite/issues?q=postMessage.
> Main thread
```
import PGWorker from "components/pg-lite/pglite-worker?worker";
void PGliteWorker.create(
new PGWorker({
name: "pglite-worker",
}),
{
parsers: {
[types.NUMERIC]: (value) => {
// console.log("Parsing NUMERIC value:", value);
return Number(value);
},
},
extensions: {
live,
vector,
electric: electricSync(),
},
},
)
```
> Worker
```
import { PGlite, PGliteInterfaceExtensions, types } from "@electric-sql/pglite";
import { electricSync } from "@electric-sql/pglite-sync";
import { live } from "@electric-sql/pglite/live";
import { OpfsAhpFS } from "@electric-sql/pglite/opfs-ahp";
import { vector } from "@electric-sql/pglite/vector";
import { PGliteWorker, worker } from "@electric-sql/pglite/worker";
export type CustomPGlite = PGliteWorker &
PGliteInterfaceExtensions<{
live: typeof live;
vector: typeof vector;
electric: ReturnType;
}>;
void worker({
async init() {
// Create and return a PGlite instance
const pg = await PGlite.create({
fs: new OpfsAhpFS("pglite-db", {}),
extensions: {
live,
vector,
electric: electricSync(),
},
});
return pg;
},
});
```
> BigDecimal
I tried making `#n` not private like `n` but the error remained.
```
export class BigDecimal {
// Configuration: private constants
private static readonly DECIMALS: number = 18; // Number of decimals on all instances
private static readonly ROUNDED: boolean = true; // Numbers are truncated (false) or rounded (true)
private static readonly SHIFT: bigint = 10n ** BigInt(BigDecimal.DECIMALS); // Derived constant
private static readonly fromBigInt: unique symbol = Symbol(); // Secret to allow construction with given #n value
public static get ZERO(): BigDecimal {
return new BigDecimal(0);
}
#n: bigint; // the BigInt that holds the BigDecimal's value multiplied by SHIFT
constructor(
value: string | number | BigDecimal | bigint,
convert?: typeof BigDecimal.fromBigInt,
) {
if (value instanceof BigDecimal) {
this.#n = value.#n;
return;
}
if (convert === BigDecimal.fromBigInt) {
this.#n = BigInt(value);
return;
}
const str = String(value);
const [ints, decis = ""] = str.split(".");
const padded = decis
.padEnd(BigDecimal.DECIMALS, "0")
.slice(0, BigDecimal.DECIMALS);
const base = BigInt(ints + padded);
const roundIncrement =
// @ts-expect-error
BigDecimal.ROUNDED && decis[BigDecimal.DECIMALS] >= "5" ? 1n : 0n;
this.#n = base + roundIncrement;
}
add(num: string | number | BigDecimal): BigDecimal {
const other = new BigDecimal(num);
const sum = this.#n + other.#n;
return new BigDecimal(sum, BigDecimal.fromBigInt);
}
subtract(num: string | number | BigDecimal): BigDecimal {
const other = new BigDecimal(num);
const diff = this.#n - other.#n;
return new BigDecimal(diff, BigDecimal.fromBigInt);
}
private static divRound(dividend: bigint, divisor: bigint): BigDecimal {
const quotient = dividend / divisor;
const remainder = dividend % divisor;
const shouldRound = BigDecimal.ROUNDED && remainder * 2n >= divisor;
return new BigDecimal(
quotient + (shouldRound ? 1n : 0n),
BigDecimal.fromBigInt,
);
}
multiply(num: string | number | BigDecimal): BigDecimal {
const other = new BigDecimal(num);
const product = this.#n * other.#n;
return BigDecimal.divRound(product, BigDecimal.SHIFT);
}
divide(num: string | number | BigDecimal): BigDecimal {
const other = new BigDecimal(num);
const scaled = this.#n * BigDecimal.SHIFT;
return BigDecimal.divRound(scaled, other.#n);
}
toString(): string {
const negative = this.#n < 0n;
let s = this.#n
.toString()
.replace("-", "")
.padStart(BigDecimal.DECIMALS + 1, "0");
s = s
.slice(0, -BigDecimal.DECIMALS)
.concat(".")
.concat(s.slice(-BigDecimal.DECIMALS))
.replace(/(\.0*|0+)$/, "");
return negative ? "-" + s : s;
}
toNumber(): number {
return Number(this.toString());
}
}
```
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.