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

Expose utility function to enable bigint serialization in consumer apps #1706

Merged
merged 3 commits into from
Sep 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion apps/demo/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import './styles.css'; // global styles

import { assertNonNull } from '@h5web/app';
import { assertNonNull, enableBigIntSerialization } from '@h5web/app';
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';

import DemoApp from './DemoApp';

enableBigIntSerialization(); // for `RawVis` and `MetadataViewer`

const rootElem = document.querySelector('#root');
assertNonNull(rootElem);

Expand Down
Binary file modified cypress/snapshots/app.cy.ts/bgr_image.snap.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified cypress/snapshots/app.cy.ts/compound_1D.snap.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified cypress/snapshots/app.cy.ts/heatmap_2D.snap.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified cypress/snapshots/app.cy.ts/heatmap_2D_complex.snap.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified cypress/snapshots/app.cy.ts/heatmap_2D_inverted_cmap.snap.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified cypress/snapshots/app.cy.ts/heatmap_4d_default.snap.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified cypress/snapshots/app.cy.ts/heatmap_4d_remapped.snap.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified cypress/snapshots/app.cy.ts/heatmap_4d_sliced.snap.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified cypress/snapshots/app.cy.ts/heatmap_4d_zeros.snap.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified cypress/snapshots/app.cy.ts/heatmap_domain.snap.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified cypress/snapshots/app.cy.ts/line_1D.snap.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified cypress/snapshots/app.cy.ts/line_complex_1D.snap.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified cypress/snapshots/app.cy.ts/matrix_1D.snap.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified cypress/snapshots/app.cy.ts/rgb_image.snap.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
38 changes: 38 additions & 0 deletions packages/app/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,44 @@ import { getFeedbackMailto } from '@h5web/app';
}} />
```

#### `enableBigIntSerialization`

Invoke this function before rendering your application to allow the _Raw_
visualization and metadata inspector to serialize and display
[big integers](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#bigint_type):

```jsx
enableBigIntSerialization();
createRoot(document.querySelector('#root')).render(<MyApp />);
```

This is recommended if you work with a provider that supports 64-bit integers —
i.e. one that may provide dataset and attribute values that include primitive
`bigint` numbers — currently only [`MockProvider`](#mockprovider).

The _Raw_ visualization and metadata inspector rely on `JSON.stringify()` to
render dataset and attribute values. By default, `JSON.stringify()` does not
know how to serialize `bigint` numbers and throws an error if it encounters one.
`enableBigIntSerialization()` teaches `JSON.stringify()` to convert big integers
to strings:
axelboc marked this conversation as resolved.
Show resolved Hide resolved

```js
> JSON.stringify(123n);
TypeError: Do not know how to serialize a BigInt

> enableBigIntSerialization();
> JSON.stringify(123n);
"123n"
```

> The `n` suffix (i.e. the same suffix used for `bigint` literals as
> demonstrated above) is added to help distinguish big integer strings from
> other strings.

> If you're application already implements `bigint` serialization, you don't
> need to call `enableBigIntSerialization()`. Doing so would override the
> existing implementation, which might have unintended effects.

### Context

The viewer component `App` communicates with its wrapping data provider through
Expand Down
1 change: 1 addition & 0 deletions packages/app/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export { default as MockProvider } from './providers/mock/MockProvider';
export { default as HsdsProvider } from './providers/hsds/HsdsProvider';
export { default as H5GroveProvider } from './providers/h5grove/H5GroveProvider';

export { enableBigIntSerialization } from './utils';
export { getFeedbackMailto } from './breadcrumbs/utils';
export type { FeedbackContext } from './breadcrumbs/models';
export type { ExportFormat, ExportURL } from './providers/models';
Expand Down
7 changes: 7 additions & 0 deletions packages/app/src/providers/mock/mock-file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ export function makeMockFile(): GroupWithChildren {
scalar('raw_large', undefined), // generated dynamically by `MockProvider`
dataset('raw_png', opaqueType(), [], PNG_RED_DOT),
scalar('scalar_num', 0, { attributes: [scalarAttr('attr', 0)] }),
scalar('scalar_bigint', BigInt(Number.MAX_SAFE_INTEGER) + 1n, {
attributes: [
scalarAttr('attr', BigInt(Number.MAX_SAFE_INTEGER) + 1n),
],
}),
scalar('scalar_str', 'foo', {
attributes: [scalarAttr('attr', 'foo')],
}),
Expand Down Expand Up @@ -108,6 +113,7 @@ export function makeMockFile(): GroupWithChildren {
group('nD_datasets', [
array('oneD_linear'),
array('oneD'),
array('oneD_bigint'),
array('oneD_cplx'),
array('oneD_compound', {
type: printableCompoundType({
Expand All @@ -121,6 +127,7 @@ export function makeMockFile(): GroupWithChildren {
array('oneD_bool'),
array('oneD_enum', { type: enumType(uintType(8), ENUM_MAPPING) }),
array('twoD'),
array('twoD_bigint'),
array('twoD_cplx'),
array('twoD_compound', {
type: printableCompoundType({
Expand Down
10 changes: 10 additions & 0 deletions packages/app/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,13 @@ import type { AttrName } from './providers/models';
export function hasAttribute(entity: Entity, attributeName: AttrName) {
return entity.attributes.some((attr) => attr.name === attributeName);
}

export function enableBigIntSerialization(): void {
// eslint-disable-next-line no-extend-native
Object.defineProperty(BigInt.prototype, 'toJSON', {
configurable: true,
value: function toJSON(this: bigint) {
return `${this.toString()}n`;
},
});
}
15 changes: 15 additions & 0 deletions packages/shared/src/mock-values.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ const range9 = () => range(1, 11);

const oneD = () => ndarray(range1().map((val) => val ** 2));

const oneD_bigint = () =>
ndarray(
range8().map((_, i) => BigInt(Number.MAX_SAFE_INTEGER) + BigInt(i - 5)),
loichuder marked this conversation as resolved.
Show resolved Hide resolved
);

const oneD_bool = () =>
ndarray([true, false, false, true, true, true, false, true, false, false]);

Expand Down Expand Up @@ -89,6 +94,7 @@ const threeD_rgb = () =>
export const mockValues = {
oneD,
oneD_linear: () => ndarray(range1()),
oneD_bigint,
oneD_cplx,
oneD_compound,
oneD_bool,
Expand All @@ -103,6 +109,15 @@ export const mockValues = {
shapeTwoD,
);
},
twoD_bigint: () => {
const { data: dataOneDBigInt } = oneD_bigint();
return ndarray(
range5().flatMap((_, i) =>
dataOneDBigInt.map((val) => val + 1n + BigInt(i) * 10n),
),
[3, 5],
);
},
twoD_cplx: () =>
ndarray(
[
Expand Down